Re: how to count rows and columns of integers/doubles in a file?
- From: Michael Mair <Michael.Mair@xxxxxxxxxxxxxxx>
- Date: Wed, 15 Mar 2006 21:59:11 +0100
Martin Joergensen schrieb:
I have some files which has the following content:
0 0 0 0 0 0
0 1 1 1 1 0
0 1 1 1 1 0
0 1 1 1 1 0
0 1 1 1 1 0
0 0 0 0 0 0
I'm making a function for a bigger program, that
1) counts number of columns in each row
2) verifies that there are the same number of columns in each row (if not: error + quit)
3) increments row count after one row is finished
4) stops execution if it encounters anything that is not an integer (later: should also work for doubles)
My only problem is that I don't know how to switch line (carriage return) or how to detect it using scanf.
The end of a line is indicated by '\n' in C.
If you are writing the file with a C programme, too, and
the reading and the writing programme are in the same locale,
then you do not have to take care of anything as long as you
work with text streams. Only if you explicitly open a binary
stream, then you have to look at the actual representation
of '\n'.
So, you can read in the number of lines and columns like this
if you concentrate on 1) to 3). You need some sort of string
buffer for 4) if you do not want to check yourself.
int countRowsAndCols (FILE *pFile, unsigned *pRows, unsigned *pCols)
{
unsigned rows, cols, oldcols;
int isConsistent = 1;
/* define file here */
rows = 0;
if (countColsInNextLine(pFile, &oldcols) != EOF) {
rows++;
while (countColsInNextLine(pFile, &cols) != EOF) {
rows++;
if (cols != oldcols) {
isConsistent = 0;
/* Your error message here */
}
}
}
*pRows = rows;
*pCols = oldcols;
return !isConsistent;
}
In
int countColsInNextLine (FILE *pFile, unsigned *pCols)
{
int c;
unsigned cols = 0;
do {
c = getc(pFile);
if (c != EOF && !isspace(c)) {
cols++;
do {
c = getc(pFile);
} while (c != EOF && !isspace(c));
}
while (c != EOF && c != '\n' && isspace(c)) {
c = getc(pFile);
}
} while (c != EOF && c != '\n')
*pCols = cols;
return c;
}
you consume characters from the file until you find
either a line break or the end of the file.
You return the last result from getc(), i.e. EOF if the
file ends. The functions are not tested.
You could make life easier in the second function by
introducing appropriate auxiliary functions.
The above is not tested.
Besides that, the program is almost finished. See below:
- - - - - - - - - - - - - - - -
#include <stdio.h>
void int_getdata(char *filename, unsigned int *x, unsigned int *y);
int main()
{
unsigned int n_x[3], n_y[3];
int_getdata("unknowns.dat", &n_x[0], &n_y[0] );
int_getdata("BC_types.dat", &n_x[1], &n_y[1] );
// double_getdata("BC_values.dat", &n_x[2], &n_y[2] );
return 0;
}
void int_getdata(char *filename, unsigned int *x, unsigned int *y)
{
FILE *fp;
unsigned int old_nx;
int int_readvalue, returnvalue;
//double double_readvalue;
old_nx = 0; /* reset */
*x = 0;
*y = 0;
if ( (fp = fopen(filename, "r") ) == NULL)
{
printf("Cannot open file %s.\n", filename);
system("PAUSE"); /* give the user at chance to see this error before the windows shuts down */
exit(1);
}
/* get nx and ny */
do{
returnvalue = fscanf(fp, "%i", &int_readvalue); /* all input must be valid */
if(returnvalue == 1) (*x)++; /* nx is getting larger */
else{
printf("Error: non-valid input found in %s.\n", filename);
exit(1);
}
if(int_readvalue == '\n')
This is not what you want. You compare the value of the read
integer against the value of the int constant '\n'.
{
if(old_nx != 0 && old_nx != *x)
{
printf("ERROR: nx is not a constant in file %s!\n", filename);
exit(1);
}
else /* we should now be sure that nx is constant and move on to the next input line */
{
old_nx = *x;
y++; /* ny is getting larger */
*x = 0;
}
}
} while(returnvalue != EOF);
printf("\nFinished reading from file %s: (x,y) = (%i,%i).\n", filename, *x, *y);
fclose(fp); /* close input file, finished reading values in */
}
- - - - - - - - - - - - - - - -
I hope somebody can help me solve this small problem, so I can finish the program....
Even though you can do certain things with the help of
scan sets (%[] or %[^]), it is probably easier to read in
a line and check the values with sscanf() or even strtoul()
or strtod(). If you only need the originally indicated
space -- non-space distinction, have a look at the suggested
functions.
We already lead the "how to read a line" discussion, so you
can just look up the respective thread.
I also get these small warnings, but they are not critical:
warning C4013: 'system' undefined; assuming extern returning int
warning C4013: 'exit' undefined; assuming extern returning int
They are. You forgot to #include <stddef.h>, so you did not get
proper types for the functions.
Especially, the arguments are not converted automatically and
you don't get a warning if they cannot be converted. For these
two functions, everything probably will work as intended but
there is a serious error behind the warning.
Cheers
Michael
--
E-Mail: Mine is an /at/ gmx /dot/ de address.
.
- Follow-Ups:
- Re: how to count rows and columns of integers/doubles in a file?
- From: Martin Joergensen
- Re: how to count rows and columns of integers/doubles in a file?
- References:
- how to count rows and columns of integers/doubles in a file?
- From: Martin Joergensen
- how to count rows and columns of integers/doubles in a file?
- Prev by Date: Re: Book-keeping metadata for allocated memory
- Next by Date: Re: Book-keeping metadata for allocated memory
- Previous by thread: how to count rows and columns of integers/doubles in a file?
- Next by thread: Re: how to count rows and columns of integers/doubles in a file?
- Index(es):
Relevant Pages
|