Jesper Olsen
Jesper Olsen

Reputation: 21

C - reading multiple file streams

Im writing my own simplified version of the classic UNIX program 'wc' (word count). It counts number of lines, words, and characters. All these features work fine. But where i run into trouble is when im trying to read multiple files from *argv[x]. I need to make every variable into an array, and run the whole process through loops to achieve what im looking for.

My program returns a segmentation fault. Something is not being assigned into the arrays at some point in the code, and i can't seem to figure out exactly where that is.

Any help is much appreciated :)

/*
 *      [PROGRAM]   wc (word count)
 *       [AUTHOR]   Jesper M. Olsen @ jm0.codes
 *         [DATE]   September 9th 2015
 *      [PURPOSE]   Returns number of lines, words, and characters in a file
 *
 *  [DESCRIPTION]   This program is meant to be utilized as a handy little browsing tool.
 *                  For instance, while moving through the filesystem of a programming archive,
 *                  just type 'wc <filename>' and you will get number of lines, words and characters returned promptly.
 */

#include <stdio.h>
#include <string.h>

int main(int argc, char *argv[])
{
    if (argc == 1)
        return -1;

    int numL[argc]; /* initialize array value placeholders */
    int numW[argc];
    int numC[argc];
    int getC[argc];
    int getW[argc];

    int setNull;
    for (setNull = 1; setNull <= argc-1; setNull++) { /* assign ZERO to value placeholders */
        numL[setNull] = 0;
        numW[setNull] = 0;
        numC[setNull] = 0;
        getW[setNull] = 0;
    }

    int x;
    FILE *fOp[argc-1];
    for (x = 1; x <= argc-1; x++) { /* open file stream for each file */
        fOp[x] = fopen(argv[x], "r");
        if (fOp[x] == NULL)
            return -1;
    }

        int y;
        for (y = 1; (getC[y] = getc(fOp[y])) != EOF; y++) {
            if (getC[y] == '\n') numL[y]++;
            if (getC[y] == ' ' || getC[y] == '\n' || getC[y] == '\t') getW[y] = 0;
            else if (getW[y] == 0) { 
                getW[y] = 1;
                numW[y]++; 
            } numC[y]++;
        } 

        int z;
        for (z = 1; z <= argc-1; z++) { /* close files */
            fclose(fOp[z]);
        }

    int c;
    for (c = 1; c <= argc-1; c++) {
        printf("[%s] %dL %dW %dC\n", argv[c], numL[c], numW[c], numC[c]);
    }

    return 0;

}   

Upvotes: 1

Views: 680

Answers (2)

Weather Vane
Weather Vane

Reputation: 34585

This will cause a segfault when you reach the last file

FILE *fOp[argc-1];

for (x = 1; x <= argc-1; x++) { /* open file stream for each file */
    fOp[x] = fopen(argv[x], "r");
    if (fOp[x] == NULL)
        return -1;
}

because the array is not large enough. It should be

FILE *fOp[argc];

The mistake would be easier to see if you used

< argc

instead of

<= argc-1

in your loops.

Upvotes: 1

ameyCU
ameyCU

Reputation: 16607

I think problem may be here -

 for (y = 1; (getC[y] = getc(fOp[y])) != EOF; y++) {
        if (getC[y] == '\n') numL[y]++;
        if (getC[y] == ' ' || getC[y] == '\n' || getC[y] == '\t') getW[y] = 0;
        else if (getW[y] == 0) { 
            getW[y] = 1;
            numW[y]++; 
        } numC[y]++;
    } 

As arrays can argc number of elements but with this loop you may have read and stored integers more than argc in getC . Thus getting Seg Fault .

But we don't know what it inside files we can't be sure.

Try increasing size of arrays .

Note - It is better to initialize array starting with index 0. In this code you haven't use index 0.

Upvotes: 0

Related Questions