1

I have a matrix in a file and i want to count the number of rows and columns.. The matrix elements are separated by space :

1 2.3 4 5 ..etc
3 4 6.77 9
8 .....
........
etc

I found a function to count the number of column..and it works like charm :

int getColumn(FILE* fp)
  {
    char buff[BUFSIZ]={0};
    int count=0;
    char *p;

    if(NULL==fgets(buff, BUFSIZ, fp))
        return -1;
    rewind(fp);
    for(p=buff;NULL!=strtok(p, " \t\n");p=NULL)
        ++count;
    return count;
}

Now i want to make a similar function getRow() that counts lines.. but i dont really understand how getColumn() works i have some alternatives for getRow() but i read that it's not very safe to play with EOF..(In fact i encountered problems with it) an exemple:

int getRow(FILE* fp)
{                                
  int ch=0;
  int count=1;

while(!feof(fp))
   {
      ch = fgetc(fp);
      if(ch == '\n')
      count++;
   }
  return count;
}
NaoufaT
  • 23
  • 1
  • 3
  • What if you just get the contents of the file and store it inside the string and then count the rows and columns with the string so that you would only need to check against `\0` and not `EOF`? – Sean Francis N. Ballais Dec 28 '15 at 15:39
  • Also see this post http://stackoverflow.com/questions/5431941/why-is-while-feof-file-always-wrong – terence hill Dec 28 '15 at 15:40
  • This is a pretty basic programming question (I'm guessing homework?). Unless for some terrible reason, you don't know C but are stuck doing this for a real job, you should walk through getColumn line by line until you understand what everything does before you concern yourself with the potential problems with `feof`, which will, in most normal cases work fine for you. – Brian McFarland Dec 28 '15 at 15:55

2 Answers2

4

Count line in a text file in C

I will try to explain how it works. First of all you have to understand what does the function getColumn.

Short answer: it reads the first line (if any) of the input file and return the number of items separated by one of the following: space, tab or newline.

Long answer: first it checks if there is something to read:

if(NULL == fgets(buff, BUFSIZ, fp))
    return -1;

The function fgets get a line from a file which means that it stops on newline (or if the specified size is less then the actual size of the line). In the example above, fgets try to read BUFFSIZ - 1 characters from the file pointed by fp and to store them in the character array buff (-1 because newline is retained). However, if there are no characters to read, fgets returns NULL and the function exits.

On the other hand, if the return value is not NULL then the line is stored in the array buff. Here the assumption is that the line fits in BUFSIZ.

BTW BUFSIZ is a macro defined in the GNU C Library as follows:

Macro: int BUFSIZ The value of this macro is an integer constant expression that is good to use for the size argument to setvbuf. This value is guaranteed to be at least 256 (link).

The array buff is then examined in the loop:

for(p=buff; NULL!=strtok(p, " \t\n"); p=NULL)
    ++count;

The for loop cycles on the array buff by means of the functions strtok. strtok "is used to isolate sequential tokens in a null-terminated string", strtok will examines buff until the terminating character '\0', however, anytime it encounters one of the specified separators, " \t\n", it will return the pointer to the item, the loop is entered and count incremented. On the first call strtok must be invoked with the pointer but each subsequent call to strtok must be done with NULL, this is why p is set to NULL in the third expression of the for loop.

How to read lines and count them

#define BUFFSIZE 1024
int countlines (FILE *fin)
{
    int  nlines  = 0;
    char line[BUFFSIZE];

    while(fgets(line, BUFFSIZE, fin) != NULL) {
        nlines++;
    }

    return nlines;
}

Again we read BUFFSIZE - 1 characters, however I prefer to set BUFFSIZE by hand.

Final Remark

The correct way to count both lines and columns is to use only one function. While reading each line you can count the number of columns. You can count the columns only on the first line if you are sure that the input file is correct (and all the lines have the same number of columns) or you can count them for each line.

terence hill
  • 3,354
  • 18
  • 31
  • To get a more accurate count of the number of lines, you can check the final character in each line. If the last character in line is `\n`, then you can count the line. That would account for lines longer than `BUFFSIZE - 1`. – Andrew Henle Dec 28 '15 at 19:06
  • Thank you very much @terencehill especially for the detailed explanation it's very helpful..i understand how it works..i think there's something missing in getColumn..i think i should add `fgets(buff,BUFSIZ, fp);rewind(fp);` before the testing ` if NULL==fgets(buff, BUFSIZ, fp)` ..is that right ? – NaoufaT Dec 28 '15 at 20:57
  • I'm not sure I understood your point. You need to rewind if the file has already been accessed, for example if you call counlines and then getColumns you should rewind the file between the two calls. – terence hill Dec 29 '15 at 00:12
  • @AndrewHenle thanks for the comment. I see your point, I'm not sure if is better to add it or leave it in the comment, this is a very basic code explained, what do you think? – terence hill Dec 29 '15 at 00:17
  • @terencehill I think your answer as-is is perfect. – Andrew Henle Dec 29 '15 at 13:26
0

Try :

while(ch != EOF)
{
     // Code goes in here
}

instead of feof().

Sean Francis N. Ballais
  • 2,338
  • 2
  • 24
  • 42
Crunch
  • 9
  • 4