Reputation: 23
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;
}
Upvotes: 1
Views: 3639
Reputation: 3454
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.
Upvotes: 4