Re: how to count rows and columns of integers/doubles in a file?



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.
.



Relevant Pages

  • doubt about socket programing
    ... my client side programme ... int k=Integer.parseInt); ... OutputStream out1=s.getOutputStream; ... response from server for that input.and then program is hanging ...
    (comp.lang.java.programmer)
  • Re: strange thing using Process class to call outside executable file
    ... Check out Performance Counters. ... use the Process class in C#,and my thread is as follows:start a process ... int main ... it comes out that this programme uses around 1800KB memory(this may be ...
    (microsoft.public.dotnet.languages.csharp)
  • Re: K&R2, section 1.5.3, exercise 1.8
    ... Richard Heathfield has created a C programme at his answers page: ... i have also created my programme which runs fine. ... int main{ ... disgusting style. ...
    (comp.lang.c)
  • strange thing using Process class to call outside executable file
    ... I've been working on an online judge(for ACM/ICPC) using C#.Programmes ... use the Process class in C#,and my thread is as follows:start a process ... int main ... it comes out that this programme uses around 1800KB memory(this may be ...
    (microsoft.public.dotnet.framework.aspnet)
  • strange thing using Process class to call outside executable file
    ... I've been working on an online judge(for ACM/ICPC) using C#.Programmes ... use the Process class in C#,and my thread is as follows:start a process ... int main ... it comes out that this programme uses around 1800KB memory(this may be ...
    (microsoft.public.dotnet.general)