By using this site, you agree to our updated Privacy Policy and our Terms of Use. Manage your Cookies Settings.
424,680 Members | 1,475 Online
Bytes IT Community
+ Ask a Question
Need help? Post your question and get tips & solutions from a community of 424,680 IT Pros & Developers. It's quick & easy.

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

P: n/a
Hi,

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. 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')
{
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....

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
Best regards / Med venlig hilsen
Martin Jørgensen

--
---------------------------------------------------------------------------
Home of Martin Jørgensen - http://www.martinjoergensen.dk

Mar 15 '06 #1
Share this Question
Share on Google+
68 Replies


P: n/a
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.
Mar 15 '06 #2

P: n/a
"Martin Joergensen" <un*********@spam.jay.net> writes:
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
What do you mean by "columns"? Does "0 0 0 0 0 0" have 6 columns
(numbers) or 11 (characters)?

[snip]
returnvalue = fscanf(fp, "%i", &int_readvalue); /* all input
must be valid */


fscanf with a "%i" format reads an integer value after skipping any
leading whitespace -- including new-lines. It gives no indication of
what it skipped. If new-lines are significant, that's the wrong
approach.

It also accepts either decimal, octal, or hexadecimal input. Decide
whether you want to allow numbers like "0xff", and whether you want
"0123" to be interpreted in octal (yielding 83) or in decimal
(yielding 123). Since you mentioned you'll eventually want the
program to work with doubles, you probably don't want to accept octal
or hexadecimal; you probably want "%d" rather than "%i". ("%d" and
"%i" behave identically for the *printf functions, but differently for
the *scanf functions).

A much better approach is to use fgets() to read a line at a time,
then use sscanf() to scan the resulting line. sscanf(), unlike
fscanf(), doesn't consume its input; it's still there in the string,
and if the sscanf() call fails (check its returned value), you can try
again.

fgets() has the disadvantage that it can only read a line up to a
specified length. If the input line is longer than what you
specified, fgets() will read only part of it; you can detect this by
whether the line you just read ends in a '\n'. If you only want to
allow input lines up to some maximum length, this isn't much of a
problem -- but you should still decide what to do if an input line
exceeds your maximum. If you want to handle arbitrarily long input
lines, you can use CBFalconer's "ggets" (Google it).

--
Keith Thompson (The_Other_Keith) ks***@mib.org <http://www.ghoti.net/~kst>
San Diego Supercomputer Center <*> <http://users.sdsc.edu/~kst>
We must do something. This is something. Therefore, we must do this.
Mar 15 '06 #3

P: n/a
On Wed, 15 Mar 2006 20:32:04 +0100, "Martin Joergensen"
<un*********@spam.jay.net> wrote:
Hi,

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. 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 */
fscanf will eat white space, including the \n that marks the end of
line.

You could use fgets to get a complete line then strtol to process each
value for correctness.

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')
{
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....

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
Best regards / Med venlig hilsen
Martin Jørgensen

Remove del for email
Mar 16 '06 #4

P: n/a
"Michael Mair" <Mi**********@invalid.invalid> skrev i en
meddelelse news:47************@individual.net...
Martin Joergensen schrieb: -snip-
The above is not tested.
Thanks... Helped me a lot... Almost finished now... Se my other
post.
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'.


Oh, yeah... I hoped that it could read integers as well as
'\n'... Seems like it can't. I just skips it..

-snip- 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.
Ok... I added a little - I also want to skip commas.

That was also so great about scanf, that it could check if all
numbers were valid at the same time it counted...
We already lead the "how to read a line" discussion, so you
can just look up the respective thread.
I found something on google:
- - - - -- -
#define LENGTH 20
#define str(x) # x
#define xstr(x) str(x)

int rc;
char array[LENGTH + 1];
rc = scanf("%" xstr(LENGTH) "[^\n]%*[^\n]", array);
if (!feof(stdin)) {
getchar();
}
if (rc == 0) {
*array = '\0';
}
/* rc will be either 1, 0, or EOF */

- - - - -

What the hell is happening here: "[^\n]%*[^\n]" ?
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.


No, I think it is stdlib.h, I needed... But thanks - you're
always a big help to me...
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.


Ok, including stdlib.h seems to work...
Best regards / Med venlig hilsen
Martin Jørgensen

--
---------------------------------------------------------------------------
Home of Martin Jørgensen - http://www.martinjoergensen.dk

Mar 16 '06 #5

P: n/a
"Keith Thompson" <ks***@mib.org> skrev i en meddelelse
news:ln************@nuthaus.mib.org...
"Martin Joergensen" <un*********@spam.jay.net> writes: -snip- A much better approach is to use fgets() to read a line at a
time,
then use sscanf() to scan the resulting line. sscanf(), unlike
fscanf(), doesn't consume its input; it's still there in the
string,
and if the sscanf() call fails (check its returned value), you
can try
again.

-snip-

What do you think about the following, based on Michael Mair's
proposal?

Just copy/paste - compiles well...
- - - - - -
#include <stdlib.h> /* system("PAUSE") */
#include <stdio.h>
#include <stddef.h>
#include <ctype.h> /* for isspace */

#define number_of_files 3

/* prototypes */
void getdata(char *filename, unsigned *pRows, unsigned *pCols);
/* this is how the args should be */
int countColsInNextLine (FILE *pFile, unsigned *pCols);
int main()
{
int i;
unsigned n_x[number_of_files], n_y[number_of_files]; /* one
space for each data file */

getdata("unknowns.dat", &n_x[0], &n_y[0] );
getdata("BC_types.dat", &n_x[1], &n_y[1] );
// getdata("BC_values.dat", &n_x[2], &n_y[2] );

for(i=0; i<number_of_files; i++)
printf("Data file number %i has properties: x = %u, y=
%u\n", i, n_x[i], n_y[i]);

return 0;
}

//fgets( stringbuffer, 20, fp);
//sscanf( stringbuffer, "%X", &var1);

void getdata(char *filename, unsigned *pRows, unsigned *pCols) /*
this is how the args should be */
{
FILE *pFile;

unsigned rows, cols, oldcols;

if ( (pFile = 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);
}

*pRows = 0;
*pCols = 0;

/* get nx and ny */
cols = 0;
rows = 0;
if (countColsInNextLine(pFile, &oldcols) != EOF) { /* get
oldcols for first row */
rows++;
while (countColsInNextLine(pFile, &cols) != EOF) {
rows++;
if (cols != oldcols) { /* verify that number of cols
didn't change */
printf("ERROR: Number of columns is not a
constant in file: %s!\n", filename);
exit(1);
}
}
}

*pRows = rows; /* update results */
*pCols = oldcols;

printf("\nFinished reading from file %s.\n", filename);
fclose(pFile); /* close input file, finished reading values
in */
}

int countColsInNextLine (FILE *pFile, unsigned *pCols)
{
int c;
unsigned cols = 0;

do {
c = getc(pFile); /* get first character to start the loop
*/
if (c != EOF && !isspace(c)) { /* first time non-space
encountered, update cols */
cols++;
do { /* skip digits and commas */
c = getc(pFile);
} while (c != EOF && !isspace(c) && c != ',' && c !=
'.'); /* comma should also be valid input in number */
}
while (c != EOF && c != '\n' && isspace(c)) { /* skip
through spaces, but not '\n' ! */
c = getc(pFile);
}
} while (c != EOF && c != '\n');

*pCols = cols;
return c;
}
- - - -
It seems like there is small error in counting the rows..... I
couldn't find the error before and I'm not sure I understood all
the while loops completely - to help myself I added some
comments.

So there's just a little error left (that's the second time in
this thread I write that - This time I hope it's true!) :-)
Best regards / Med venlig hilsen
Martin Jørgensen

--
---------------------------------------------------------------------------
Home of Martin Jørgensen - http://www.martinjoergensen.dk

Mar 16 '06 #6

P: n/a
Martin Joergensen wrote:
"Keith Thompson" <ks***@mib.org> skrev i en meddelelse
news:ln************@nuthaus.mib.org... -snip-
What do you think about the following, based on Michael Mair's proposal?

-snip-

I don't know why, but I can't debug that code very well... I put
breakpoints in it but very often within the getdata-function, it just
finishes the program ignoring my breakpoints....

Why is that so?
Best regards / Med venlig hilsen
Martin Jørgensen

--
---------------------------------------------------------------------------
Home of Martin Jørgensen - http://www.martinjoergensen.dk
Mar 16 '06 #7

P: n/a
Martin Jørgensen wrote:
Martin Joergensen wrote:
"Keith Thompson" <ks***@mib.org> skrev i en meddelelse
news:ln************@nuthaus.mib.org...


-snip-
What do you think about the following, based on Michael Mair's proposal?


-snip-

I don't know why, but I can't debug that code very well... I put
breakpoints in it but very often within the getdata-function, it just
finishes the program ignoring my breakpoints....

Why is that so?


Forget it... I forgot to add a compiler option and now it works.
Best regards / Med venlig hilsen
Martin Jørgensen

--
---------------------------------------------------------------------------
Home of Martin Jørgensen - http://www.martinjoergensen.dk
Mar 17 '06 #8

P: n/a
Martin Joergensen schrieb:
"Michael Mair" <Mi**********@invalid.invalid> skrev i en meddelelse
news:47************@individual.net...
Martin Joergensen schrieb: <snip>
rc = scanf("%" xstr(LENGTH) "[^\n]%*[^\n]", array); <snip> What the hell is happening here: "[^\n]%*[^\n]" ?


read up to LENGTH non-'\n' characters into array, consume
arbitrarily many subsequent '\n's
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.


No, I think it is stdlib.h, I needed... But thanks - you're always a big
help to me...


"Left, left -- oh, I meant the other left"
Of course, you are right: I meant <stdlib.h>

Cheers
Michael
--
E-Mail: Mine is an /at/ gmx /dot/ de address.
Mar 17 '06 #9

P: n/a
Michael Mair wrote:
-snip-
Cheers
Michael


Do you like my new program?

I find it *REALLY* useful :-)

- - - - - - - - - - - -

#include <stdlib.h> /* system("PAUSE") */
#include <stdio.h>
#include <stddef.h>
#include <ctype.h> /* for isspace */

#define max_number_of_files 50

/* prototypes */
void getdata(char *filename, unsigned *pCols, unsigned *pRows, int *count);
int countColsInNextLine (FILE *pFile, unsigned *pCols, unsigned *pRows);
void testwronginput(int c, unsigned cols, unsigned rows);

int main()
{
int i, count;
unsigned n_x[max_number_of_files], n_y[max_number_of_files]; /* one
space for each data file */

count = 0;
getdata("unknowns.dat", &n_x[0], &n_y[0], &count );
getdata("BC_types.dat", &n_x[1], &n_y[1], &count );
getdata("BC_values.dat", &n_x[2], &n_y[2], &count );

for(i=0; i<count; i++)
printf("Data file number %i has properties: Columns (x) = %u,
Rows y= %u\n", i+1, n_x[i], n_y[i]);

system("PAUSE"); /* give the user at chance to see this error
before the windows shuts down */
return 0;
}
void getdata(char *filename, unsigned *pCols, unsigned *pRows, int *count)
{
FILE *pFile;

unsigned rows, cols, oldcols;

printf("Opening file: %s.\n", filename);
if ( (pFile = 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);
}

*pRows = 0;
*pCols = 0;

/* get nx and ny */
cols = 0;
rows = 0;
if (countColsInNextLine(pFile, &oldcols, &rows) != EOF) { /* return
oldcols for first row */
rows++;
while (countColsInNextLine(pFile, &cols, &rows) != EOF) { /*
check row 2 -> EOF */
rows++;
if (cols != oldcols) { /* verify that number of cols didn't
change */
printf("ERROR: Number of columns is not a constant in
file: %s\n\n", filename);
printf("In line %u, the number of columns is %u
cols.\n", rows, cols);
printf("In the previous line it was counted to
%u.\n\nPlease fix this problem now.\n", oldcols);
exit(1);
}
}
}

if (cols != 0 && cols != oldcols) {
printf("ERROR: Line %u (last line) consisted of %u
columns.\nLine %u had %u columns.\n", rows, cols, rows-1, oldcols);
exit(1);
}

*pRows = rows; /* update results */
*pCols = oldcols;
(*count)++;

printf("Finished reading from file %s.\n\n", filename);
fclose(pFile); /* close input file, finished reading values in */
}

int countColsInNextLine (FILE *pFile, unsigned *pCols, unsigned *pRows)
{
int c;
unsigned cols = 0;

c = getc(pFile); /* get first character to start the loop */
do {
testwronginput(c, cols, *pRows);
if (c != EOF && !isspace(c)) { /* first time non-space
encountered, update cols */
cols++;
do { /* skip digits and commas, after first digit */
c = getc(pFile);
testwronginput(c, cols, *pRows);
} while (c != EOF && !isspace(c) || c == ',' || c == '.');
/* comma should also be valid input in number */
}
while (c != EOF && c != '\n' && isspace(c)) { /* skip through
blank spaces, but not '\n' ! */
c = getc(pFile);
testwronginput(c, cols, *pRows);
}
} while (c != EOF && c != '\n'); /* is the line finished or is EOF
reached? */

*pCols = cols;
return c;
}

void testwronginput(int c, unsigned cols, unsigned rows) /* I tried
isblank() but my system complained about it */
{
if (isalpha(c)) {
printf("Error! Alphabetic character '%c' encountered before
EOF\n", c);
printf("Last succesful location read was: Line %u, Column
%u\n", 1+rows, cols);
system("PAUSE"); /* give the user at chance to see this error
before the windows shuts down */
exit(1);
}
if (iscntrl(c) && c != 10) {
printf("Error! Control character '%c' encountered before
EOF\n", c);
printf("Last succesful location read was: Line %u, Column
%u\n", 1+rows, cols);
system("PAUSE"); /* give the user at chance to see this error
before the windows shuts down */
exit(1);
}
if (!isprint(c) && c != EOF && c != '\n') {
printf("Error! Non-printing character '%c' encountered before
EOF\n", c);
printf("Last succesful location read was: Line %u, Column
%u\n", 1+rows, cols);
system("PAUSE"); /* give the user at chance to see this error
before the windows shuts down */
exit(1);
}
}

- - - - - - - - - - - -
Best regards / Med venlig hilsen
Martin Jørgensen

--
---------------------------------------------------------------------------
Home of Martin Jørgensen - http://www.martinjoergensen.dk
Mar 17 '06 #10

P: n/a
Martin Jørgensen wrote:
Michael Mair wrote:
-snip-
Cheers
Michael

Do you like my new program?

-snip-

I have a serious problem now!

I thought everything was okay and was progressing well - So I now
figured out how to do this program but now I want to include it in my
bigger program and use number of cols + number of rows to malloc().

So, I have a lot of arrays that depend on malloc() which again should
depend on number of rows in x-direction = nx, and number of cols in
y-direction = ny.

So my big program starts with something like:
- - - - - - - - - - - -

int main(void)
{

/* prototypes */
void int_fillinnumbers(int, int, int, int, int, int **);
void double_fillinnumbers(double, int, int, int, int, double **);
void int_printout(int, int, int, int, int **);
void double_printout(int, int, int, int, double **);
void conversion(int no, int *i, int *j); /* convert from number of
interior cells to [i][j] format */
void one_dim_double_printout(int startx, int stopx, double *array); /*
for printing out temperatures from CG-solver */
void integer_load_properties(char *filename, int **array);
void double_load_properties(char *filename, double **array);

pstSolveType pstSolve;
// // // // // //

/* STOP READING HERE! Now, I need the number of cols and rows from the
data-files to dynamically initialize the correct 1D and 2D-array sizes.
I need it here, because below malloc need number of cols */

// // // // // //
double **T = malloc((cols+1)*sizeof(double*)); /* alternative: int **T
= malloc((cols + 1) * sizeof *T); */
double **T_new = malloc((cols+1)*sizeof(double*));

.. . . . . .
.. . . . . . (later)
.. . . . . .

T[0] = malloc((cols+1)*(rows+1)*sizeof(double));
T_new[0] = malloc((cols+1)*(rows+1)*sizeof(double));

The problem is that I get a compiler error, something about a missing
semi-colon. And I've got this error a couple of times before. I happens
because I mix declarations and initialisation, somebody wrote...

What the hell do I do now? Until now, rows and columns was just set to
something using #define, but I don't like that solution with having to
change input data several places, both in the #define line and also in
each input file(s)...

So, what I want is to include these lines:

count = 0;
getdata("unknowns.dat", &n_x[0], &n_y[0], &count );
getdata("BC_types.dat", &n_x[1], &n_y[1], &count );
getdata("BC_values.dat", &n_x[2], &n_y[2], &count );

for(i=0; i<count; i++)
printf("Data file number %i has properties: Columns (x) = %u,
Rows y= %u\n", i+1, n_x[i], n_y[i]);
But then the compiler is complaining like hell, because I need to the
return value of *n_x and *n_y for malloc(), *count is just a counter for
number of read files...

I really, *really* hope there is a good solution to this problem. I just
have no idea what it is.

Please let me know, if you have any ideas whatsoever. I almost can't
believe that there's no way of dealing with this problem in a good way.
Best regards / Med venlig hilsen
Martin Jørgensen

--
---------------------------------------------------------------------------
Home of Martin Jørgensen - http://www.martinjoergensen.dk
Mar 17 '06 #11

P: n/a
On Fri, 17 Mar 2006 19:00:51 +0100, Martin Jørgensen
<un*********@spam.jay.net> wrote:
Martin Jørgensen wrote:
Michael Mair wrote:
-snip-
Cheers
Michael

Do you like my new program?

-snip-

I have a serious problem now!

I thought everything was okay and was progressing well - So I now
figured out how to do this program but now I want to include it in my
bigger program and use number of cols + number of rows to malloc().

So, I have a lot of arrays that depend on malloc() which again should
depend on number of rows in x-direction = nx, and number of cols in
y-direction = ny.

So my big program starts with something like:
- - - - - - - - - - - -

int main(void)
{

/* prototypes */
void int_fillinnumbers(int, int, int, int, int, int **);
void double_fillinnumbers(double, int, int, int, int, double **);
void int_printout(int, int, int, int, int **);
void double_printout(int, int, int, int, double **);
void conversion(int no, int *i, int *j); /* convert from number of
interior cells to [i][j] format */
void one_dim_double_printout(int startx, int stopx, double *array); /*
for printing out temperatures from CG-solver */
void integer_load_properties(char *filename, int **array);
void double_load_properties(char *filename, double **array);

pstSolveType pstSolve;
// // // // // //

/* STOP READING HERE! Now, I need the number of cols and rows from the
data-files to dynamically initialize the correct 1D and 2D-array sizes.
I need it here, because below malloc need number of cols */

// // // // // //
double **T = malloc((cols+1)*sizeof(double*)); /* alternative: int **T
= malloc((cols + 1) * sizeof *T); */


In most implementations, rows come before columns.
double **T_new = malloc((cols+1)*sizeof(double*));

. . . . . .
. . . . . . (later)
. . . . . .

T[0] = malloc((cols+1)*(rows+1)*sizeof(double));
Since you already have cols+1 pointers, each pointer only needs to
point to rows+1 doubles, not (cols+1)*(rows+1).
T_new[0] = malloc((cols+1)*(rows+1)*sizeof(double));

The problem is that I get a compiler error, something about a missing
semi-colon. And I've got this error a couple of times before. I happens
because I mix declarations and initialisation, somebody wrote...
Missing semicolon errors are usually caused by an error preceding the
actual line flagged. You need to show us all the code.

What the hell do I do now? Until now, rows and columns was just set to
something using #define, but I don't like that solution with having to
change input data several places, both in the #define line and also in
each input file(s)...

So, what I want is to include these lines:

count = 0;
getdata("unknowns.dat", &n_x[0], &n_y[0], &count );
getdata("BC_types.dat", &n_x[1], &n_y[1], &count );
getdata("BC_values.dat", &n_x[2], &n_y[2], &count );

for(i=0; i<count; i++)
printf("Data file number %i has properties: Columns (x) = %u,
Rows y= %u\n", i+1, n_x[i], n_y[i]);
But then the compiler is complaining like hell, because I need to the
return value of *n_x and *n_y for malloc(), *count is just a counter for
number of read files...
Show the code. Your explanation is borderline meaningless.

I really, *really* hope there is a good solution to this problem. I just
have no idea what it is.

Please let me know, if you have any ideas whatsoever. I almost can't
believe that there's no way of dealing with this problem in a good way.
Best regards / Med venlig hilsen
Martin Jørgensen

Remove del for email
Mar 18 '06 #12

P: n/a
Martin Jørgensen wrote:
Michael Mair wrote:
-snip-
Cheers
Michael


Do you like my new program?


<snip>

Here's some help. Compile this small program, and run it with the
filename of your .dat file as the command line argument. Try all the
cases you can think of, and see how the error handling works.
#include <stdio.h>
#include <stdlib.h>

enum Error {
Success, /* All went well */
TooManyCol, /* Too many columns */
TooFewCol, /* Too few columns */
ConvErr, /* Conversion failed */
FileErr /* File read error */
};

/*
* Parse a file to determine the number of rows and columns of integer
* data. Lines containing only whitespace are ignored. If the return
* value is not Success, the line number in the file where the problem
* was encountered is written to *rows. If a fscanf conversion error
* occurred, then the current position of 'fp' will be the position of
* the problematic input.
*/
enum Error parse(FILE *fp, int *rows, int *cols)
{
int line, count, ret, val;
enum Error err = Success;

*rows = *cols = 0;
for(line = 1; ; line++) {
for(count = 0; ; count++) {

/* Discard spaces and tabs. */
ret = fscanf(fp, "%*[ \t]");
if(ret == EOF)
break;

/* Get the next character. */
ret = getc(fp);
if(ret == EOF)
break;

/* At the end of the line? */
if(ret == '\n')
break;

/* No. Put back and fscanf. */
ungetc(ret, fp);
ret = fscanf(fp, "%d", &val);
if(ret != 1) {
if(ret == 0)
err = ConvErr;
break;
}
}

/* Check for file error. */
if(ret == EOF && ferror(fp))
err = FileErr;

/* If successful so far... */
if(err == Success) {
if(count != 0) {
(*rows)++;
if(*cols == 0)
*cols = count;
else {
if(count < *cols)
err = TooFewCol;
else if(count > *cols)
err = TooManyCol;
}
}
}

/* If an error or EOF, stop */
if(err != Success || feof(fp))
break;
}

/* On error, report line number. */
if(err != Success)
*rows = line;
return err;
}
int main(int argc, char *argv[])
{
FILE *fp;
int rows, cols;
enum Error result;
const char *file;
int ret = EXIT_FAILURE;
char buf[8];

/* Check argument count. */
if(argc != 2) {
printf("usage: %s FILENAME\n", argv[0]);
return ret;
}

/* Open the data file. */
file = argv[1];
fp = fopen(file, "r");
if(fp == NULL) {
printf("Error: cannot open %s.\n", file);
return ret;
}

/* Try to parse the file, then interpret the result. */
result = parse(fp, &rows, &cols);
switch(result) {
case Success:
printf("%s: %d rows, %d columns\n", file,
rows, cols);
ret = EXIT_SUCCESS;
break;

case TooManyCol:
printf("Error: %s line %d: too many columns.\n",
file, rows);
break;

case TooFewCol:
printf("Error: %s line %d: too few columns.\n",
file, rows);
break;

case ConvErr:
fscanf(fp, "%7s", buf);
printf("Error: %s line %d: invalid input near \"%s\".\n",
file, rows, buf);
break;

case FileErr:
default:
printf("Error: %s line %d: unknown file error.\n",
file, rows);
break;
}

/* Clean up and exit */
fclose(fp);
return ret;
}
Report back with any comments, questions, or bugs. I wrote it over
lunch, so it may contain a bug or two.
Mark F. Haigh
mf*****@sbcglobal.net

Mar 18 '06 #13

P: n/a
Barry Schwarz wrote:
On Fri, 17 Mar 2006 19:00:51 +0100, Martin Jørgensen
<un*********@spam.jay.net> wrote: -snip-
double **T = malloc((cols+1)*sizeof(double*)); /* alternative: int **T
= malloc((cols + 1) * sizeof *T); */

In most implementations, rows come before columns.


Damn... I think you're right....... I should change it - Only went good
because number of rows = number of cols...
double **T_new = malloc((cols+1)*sizeof(double*));

. . . . . .
. . . . . . (later)
. . . . . .

T[0] = malloc((cols+1)*(rows+1)*sizeof(double));

Since you already have cols+1 pointers, each pointer only needs to
point to rows+1 doubles, not (cols+1)*(rows+1).


But I *don't* have number of cols and number of rows from my program
using the above implementation. In the above implementation, I just did
a #define cols 8 (or whatever). As I wrote, the problem is that I don't
want to change both #define rows and the input file. Only the input file..
T_new[0] = malloc((cols+1)*(rows+1)*sizeof(double));

The problem is that I get a compiler error, something about a missing
semi-colon. And I've got this error a couple of times before. I happens
because I mix declarations and initialisation, somebody wrote...

Missing semicolon errors are usually caused by an error preceding the
actual line flagged. You need to show us all the code.


Well, I guess you saw my program but perhaps didn't notice it very much,
so here I just took some parts to show you the structure of what I want
(untested, but then you know what this is about):

- - - - -

/* prototypes */
/* several ones bla.bla.bla. from the bigger program I have */

/* more prototypes */
void getdata(char *filename, unsigned *pCols, unsigned *pRows, int
*count);
int countColsInNextLine (FILE *pFile, unsigned *pCols, unsigned
*pRows);
void testwronginput(int c, unsigned cols, unsigned rows);
int main(void)
{
/* read from file and get number of cols+rows */

unsigned count; /* and a lot more var's, not necessary in this
example */
double **T, **T_new;

count = 0; /* keep track of number of datafiles read */
getdata("unknowns.dat", &n_x[0], &n_y[0], &count );
getdata("BC_types.dat", &n_x[1], &n_y[1], &count );
getdata("BC_values.dat", &n_x[2], &n_y[2], &count );

/* error-testing if number of rows+cols is the same in all files,
i.e: n_x[0] = n_x[1] = n_x[2] and the same for n_y */

double **T = malloc((n_y[0]+1)*sizeof(double*)); /* n_y = rows */
double **T_new = malloc((ny[0]+1)*sizeof(double*)); /* n_y = rows */

/*. . . . . .
.. . . . . . (later)
.. . . . . . */

T[0] = malloc((n_x[0]+1)*(n_y[0]+1)*sizeof(double)); /* nx= cols */
T_new[0] = malloc((n_x[0]+1)*(n_y[0]+1)*sizeof(double)); /* nx= cols */
}
void getdata(char *filename, unsigned *pCols, unsigned *pRows, int *count)
{
FILE *pFile;

unsigned rows, cols, oldcols;

printf("Opening file: %s.\n", filename);
if ( (pFile = 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);
}

*pRows = 0;
*pCols = 0;

/* get nx and ny */
cols = 0;
rows = 0;
if (countColsInNextLine(pFile, &oldcols, &rows) != EOF) { /* return
oldcols for first row */
rows++;
while (countColsInNextLine(pFile, &cols, &rows) != EOF) { /*
check row 2 -> EOF */
rows++;
if (cols != oldcols) { /* verify that number of cols didn't
change */
printf("ERROR: Number of columns is not a constant in
file: %s\n\n", filename);
printf("In line %u, the number of columns is %u
cols.\n", rows, cols);
printf("In the previous line it was counted to
%u.\n\nPlease fix this problem now.\n", oldcols);
exit(1);
}
}
}

if (cols != 0 && cols != oldcols) {
printf("ERROR: Line %u (last line) consisted of %u
columns.\nLine %u had %u columns.\n", rows, cols, rows-1, oldcols);
exit(1);
}

*pRows = rows; /* update results */
*pCols = oldcols;
(*count)++;

printf("Finished reading from file %s.\n\n", filename);
fclose(pFile); /* close input file, finished reading values in */
}

int countColsInNextLine (FILE *pFile, unsigned *pCols, unsigned *pRows)
{
int c;
unsigned cols = 0;

c = getc(pFile); /* get first character to start the loop */
do {
testwronginput(c, cols, *pRows);
if (c != EOF && !isspace(c)) { /* first time non-space
encountered, update cols */
cols++;
do { /* skip digits and commas, after first digit */
c = getc(pFile);
testwronginput(c, cols, *pRows);
} while (c != EOF && !isspace(c) || c == ',' || c == '.');
/* comma should also be valid input in number */
}
while (c != EOF && c != '\n' && isspace(c)) { /* skip through
blank spaces, but not '\n' ! */
c = getc(pFile);
testwronginput(c, cols, *pRows);
}
} while (c != EOF && c != '\n'); /* is the line finished or is EOF
reached? */

*pCols = cols;
return c;
}

void testwronginput(int c, unsigned cols, unsigned rows) /* I tried
isblank() but my system complained about it */
{
if (isalpha(c)) {
printf("Error! Alphabetic character '%c' encountered before
EOF\n", c);
printf("Last succesful location read was: Line %u, Column
%u\n", 1+rows, cols);
system("PAUSE"); /* give the user at chance to see this error
before the windows shuts down */
exit(1);
}
if (iscntrl(c) && c != 10) {
printf("Error! Control character '%c' encountered before
EOF\n", c);
printf("Last succesful location read was: Line %u, Column
%u\n", 1+rows, cols);
system("PAUSE"); /* give the user at chance to see this error
before the windows shuts down */
exit(1);
}
if (!isprint(c) && c != EOF && c != '\n') {
printf("Error! Non-printing character '%c' encountered before
EOF\n", c);
printf("Last succesful location read was: Line %u, Column
%u\n", 1+rows, cols);
system("PAUSE"); /* give the user at chance to see this error
before the windows shuts down */
exit(1);
}
}

-snip- Show the code. Your explanation is borderline meaningless.


See above.

Best regards / Med venlig hilsen
Martin Jørgensen

--
---------------------------------------------------------------------------
Home of Martin Jørgensen - http://www.martinjoergensen.dk
Mar 18 '06 #14

P: n/a
"Barry Schwarz" <sc******@doezl.net> skrev i en meddelelse
news:nj********************************@4ax.com...
-snip-
Show the code. Your explanation is borderline meaningless.


Ok, forget everything I wrote earlier... I just need to know how
to fix the following code (3 warnings, 2 errors).

- - - -- - -- - - - -- - --
#include <stdlib.h> /* system("PAUSE") */
#include <stdio.h>
#include <stddef.h>
#include <ctype.h> /* for isspace */

/* defintions */
#define max_input_files 3

/* more prototypes */
void getdata(char *filename, unsigned *pCols, unsigned *pRows,
int *count);
int countColsInNextLine(FILE *pFile, unsigned *pCols, unsigned
*pRows);
void testwronginput(int c, unsigned cols, unsigned rows);
int main(void)
{
/* read from file and get number of cols+rows */

unsigned count, n_x[max_input_files], n_y[max_input_files];
/* and a lot more var's, not necessary in this example */
double **T, **T_new;

count = 0; /* keep track of number of datafiles read */
getdata("inputfile1.dat", &n_x[0], &n_y[0], &count );
getdata("inputfile2.dat", &n_x[1], &n_y[1], &count );
if(n_x[0] != n_x[1] && n_y[0] != n_y[1])
exit(1);
getdata("inputfile3.dat", &n_x[2], &n_y[2], &count );
if(n_x[1] != n_x[2] && n_y[1] != n_y[2])
exit(1);

double **T = malloc((n_y[0]+1)*sizeof(double*)); /* n_y =
rows */
double **T_new = malloc((n_y[0]+1)*sizeof(double*)); /* n_y =
rows */

T[0] = malloc((n_x[0]+1)*(n_y[0]+1)*sizeof(double)); /* nx=
cols */
T_new[0] = malloc((n_x[0]+1)*(n_y[0]+1)*sizeof(double)); /*
nx= cols */

/* eventually test with T[4][6] = 959, and printf("%lf",
T[4][6]); etc... */
}
void getdata(char *filename, unsigned *pCols, unsigned *pRows,
int *count)
{
FILE *pFile;

unsigned rows, cols, oldcols;

printf("Opening file: %s.\n", filename);
if ( (pFile = 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);
}

*pRows = 0;
*pCols = 0;

/* get nx and ny */
cols = 0;
rows = 0;
if (countColsInNextLine(pFile, &oldcols, &rows) != EOF) { /*
return
oldcols
for first row */
rows++;
while (countColsInNextLine(pFile, &cols, &rows) != EOF)
{ /*

check row 2 -> EOF */
rows++;
if (cols != oldcols) { /* verify that number of cols
didn't
change */
printf("ERROR: Number of columns is not a
constant in file: %s\n\n", filename);
printf("In line %u, the number of columns is %u cols.\n",
rows, cols);
printf("In the previous line it was counted to
%u.\n\nPlease fix this problem now.\n", oldcols);
exit(1);
}
}
}

if (cols != 0 && cols != oldcols) {
printf("ERROR: Line %u (last line) consisted of %u
columns.\nLine %u had %u columns.\n", rows, cols, rows-1,
oldcols);
exit(1);
}

*pRows = rows; /* update results */
*pCols = oldcols;
(*count)++;

printf("Finished reading from file %s.\n\n", filename);
fclose(pFile); /* close input file, finished reading values
in */
}

int countColsInNextLine (FILE *pFile, unsigned *pCols, unsigned
*pRows)
{
int c;
unsigned cols = 0;

c = getc(pFile); /* get first character to start the loop */
do {
testwronginput(c, cols, *pRows);
if (c != EOF && !isspace(c)) { /* first time non-space
encountered, update cols */
cols++;
do { /* skip digits and commas, after first digit
*/
c = getc(pFile);
testwronginput(c, cols, *pRows);
} while (c != EOF && !isspace(c) || c == ',' || c ==
'.');
/* comma should also be valid input in number */
}
while (c != EOF && c != '\n' && isspace(c)) { /* skip
through
blank
spaces, but not '\n' ! */
c = getc(pFile);
testwronginput(c, cols, *pRows);
}
} while (c != EOF && c != '\n'); /* is the line finished or
is EOF
reached? */

*pCols = cols;
return c;
}

void testwronginput(int c, unsigned cols, unsigned rows) /* I
tried isblank() but my system complained about it */
{
if (isalpha(c)) {
printf("Error! Alphabetic character '%c' encountered
before EOF\n", c);
printf("Last succesful location read was: Line %u,
Column %u\n", 1+rows, cols);
system("PAUSE"); /* give the user at chance to see
this error
before the windows shuts down */
exit(1);
}
if (iscntrl(c) && c != 10) {
printf("Error! Control character '%c' encountered before
EOF\n", c);
printf("Last succesful location read was: Line %u,
Column %u\n", 1+rows, cols);
system("PAUSE"); /* give the user at chance to see
this error before the windows shuts down */
exit(1);
}
if (!isprint(c) && c != EOF && c != '\n') {
printf("Error! Non-printing character '%c' encountered
before EOF\n", c);
printf("Last succesful location read was: Line %u,
Column %u\n", 1+rows, cols);
system("PAUSE"); /* give the user at chance to see
this error
before the windows shuts down */
exit(1);
}
}

- - - -- - -- - - - -- - --

Compiler complaints:

int * differes in indirection.... Missing ';' before 'type....
Best regards / Med venlig hilsen
Martin Jørgensen

--
---------------------------------------------------------------------------
Home of Martin Jørgensen - http://www.martinjoergensen.dk

Mar 18 '06 #15

P: n/a
Mark F. Haigh wrote:
Martin Jørgensen wrote:
Michael Mair wrote:
-snip-

Cheers
Michael


Do you like my new program?

<snip>

Here's some help. Compile this small program, and run it with the
filename of your .dat file as the command line argument. Try all the
cases you can think of, and see how the error handling works.


Hi Mark,

Thanks a lot for bringing another way of solving this problem... But I
already solved this problem, so imagine changing your program such that
i use malloc to initialize a new 2D array called T_new (untested):
int main(int argc, char *argv[])
{
FILE *fp;
int rows, cols;
enum Error result;
const char *file;
int ret = EXIT_FAILURE;
char buf[8];

/* Open the data file (filename is fixed). */
fp = fopen("testfile.dat", "r");
if(fp == NULL) {
printf("Error: cannot open %s.\n", file);
return ret;
}

/* Try to parse the file, then interpret the result. */
result = parse(fp, &rows, &cols);
if(result != Success) {
printf("Error in input file\n");
exit(1)
}

/* this is the what I want: using number of cols+rows for malloc */
double **T_new = malloc((rows+1)*sizeof(double*));
T_new[0] = malloc((cols*rows)*sizeof(double));

/* test: assuming input file has more than 4 rows and 5 columns */
T_new[4][5] = 431.56;
printf("test-value = %lf", T_new[4][5]");

/* Clean up and exit */
fclose(fp);
return ret;
}

- - - - - - - - - - - -

Since I already solved this problem (and my solution can also take files
with double input elements such as 425,358 or 823.23 as individual
elements, I didn't tested the above)... But you code is really nice to
learn from, and very logically structured. I like that... It gives me
som new ideas for future ways of solving problems.

.... The above is just so you know what I'm asking for, in case you want
to try and solve the problem... I just sended some "ready-to-go
copy/paste code" to Barry Schwarz (18/3-06, time:16:04, but it didn't
show up yet) that show I want to take the result from what corresponds
to your variables called cols and rows, to malloc a 2D-array...
Best regards / Med venlig hilsen
Martin Jørgensen

--
---------------------------------------------------------------------------
Home of Martin Jørgensen - http://www.martinjoergensen.dk
Mar 18 '06 #16

P: n/a
On Sat, 18 Mar 2006 16:04:24 +0100, "Martin Joergensen"
<un*********@spam.jay.net> wrote:
Ok, forget everything I wrote earlier... I just need to know how
to fix the following code (3 warnings, 2 errors).
You show exactly two diagnostics at the very bottom of 200 lines of
extremely poorly formatted code. You don't provide the complete
error message and you don't identify to which lines the errors relate.
(or if you did it was buried in your code to the point of
invisibility). You need to give us a fighting chance to help you. Try
all of the following:
Limit your line length so your posting software does not break
things up at an inconvenient place.
Limit your use of vertical white space.
Indent in a very consistent fashion, four characters usually
works well.

- - - -- - -- - - - -- - --
#include <stdlib.h> /* system("PAUSE") */
#include <stdio.h>
#include <stddef.h>
#include <ctype.h> /* for isspace */

/* defintions */
#define max_input_files 3
It is a common convention to code your #define in all caps. Just
something to make it easier to read.

/* more prototypes */
void getdata(char *filename, unsigned *pCols, unsigned *pRows,
int *count);
int countColsInNextLine(FILE *pFile, unsigned *pCols, unsigned
*pRows);
void testwronginput(int c, unsigned cols, unsigned rows);
int main(void)
{
/* read from file and get number of cols+rows */

unsigned count, n_x[max_input_files], n_y[max_input_files];
/* and a lot more var's, not necessary in this example */
double **T, **T_new;

count = 0; /* keep track of number of datafiles read */
getdata("inputfile1.dat", &n_x[0], &n_y[0], &count );
getdata("inputfile2.dat", &n_x[1], &n_y[1], &count );
if(n_x[0] != n_x[1] && n_y[0] != n_y[1])
Did you mean "and" or "or" here? If either mismatches do you quit or
do you quit only if both mismatch?
exit(1);
getdata("inputfile3.dat", &n_x[2], &n_y[2], &count );
if(n_x[1] != n_x[2] && n_y[1] != n_y[2])
exit(1);

double **T = malloc((n_y[0]+1)*sizeof(double*)); /* n_y =
rows */
It will save you problems later on if you use sizeof *T.
double **T_new = malloc((n_y[0]+1)*sizeof(double*)); /* n_y =
rows */

T[0] = malloc((n_x[0]+1)*(n_y[0]+1)*sizeof(double)); /* nx=
cols */
And sizeof *T[0] here.
T_new[0] = malloc((n_x[0]+1)*(n_y[0]+1)*sizeof(double)); /*
nx= cols */

/* eventually test with T[4][6] = 959, and printf("%lf",
T[4][6]); etc... */
}
void getdata(char *filename, unsigned *pCols, unsigned *pRows,
int *count)
{
FILE *pFile;

unsigned rows, cols, oldcols;

printf("Opening file: %s.\n", filename);
if ( (pFile = 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);
Use EXIT_FAILURE instead of 1 for portability.
}

*pRows = 0;
*pCols = 0;

/* get nx and ny */
cols = 0;
rows = 0;
if (countColsInNextLine(pFile, &oldcols, &rows) != EOF) { /*
return
oldcols
for first row */
What did that look like on your system????
rows++;
while (countColsInNextLine(pFile, &cols, &rows) != EOF)
Since you increment rows above, did you really intend for function
count... to change its value also? But count... does not change rows.
Why do you define the function to take a pointer when it really wants
the value pointed to?
{ /*

check row 2 -> EOF */
rows++;
if (cols != oldcols) { /* verify that number of cols
didn't
change */
At this point in time (first iteration of while loop), oldcols has not
been initialized.
printf("ERROR: Number of columns is not a
constant in file: %s\n\n", filename);
printf("In line %u, the number of columns is %u cols.\n",
rows, cols);
printf("In the previous line it was counted to
%u.\n\nPlease fix this problem now.\n", oldcols);
exit(1);
}
}
}

if (cols != 0 && cols != oldcols) {
printf("ERROR: Line %u (last line) consisted of %u
columns.\nLine %u had %u columns.\n", rows, cols, rows-1,
oldcols);
exit(1);
}

*pRows = rows; /* update results */
*pCols = oldcols;
(*count)++;

printf("Finished reading from file %s.\n\n", filename);
fclose(pFile); /* close input file, finished reading values
in */
}

int countColsInNextLine (FILE *pFile, unsigned *pCols, unsigned
*pRows)
{
int c;
unsigned cols = 0;

c = getc(pFile); /* get first character to start the loop */
do {
testwronginput(c, cols, *pRows);
if (c != EOF && !isspace(c)) { /* first time non-space
encountered, update cols */
cols++;
do { /* skip digits and commas, after first digit
*/
c = getc(pFile);
testwronginput(c, cols, *pRows);
} while (c != EOF && !isspace(c) || c == ',' || c ==
'.');
Since && has higher precedence that ||, this is treated as
(c != EOF && !isspace(c)) || (c == ',') || (c == '.')
This is an A or B or C expression. If A is true, B and C will never
be evaluated (called a short circuit evaluation). Consider either of
the last two tests. If either is true, is it possible for A to be
false? Obviously not. If A is false, c is either EOF (and B and C
are both false also) or c is whitespace (and B and C are both false
also). The bottom line is that B and C contribute nothing but a
confusion factor. The truth of falseness of the expression is
completely determined by A.
/* comma should also be valid input in number */
Rather than trying to validate a numerical value yourself, you might
consider using strtod to do the work for you. I think it will
properly handle the decimal marker (, or .) based on locale.
}
while (c != EOF && c != '\n' && isspace(c)) { /* skip
through
blank
spaces, but not '\n' ! */
c = getc(pFile);
testwronginput(c, cols, *pRows);
}
} while (c != EOF && c != '\n'); /* is the line finished or
is EOF
reached? */

*pCols = cols;
return c;
}

void testwronginput(int c, unsigned cols, unsigned rows) /* I
tried isblank() but my system complained about it */
There is no isblank. If you want to test for blank, use ' '. If you
want to test for whitespace, use isspace.
{
if (isalpha(c)) {
printf("Error! Alphabetic character '%c' encountered
before EOF\n", c);
printf("Last succesful location read was: Line %u,
Column %u\n", 1+rows, cols);
system("PAUSE"); /* give the user at chance to see
this error
before the windows shuts down */
exit(1);
}
if (iscntrl(c) && c != 10) {
What is 10? It may be \n on your system but it isn't on mine. Don't
use magic ascii codes. Use the escape sequence if you can.
printf("Error! Control character '%c' encountered before
EOF\n", c);
By definition, control character will not print with %c. Use %d so
the user can determine which control character was found.
printf("Last succesful location read was: Line %u,
Column %u\n", 1+rows, cols);
system("PAUSE"); /* give the user at chance to see
this error before the windows shuts down */
exit(1);
}
if (!isprint(c) && c != EOF && c != '\n') {
printf("Error! Non-printing character '%c' encountered
before EOF\n", c);
A non-printing won't display properly with %c. Use %d here also.
printf("Last succesful location read was: Line %u,
Column %u\n", 1+rows, cols);
system("PAUSE"); /* give the user at chance to see
this error
before the windows shuts down */
exit(1);
}
}

- - - -- - -- - - - -- - --

Compiler complaints:

int * differes in indirection.... Missing ';' before 'type....
Sorry, your formatting makes it impossible to compile your code and I
didn't spot these in my review.


Best regards / Med venlig hilsen
Martin Jørgensen

Remove del for email
Mar 18 '06 #17

P: n/a
Martin Joergensen wrote:
Ok, forget everything I wrote earlier... I just need to know how
to fix the following code (3 warnings, 2 errors).


I copied lines with problems and inserted a `#ifdef pmg` to the
changed lines. After a few compilation runs gcc output is

$ c90 -Dpmg foo.c
foo.c: In function `countColsInNextLine':
foo.c:135: warning: suggest parentheses around && within ||
if I don't define pmg (so it's the code you posted), gcc output is

$ c90 foo.c
foo.c: In function `main':
foo.c:42: warning: pointer targets in passing arg 4 of `getdata' differ in signedness
foo.c:43: warning: pointer targets in passing arg 4 of `getdata' differ in signedness
foo.c:47: warning: pointer targets in passing arg 4 of `getdata' differ in signedness
foo.c:56: error: redeclaration of `T'
foo.c:39: error: `T' previously declared here
foo.c:56: warning: ISO C89 forbids mixed declarations and code
foo.c:57: error: redeclaration of `T_new'
foo.c:39: error: `T_new' previously declared here
foo.c:39: warning: unused variable `T'
foo.c:39: warning: unused variable `T_new'
foo.c: In function `countColsInNextLine':
foo.c:135: warning: suggest parentheses around && within ||

Will you provide a working email address so that I can
mail you my changes?

--
If you're posting through Google read <http://cfaj.freeshell.org/google>
Mar 19 '06 #18

P: n/a
Pedro Graca wrote:
Martin Joergensen wrote:
Ok, forget everything I wrote earlier... I just need to know how
to fix the following code (3 warnings, 2 errors).

I copied lines with problems and inserted a `#ifdef pmg` to the
changed lines. After a few compilation runs gcc output is


Ok, but what is pmg?
$ c90 -Dpmg foo.c
foo.c: In function `countColsInNextLine':
foo.c:135: warning: suggest parentheses around && within ||
if I don't define pmg (so it's the code you posted), gcc output is

$ c90 foo.c
foo.c: In function `main':
foo.c:42: warning: pointer targets in passing arg 4 of `getdata' differ in signedness
foo.c:43: warning: pointer targets in passing arg 4 of `getdata' differ in signedness
foo.c:47: warning: pointer targets in passing arg 4 of `getdata' differ in signedness
foo.c:56: error: redeclaration of `T'
foo.c:39: error: `T' previously declared here
foo.c:56: warning: ISO C89 forbids mixed declarations and code
foo.c:57: error: redeclaration of `T_new'
foo.c:39: error: `T_new' previously declared here
foo.c:39: warning: unused variable `T'
foo.c:39: warning: unused variable `T_new'
foo.c: In function `countColsInNextLine':
foo.c:135: warning: suggest parentheses around && within ||

Will you provide a working email address so that I can
mail you my changes?


Sure, or else you could just post it here... But just remove ".spam"
before the @ and remove "spam." after the "@" - that's my e-mail address
(I just did it that way to avoid the spam robots, so please don't post
the full address without "concealment"). At this moment, I don't get
spam to that address and I would like it to be that way, if possible.
Best regards / Med venlig hilsen
Martin Jørgensen

--
---------------------------------------------------------------------------
Home of Martin Jørgensen - http://www.martinjoergensen.dk
Mar 19 '06 #19

P: n/a
Martin Jørgensen wrote:
<snip>
Thanks a lot for bringing another way of solving this problem... But I
already solved this problem, so imagine changing your program such that
i use malloc to initialize a new 2D array called T_new (untested):
<code snipped>
Since I already solved this problem [...]
I certainly don't think you've solved the problem. In fact, I'm not
even convinced you've managed to state the problem coherently. The
code you've posted thus far is confused, not robust, and
unmaintainable.

Don't be offended. Nobody is born knowing C. You're making a
sustained effort, and that is why we're willing to spend time to help.

There's a lot of things we don't know about what you're trying to do.
But we do know that:

1. You are a student, and this may be a homework assignment. If this
is the case, you're trying to learn how to use C to solve real-world
problems. So we can conclude that you should be working hard to make
your program more clear, robust, and maintainable so that you learn a
lot about C, and as a result, get a good grade.

Or...

2. You are writing a program that you hope others will find useful.
If this is the case, you need to ensure that your program is robust (a
non-robust program is not very useful) and clearly-written and
maintainable (so that other people can understand how the program
works, and can extend it or fix bugs in it).

Either way, you need to work toward the same goals of clarity,
robustness, and maintainability. A solution that does not address all
of these is not a solution at all.
(and my solution can also take files
with double input elements such as 425,358 or 823.23 as individual
elements, I didn't tested the above)... But you code is really nice to
learn from, and very logically structured. I like that... It gives me
som new ideas for future ways of solving problems.


Because you have not assured us that your problem is not homework, I'm
not going to post code that does exactly what you need. It's just a
push in the right direction, and is easily extendable to do exactly
what you need.

Notice that nowhere have you:

1. Described concisely the format of the file you wish to be able to
parse. Do you control the file format? Or is it generated by another
program not under your control?

2. Described what you wish to do with the file. What's the point of
this exercise? What's the big picture? I take it you want to read it
into a multidimensional array so you can manipulate it somehow. What
for?

You have to help us so we can help you. We're not mind readers!

<snip>

Mark F. Haigh
mf*****@sbcglobal.net

Mar 19 '06 #20

P: n/a
Barry Schwarz wrote:
On Sat, 18 Mar 2006 16:04:24 +0100, "Martin Joergensen"
<un*********@spam.jay.net> wrote:

Ok, forget everything I wrote earlier... I just need to know how
to fix the following code (3 warnings, 2 errors).

You show exactly two diagnostics at the very bottom of 200 lines of
extremely poorly formatted code. You don't provide the complete


Just look what's inside main().
error message and you don't identify to which lines the errors relate.
Well, I can't imagine it is so difficult to copy/paste the code and see
for yourself. I also didn't know that outlook apparently screwed up the
formatting again, since I haven't posted that many posts in this group,
as I'm still learning the C-language. Still it should just be a few
lines where you remove the extra return that outlook inserted.
(or if you did it was buried in your code to the point of
invisibility). You need to give us a fighting chance to help you. Try
all of the following:
Limit your line length so your posting software does not break
things up at an inconvenient place.
I've heard that before. And now I think that's a stupid advice. The
point is that I *shouldn't* limit the line length because then you get
these errors that you're complaining about here. Your news reader should
just wrap the lines if they're too long.
Limit your use of vertical white space.
Indent in a very consistent fashion, four characters usually
works well.
This *IS* 4 characters.
- - - -- - -- - - - -- - --
#include <stdlib.h> /* system("PAUSE") */
#include <stdio.h>
#include <stddef.h>
#include <ctype.h> /* for isspace */

/* defintions */
#define max_input_files 3

It is a common convention to code your #define in all caps. Just
something to make it easier to read.


Ok.
/* more prototypes */
void getdata(char *filename, unsigned *pCols, unsigned *pRows,
int *count);
int countColsInNextLine(FILE *pFile, unsigned *pCols, unsigned
*pRows);
void testwronginput(int c, unsigned cols, unsigned rows);
int main(void)
{
/* read from file and get number of cols+rows */

unsigned count, n_x[max_input_files], n_y[max_input_files];
/* and a lot more var's, not necessary in this example */
double **T, **T_new;

count = 0; /* keep track of number of datafiles read */
getdata("inputfile1.dat", &n_x[0], &n_y[0], &count );
getdata("inputfile2.dat", &n_x[1], &n_y[1], &count );
if(n_x[0] != n_x[1] && n_y[0] != n_y[1])

Did you mean "and" or "or" here? If either mismatches do you quit or
do you quit only if both mismatch?


Sorry, I meant "or", but that's not the important thing here.
exit(1);
getdata("inputfile3.dat", &n_x[2], &n_y[2], &count );
if(n_x[1] != n_x[2] && n_y[1] != n_y[2])
exit(1);

double **T = malloc((n_y[0]+1)*sizeof(double*)); /* n_y =
rows */

It will save you problems later on if you use sizeof *T.


Ok, thanks.
double **T_new = malloc((n_y[0]+1)*sizeof(double*)); /* n_y =
rows */

T[0] = malloc((n_x[0]+1)*(n_y[0]+1)*sizeof(double)); /* nx=
cols */

And sizeof *T[0] here.


Yes.
T_new[0] = malloc((n_x[0]+1)*(n_y[0]+1)*sizeof(double)); /*
nx= cols */

/* eventually test with T[4][6] = 959, and printf("%lf",
T[4][6]); etc... */
}
void getdata(char *filename, unsigned *pCols, unsigned *pRows,
int *count)
{
FILE *pFile;

unsigned rows, cols, oldcols;

printf("Opening file: %s.\n", filename);
if ( (pFile = 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);

Use EXIT_FAILURE instead of 1 for portability.


Ok, but still that's not the important thing here.
}

*pRows = 0;
*pCols = 0;

/* get nx and ny */
cols = 0;
rows = 0;
if (countColsInNextLine(pFile, &oldcols, &rows) != EOF) { /*
return
oldcols
for first row */

What did that look like on your system????


It looked fine until I saw your reply.
rows++;
while (countColsInNextLine(pFile, &cols, &rows) != EOF)

Since you increment rows above, did you really intend for function
count... to change its value also? But count... does not change rows.


Why are you talking about the "count" variable in those two lines? If
you want, you can go back to message-ID <31************@news.tdc.dk> and
run the code from there. Still, this is not the relevant part, and the
above should be okay - at least it has worked before.
Why do you define the function to take a pointer when it really wants
the value pointed to?
Because it needs to change the values. If you want to make it another
way, that's fine but not the most important thing here since the code
worked before (see message-ID shown before).
{ /*

check row 2 -> EOF */
rows++;
if (cols != oldcols) { /* verify that number of cols
didn't
change */

At this point in time (first iteration of while loop), oldcols has not
been initialized.


Wrong. It was initialized just before that, here:

if (countColsInNextLine(pFile, &oldcols, &rows) != EOF)

But still, that is not relevant. What is relevant, is that I would like
the code to compile.
printf("ERROR: Number of columns is not a
constant in file: %s\n\n", filename);
printf("In line %u, the number of columns is %u cols.\n",
rows, cols);
printf("In the previous line it was counted to
%u.\n\nPlease fix this problem now.\n", oldcols);
exit(1);
}
}
}

if (cols != 0 && cols != oldcols) {
printf("ERROR: Line %u (last line) consisted of %u
columns.\nLine %u had %u columns.\n", rows, cols, rows-1,
oldcols);
exit(1);
}

*pRows = rows; /* update results */
*pCols = oldcols;
(*count)++;

printf("Finished reading from file %s.\n\n", filename);
fclose(pFile); /* close input file, finished reading values
in */
}

int countColsInNextLine (FILE *pFile, unsigned *pCols, unsigned
*pRows)
{
int c;
unsigned cols = 0;

c = getc(pFile); /* get first character to start the loop */
do {
testwronginput(c, cols, *pRows);
if (c != EOF && !isspace(c)) { /* first time non-space
encountered, update cols */
cols++;
do { /* skip digits and commas, after first digit
*/
c = getc(pFile);
testwronginput(c, cols, *pRows);
} while (c != EOF && !isspace(c) || c == ',' || c ==
'.');

Since && has higher precedence that ||, this is treated as
(c != EOF && !isspace(c)) || (c == ',') || (c == '.')
This is an A or B or C expression. If A is true, B and C will never
be evaluated (called a short circuit evaluation). Consider either of
the last two tests. If either is true, is it possible for A to be
false? Obviously not. If A is false, c is either EOF (and B and C
are both false also) or c is whitespace (and B and C are both false


Damn, you're right. I think there's something wrong there... Perhaps it
should rather be while (c != EOF || isspace(c) || c == ',' || c == '.');
also). The bottom line is that B and C contribute nothing but a
confusion factor. The truth of falseness of the expression is
completely determined by A.

/* comma should also be valid input in number */

Rather than trying to validate a numerical value yourself, you might
consider using strtod to do the work for you. I think it will
properly handle the decimal marker (, or .) based on locale.


Sure it will? Still, not so important since the code worked in the
message-ID I gave you earlier in this post.
}
while (c != EOF && c != '\n' && isspace(c)) { /* skip
through
blank
spaces, but not '\n' ! */
c = getc(pFile);
testwronginput(c, cols, *pRows);
}
} while (c != EOF && c != '\n'); /* is the line finished or
is EOF
reached? */

*pCols = cols;
return c;
}

void testwronginput(int c, unsigned cols, unsigned rows) /* I
tried isblank() but my system complained about it */

There is no isblank. If you want to test for blank, use ' '. If you
want to test for whitespace, use isspace.


Well, there is on p.229 in "C primer plus". But not on my system.
{
if (isalpha(c)) {
printf("Error! Alphabetic character '%c' encountered
before EOF\n", c);
printf("Last succesful location read was: Line %u,
Column %u\n", 1+rows, cols);
system("PAUSE"); /* give the user at chance to see
this error
before the windows shuts down */
exit(1);
}
if (iscntrl(c) && c != 10) {

What is 10? It may be \n on your system but it isn't on mine. Don't
use magic ascii codes. Use the escape sequence if you can.


Ok. I'll see if I can remember it. I just saw in the debugger that I
think scanf left a 10 in the buffer and if I didn't put this here, it
would have taken that as a control character and stop the program.
printf("Error! Control character '%c' encountered before
EOF\n", c);

By definition, control character will not print with %c. Use %d so
the user can determine which control character was found.


Ok, still not important.
printf("Last succesful location read was: Line %u,
Column %u\n", 1+rows, cols);
system("PAUSE"); /* give the user at chance to see
this error before the windows shuts down */
exit(1);
}
if (!isprint(c) && c != EOF && c != '\n') {
printf("Error! Non-printing character '%c' encountered
before EOF\n", c);

A non-printing won't display properly with %c. Use %d here also.


Ok, still not important to me.
printf("Last succesful location read was: Line %u,
Column %u\n", 1+rows, cols);
system("PAUSE"); /* give the user at chance to see
this error
before the windows shuts down */
exit(1);
}
}

- - - -- - -- - - - -- - --

Compiler complaints:

int * differes in indirection.... Missing ';' before 'type....

Sorry, your formatting makes it impossible to compile your code and I
didn't spot these in my review.


I'll post the code again so you should just copy/paste and this time I
copy/paste the code to my macintosh computer and post it from
Thunderbird instead of outlook. I think that'll have this effect that
the lines will not be broken stupid places and then your compiler should
get about the same errors and warnings as me I hope.
Best regards / Med venlig hilsen
Martin Jørgensen

--
---------------------------------------------------------------------------
Home of Martin Jørgensen - http://www.martinjoergensen.dk
Mar 19 '06 #21

P: n/a
Barry Schwarz wrote:
On Sat, 18 Mar 2006 16:04:24 +0100, "Martin Joergensen"

.... snip ...

void testwronginput(int c, unsigned cols, unsigned rows) /* I
tried isblank() but my system complained about it */


There is no isblank. If you want to test for blank, use ' '.
If you want to test for whitespace, use isspace.


Yes there is, in C99. From N1124 (missing in N869):

7.4.1.3 The isblank function

Synopsis

1 #include <ctype.h>

int isblank(int c);

Description

2 The isblank function tests for any character that is a
standard blank character or is one of a locale-specific set
of characters for which isspace is true and that is used to
separate words within a line of text. The standard blank
characters are the following:

space (' '), and horizontal tab ('\t').

In the "C" locale, isblank returns true only for the standard
blank characters.

--
"If you want to post a followup via groups.google.com, don't use
the broken "Reply" link at the bottom of the article. Click on
"show options" at the top of the article, then click on the
"Reply" at the bottom of the article headers." - Keith Thompson
More details at: <http://cfaj.freeshell.org/google/>
Also see <http://www.safalra.com/special/googlegroupsreply/>
Mar 19 '06 #22

P: n/a
Martin Jørgensen wrote:
Pedro Graca wrote:
I copied lines with problems and inserted a `#ifdef pmg` to the
changed lines. After a few compilation runs gcc output is
Ok, but what is pmg?


Just my initials. I use them to easily identify changes I make to code.

#ifdef pmg
int main(void)
#else
void main()
#endif

or

int main(void) /* pmg: was void main() */
Will you provide a working email address so that I can
mail you my changes?


[...] or else you could just post it here...

.... I'll post the snippets I changed ...

// ...

/* more prototypes */
#ifdef pmg
void getdata(char *filename, unsigned *pCols, unsigned *pRows, unsigned *count);
#else
void getdata(char *filename, unsigned *pCols, unsigned *pRows, int *count);
#endif

// ...

#ifdef pmg
T = malloc((n_y[0]+1) * sizeof *T); /* n_y = rows */
T_new = malloc((n_y[0]+1) * sizeof *T_new); /* n_y = rows */
#else
double **T = malloc((n_y[0]+1)*sizeof(double*)); /* n_y = rows */
double **T_new = malloc((n_y[0]+1)*sizeof(double*)); /* n_y = rows */
#endif
#ifdef pmg
T[0] = malloc((n_x[0]+1)*(n_y[0]+1) * sizeof *T[0]); /* nx= cols */
T_new[0] = malloc((n_x[0]+1)*(n_y[0]+1) * sizeof *T[0]); /* nx= cols */
#else
T[0] = malloc((n_x[0]+1)*(n_y[0]+1)*sizeof(double)); /* nx= cols */
T_new[0] = malloc((n_x[0]+1)*(n_y[0]+1)*sizeof(double)); /* nx= cols */
#endif
/* eventually test with T[4][6] = 959, and printf("%lf", T[4][6]); etc... */
#ifdef pmg
return 0;
#else
#endif
}

#ifdef pmg
void getdata(char *filename, unsigned *pCols, unsigned *pRows, unsigned *count) {
#else
void getdata(char *filename, unsigned *pCols, unsigned *pRows, int *count) {
#endif

// ...
just remove ".spam"
before the @ and remove "spam." after the "@" - that's my e-mail address At this moment, I don't get
spam to that address and I would like it to be that way, if possible.


I sent the full code to your email address. Please excuse me for asking
for the email address; somehow it never occurred to me to remove the
spams from the address you use and try that.

--
If you're posting through Google read <http://cfaj.freeshell.org/google>
Mar 19 '06 #23

P: n/a
Martin Jørgensen wrote:
Barry Schwarz wrote:
"Martin Joergensen" <un*********@spam.jay.net> wrote:
Ok, forget everything I wrote earlier... I just need to know how
to fix the following code (3 warnings, 2 errors).


You show exactly two diagnostics at the very bottom of 200 lines of
extremely poorly formatted code. You don't provide the complete


Just look what's inside main().
error message and you don't identify to which lines the errors relate.


Well, I can't imagine it is so difficult to copy/paste the code
and see for yourself. I also didn't know that outlook apparently
screwed up the formatting again, since I haven't posted that many
posts in this group, as I'm still learning the C-language. Still
it should just be a few lines where you remove the extra return
that outlook inserted.


If (you can't go to the trouble of making your posts easily
readable and usable, by doing such things as proper code
indentation, using spaces in place of tabs, restricting line length
to about 65 (maybe 72), using /**/ comments only) THEN:

we can't be bothered reading it.

--
"If you want to post a followup via groups.google.com, don't use
the broken "Reply" link at the bottom of the article. Click on
"show options" at the top of the article, then click on the
"Reply" at the bottom of the article headers." - Keith Thompson
More details at: <http://cfaj.freeshell.org/google/>
Also see <http://www.safalra.com/special/googlegroupsreply/>

Mar 19 '06 #24

P: n/a
Martin Jørgensen <un*********@spam.jay.net> writes:
Barry Schwarz wrote:

[...]
You need to give us a fighting chance to help you. Try all of the
following:
Limit your line length so your posting software does not break
things up at an inconvenient place.


I've heard that before. And now I think that's a stupid advice. The
point is that I *shouldn't* limit the line length because then you get
these errors that you're complaining about here. Your news reader
should just wrap the lines if they're too long.


That's the problem. If you post code with very long lines, some
software somewhere between your computer and mine is likely to wrap
the lines. If a line is wrapped in the middle of a string literal,
the result will not compile.

Keep any code you post below 72 columns. Use only spaces, not tabs.

And be very careful throwing around words like "stupid".

--
Keith Thompson (The_Other_Keith) ks***@mib.org <http://www.ghoti.net/~kst>
San Diego Supercomputer Center <*> <http://users.sdsc.edu/~kst>
We must do something. This is something. Therefore, we must do this.
Mar 19 '06 #25

P: n/a
Barry Schwarz wrote:
On Sat, 18 Mar 2006 16:04:24 +0100, "Martin Joergensen"
<un*********@spam.jay.net> wrote: -snip-
Sorry, your formatting makes it impossible to compile your code and I
didn't spot these in my review.


Okay, forget about this wrapping thing. Guess you're right. I just can't
restrict Visual studio from making lines longer than 65 characters or
so. I went through all the options and help. The following should be
better in that I don't think it inserts ekstra linebreaks in places
never intended to have linebreaks. So what's important is what's inside
main() and I hope that copy/pasting should work - I manually fixed some
comments etc.

- - - - - -- - - - -- -
#include <stdlib.h> /* system("PAUSE") */
#include <stdio.h>
#include <stddef.h>
#include <ctype.h> /* for isspace */

/* defintions */
#define max_input_files 3

/* more prototypes */
void getdata(char *filename, unsigned *pCols, unsigned *pRows, int *count);
int countColsInNextLine(FILE *pFile, unsigned *pCols, unsigned *pRows);
void testwronginput(int c, unsigned cols, unsigned rows);
int main(void)
{
/* read from file and get number of cols+rows */

unsigned count, n_x[max_input_files], n_y[max_input_files];
/* and a lot more var's, not necessary in this example */
double **T, **T_new;

count = 0; /* keep track of number of datafiles read */
getdata("inputfile1.dat", &n_x[0], &n_y[0], &count );
getdata("inputfile2.dat", &n_x[1], &n_y[1], &count );
if(n_x[0] != n_x[1] && n_y[0] != n_y[1])
exit(1);
getdata("inputfile3.dat", &n_x[2], &n_y[2], &count );
if(n_x[1] != n_x[2] && n_y[1] != n_y[2])
exit(1);

double **T = malloc((n_y[0]+1)*sizeof(double*)); /* n_y = rows */
double **T_new = malloc((n_y[0]+1)*sizeof(double*)); /* n_y = rows */

T[0] = malloc((n_x[0]+1)*(n_y[0]+1)*sizeof(double)); /* nx= cols */
T_new[0] = malloc((n_x[0]+1)*(n_y[0]+1)*sizeof(double)); /* nx= cols */
}

void getdata(char *filename, unsigned *pCols, unsigned *pRows, int *count)
{
FILE *pFile;

unsigned rows, cols, oldcols;

printf("Opening file: %s.\n", filename);
if ( (pFile = fopen(filename, "r") ) == NULL)
{
printf("Cannot open file %s.\n", filename);
/* give the user at chance to see this error before the windows
shuts down */
system("PAUSE");
exit(1);
}

*pRows = 0;
*pCols = 0;

/* get nx and ny */
cols = 0;
rows = 0;
/* return oldcols for first row */
if (countColsInNextLine(pFile, &oldcols, &rows) != EOF) {
rows++;
/* check row 2 -> EOF */
while (countColsInNextLine(pFile, &cols, &rows) != EOF) {
rows++;
/* verify that number of cols didn't change */
if (cols != oldcols) {
printf("ERROR: Number of columns is not a constant in
file: %s\n\n", filename);
printf("In line %u, the number of columns is %u
cols.\n", rows, cols);
printf("In the previous line it was counted to
%u.\n\nPlease fix this problem now.\n", oldcols);
exit(1);
}
}
}

if (cols != 0 && cols != oldcols) {
printf("ERROR: Line %u (last line) consisted of %u columns.\n");
printf("Line %u had %u columns.\n", rows, cols, rows-1, oldcols);
exit(1);
}

*pRows = rows; /* update results */
*pCols = oldcols;
(*count)++;

printf("Finished reading from file %s.\n\n", filename);
fclose(pFile); /* close input file, finished reading values in */
}
int countColsInNextLine (FILE *pFile, unsigned *pCols, unsigned *pRows)
{
int c;
unsigned cols = 0;

c = getc(pFile); /* get first character to start the loop */
do {
testwronginput(c, cols, *pRows);
/* first time non-space encountered, update cols */
if (c != EOF && !isspace(c)) {
cols++;
/* skip digits and commas, after first digit */
do {
c = getc(pFile);
testwronginput(c, cols, *pRows);
} while (c != EOF || isspace(c) || c == ',' || c == '.');
/* comma should also be valid input in number */
}
/* skip through blank spaces, but not '\n' ! */
while (c != EOF && c != '\n' && isspace(c)) {
c = getc(pFile);
testwronginput(c, cols, *pRows);
}
} while (c != EOF && c != '\n');
/* is the line finished or is EOF reached? */

*pCols = cols;
return c;
}
void testwronginput(int c, unsigned cols, unsigned rows)
{
/* I tried isblank() but my system complained about it */
if (isalpha(c)) {
printf("Error! Alphabetic character '%c' encountered before
EOF\n", c);
printf("Last succesful location read was: Line %u, Column
%u\n", 1+rows, cols);
/* give the user at chance to see this error before the windows
shuts down */
system("PAUSE");
exit(1);
}
if (iscntrl(c) && c != 10) {
printf("Error! Control character '%c' encountered before
EOF\n", c);
printf("Last succesful location read was: Line %u, Column
%u\n", 1+rows, cols);
/* give the user at chance to see this error before the windows
shuts down */
system("PAUSE");
exit(1);
}
if (!isprint(c) && c != EOF && c != '\n') {
printf("Error! Non-printing character '%c' encountered before
EOF\n", c);
printf("Last succesful location read was: Line %u, Column
%u\n", 1+rows, cols);
/* give the user at chance to see this error before the windows
shuts down */
system("PAUSE");
exit(1);
}
}

- - - - - -- - - - -- -
Best regards / Med venlig hilsen
Martin Jørgensen

--
---------------------------------------------------------------------------
Home of Martin Jørgensen - http://www.martinjoergensen.dk
Mar 19 '06 #26

P: n/a
Keith Thompson wrote:
Martin Jørgensen <un*********@spam.jay.net> writes:
Barry Schwarz wrote:


[...]
You need to give us a fighting chance to help you. Try all of the
following:
Limit your line length so your posting software does not break
things up at an inconvenient place.


I've heard that before. And now I think that's a stupid advice. The
point is that I *shouldn't* limit the line length because then you get
these errors that you're complaining about here. Your news reader
should just wrap the lines if they're too long.

That's the problem. If you post code with very long lines, some
software somewhere between your computer and mine is likely to wrap
the lines. If a line is wrapped in the middle of a string literal,
the result will not compile.

Keep any code you post below 72 columns. Use only spaces, not tabs.

And be very careful throwing around words like "stupid".


The problem is that if I force outlook to make a new line after 72
columns, you will be having a *much* harder time reading the code. I
still don't know how and if possible to make visual studio restrict
itself to whatever columns. I couldn't find anything in options.
Best regards / Med venlig hilsen
Martin Jørgensen

--
---------------------------------------------------------------------------
Home of Martin Jørgensen - http://www.martinjoergensen.dk
Mar 19 '06 #27

P: n/a
Mark F. Haigh wrote:
Martin Jørgensen wrote:

<snip>
Thanks a lot for bringing another way of solving this problem... But I
already solved this problem, so imagine changing your program such that
i use malloc to initialize a new 2D array called T_new (untested):

<code snipped>
Since I already solved this problem [...]

I certainly don't think you've solved the problem. In fact, I'm not
even convinced you've managed to state the problem coherently. The
code you've posted thus far is confused, not robust, and
unmaintainable.


Last time I tried it worked.
Don't be offended. Nobody is born knowing C. You're making a
sustained effort, and that is why we're willing to spend time to help.

There's a lot of things we don't know about what you're trying to do.
But we do know that:

1. You are a student, and this may be a homework assignment. If this
is the case, you're trying to learn how to use C to solve real-world
problems. So we can conclude that you should be working hard to make
your program more clear, robust, and maintainable so that you learn a
lot about C, and as a result, get a good grade.
It is not a homework assignment.
Or...

2. You are writing a program that you hope others will find useful.
If this is the case, you need to ensure that your program is robust (a
non-robust program is not very useful) and clearly-written and
maintainable (so that other people can understand how the program
works, and can extend it or fix bugs in it).

Either way, you need to work toward the same goals of clarity,
robustness, and maintainability. A solution that does not address all
of these is not a solution at all.

(and my solution can also take files
with double input elements such as 425,358 or 823.23 as individual
elements, I didn't tested the above)... But you code is really nice to
learn from, and very logically structured. I like that... It gives me
som new ideas for future ways of solving problems.

Because you have not assured us that your problem is not homework, I'm
not going to post code that does exactly what you need. It's just a
push in the right direction, and is easily extendable to do exactly
what you need.


It is not a homework assignment.
Notice that nowhere have you:

1. Described concisely the format of the file you wish to be able to
parse. Do you control the file format? Or is it generated by another
program not under your control?
I did that already in the beginning of the thread:
Hi,

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
You can replace some of them with decimal numbers if you don't trust me.
2. Described what you wish to do with the file. What's the point of
this exercise? What's the big picture? I take it you want to read it
into a multidimensional array so you can manipulate it somehow. What
for?

You have to help us so we can help you. We're not mind readers!


I already told that a couple of times: Now I want to get number of rows
and number of cols for malloc'ing a 2D-array. You don't have to be a
mind reader to understand that. I wrote that a couple of times since
<k3************@news.tdc.dk> and I even posted a program that just don't
compile in <fs***********@news.tdc.dk> and I don't know why. So if
there's any problem in answering this question, the reason is not that
you aren't a mind reader.
Best regards / Med venlig hilsen
Martin Jørgensen

--
---------------------------------------------------------------------------
Home of Martin Jørgensen - http://www.martinjoergensen.dk
Mar 19 '06 #28

P: n/a
Pedro Graca wrote:
Martin Jørgensen wrote: -snip-
... I'll post the snippets I changed ...
Thanks.
// ...

/* more prototypes */
#ifdef pmg
void getdata(char *filename, unsigned *pCols, unsigned *pRows, unsigned *count);
#else
void getdata(char *filename, unsigned *pCols, unsigned *pRows, int *count);
#endif
Yeah... That should ofcourse give a warning...
// ...

#ifdef pmg
T = malloc((n_y[0]+1) * sizeof *T); /* n_y = rows */
T_new = malloc((n_y[0]+1) * sizeof *T_new); /* n_y = rows */
#else
double **T = malloc((n_y[0]+1)*sizeof(double*)); /* n_y = rows */
double **T_new = malloc((n_y[0]+1)*sizeof(double*)); /* n_y = rows */
#endif
I should just not have used double **T, etc.
#ifdef pmg
T[0] = malloc((n_x[0]+1)*(n_y[0]+1) * sizeof *T[0]); /* nx= cols */
T_new[0] = malloc((n_x[0]+1)*(n_y[0]+1) * sizeof *T[0]); /* nx= cols */
#else
T[0] = malloc((n_x[0]+1)*(n_y[0]+1)*sizeof(double)); /* nx= cols */
T_new[0] = malloc((n_x[0]+1)*(n_y[0]+1)*sizeof(double)); /* nx= cols */
#endif
I see. Not critical though, I guess - but nicer.
/* eventually test with T[4][6] = 959, and printf("%lf", T[4][6]); etc... */
#ifdef pmg
return 0;
#else
#endif
}

#ifdef pmg
void getdata(char *filename, unsigned *pCols, unsigned *pRows, unsigned *count) {
#else
void getdata(char *filename, unsigned *pCols, unsigned *pRows, int *count) {
#endif

-snip-

Thanks a lot... It seems to work!

The most critical thing must have been that I used double **T = ...
instead of just T = malloc... I wouldn't have figured that out myself
since I haven't worked that much with malloc. What's the difference
anyway, just to point it completely out?

So close still... Thanks a lot - I appreciate your help. I hope that I
can figure the rest of the implementation out in my bigger program
myself, from this piece of code.
Best regards / Med venlig hilsen
Martin Jørgensen

--
---------------------------------------------------------------------------
Home of Martin Jørgensen - http://www.martinjoergensen.dk
Mar 19 '06 #29

P: n/a
Martin Jørgensen wrote:
Mark F. Haigh wrote:
Martin Jørgensen wrote:

<snip>
Thanks a lot for bringing another way of solving this problem... But I
already solved this problem, so imagine changing your program such that
i use malloc to initialize a new 2D array called T_new (untested):

<code snipped>
Since I already solved this problem [...]

I certainly don't think you've solved the problem. In fact, I'm not
even convinced you've managed to state the problem coherently. The
code you've posted thus far is confused, not robust, and
unmaintainable.


Last time I tried it worked.


It may "work", but it's certainly a childish effort, at best. Let me
guess, you're a first year student? Your code sucks. Unclear,
unmaintainable, unportable. Amateur.

<snip>
It is not a homework assignment.
<snip>
It is not a homework assignment.

Very cute. I'm impressed. I think all of us are.
Notice that nowhere have you:

1. Described concisely the format of the file you wish to be able to
parse. Do you control the file format? Or is it generated by another
program not under your control?


I did that already in the beginning of the thread:
Hi,

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


You can replace some of them with decimal numbers if you don't trust me.
2. Described what you wish to do with the file. What's the point of
this exercise? What's the big picture? I take it you want to read it
into a multidimensional array so you can manipulate it somehow. What
for?

You have to help us so we can help you. We're not mind readers!


I already told that a couple of times: Now I want to get number of rows
and number of cols for malloc'ing a 2D-array. You don't have to be a
mind reader to understand that. I wrote that a couple of times since
<k3************@news.tdc.dk> and I even posted a program that just don't
compile in <fs***********@news.tdc.dk> and I don't know why.


We all know why it doesn't compile. It's because you don't know what
you're talking about. Your code sucks. Most regulars here can write
the complete program you've been struggling with for 3 days in about 10
minutes.
So if
there's any problem in answering this question, the reason is not that
you aren't a mind reader.


Fuck off. You are quite possibly the most worthless programmer (and
human being) I've ever seen. You'll get no further responses.

I have better things to do than waste my time dealing with morons like
you.
Mark F. Haigh
mf*****@sbcglobal.net

Mar 19 '06 #30

P: n/a
Mark F. Haigh opined:
Martin Jørgensen wrote:
Mark F. Haigh wrote:
> Martin Jørgensen wrote:
>
> <snip>
>
>>Thanks a lot for bringing another way of solving this problem...
>>But I already solved this problem, so imagine changing your
>>program such that i use malloc to initialize a new 2D array called
>>T_new (untested):
>>
>
> <code snipped>
>
>>Since I already solved this problem [...]
>
>
> I certainly don't think you've solved the problem. In fact, I'm
> not
> even convinced you've managed to state the problem coherently.
> The code you've posted thus far is confused, not robust, and
> unmaintainable.
Last time I tried it worked.


It may "work", but it's certainly a childish effort, at best. Let me
guess, you're a first year student? Your code sucks. Unclear,
unmaintainable, unportable. Amateur.


So? He's at least trying, unlike many other we see here. Since when has
being a beginner become shameful?
<snip>

It is not a homework assignment.
<snip>

It is not a homework assignment.


Very cute. I'm impressed. I think all of us are.


This is devoid of content (scorn is not content).

<snip>
I already told that a couple of times: Now I want to get number of
rows and number of cols for malloc'ing a 2D-array. You don't have to
be a mind reader to understand that. I wrote that a couple of times
since <k3************@news.tdc.dk> and I even posted a program that
just don't compile in <fs***********@news.tdc.dk> and I don't know
why.


We all know why it doesn't compile.


So why not tell him?
It's because you don't know what
you're talking about. Your code sucks.
Maybe, but if he's really a beginner it's not a sin.
Most regulars here can write
the complete program you've been struggling with for 3 days in about
10 minutes.


Maybe, but how does it help the OP, or anybody else?
So if
there's any problem in answering this question, the reason is not
that you aren't a mind reader.


Fuck off. You are quite possibly the most worthless programmer (and
human being) I've ever seen. You'll get no further responses.

I have better things to do than waste my time dealing with morons
like you.


And this is completely unacceptable.

I, for one, will be quite happy if you did not contribute here any
further.

*PLONK*

PS
You also snipped quite a lot of OPs post which very politely expresses
gratitude for your help, so there's really no reason for you to be as
rude and scornful as you were.

--
BR, Vladimir

Don't go surfing in South Dakota for a while.

Mar 19 '06 #31

P: n/a
Martin Jørgensen wrote:
Keith Thompson wrote:

[ snip ]

That's the problem. If you post code with very long lines, some
software somewhere between your computer and mine is likely to wrap
the lines. If a line is wrapped in the middle of a string literal,
the result will not compile.

Keep any code you post below 72 columns. Use only spaces, not tabs.

And be very careful throwing around words like "stupid".


The problem is that if I force outlook to make a new line after 72
columns, you will be having a *much* harder time reading the code. I
still don't know how and if possible to make visual studio restrict
itself to whatever columns. I couldn't find anything in options.
Best regards / Med venlig hilsen
Martin Jørgensen

Martin, you are making excuses instead of solving problems. That you
don't know how to do it right is not a good reason to keep on doing it
wrong.

Outlook is not the only or even the preferable news client. There's
Thunderbird, Free Agent, etc. Look 'em up.

I don't know either how to make the VS editors emit spaces instead of
tabs (Anybody else know?). But in preparing a code snippet to be
included in a usenet post I will run it through GNU indent to remove
tabs and indent to 3 spaces.

If you can't be bothered to prepare your code for us, don't be surprised
if we are not prepared to even read what you offer.

--
Joe Wright
"Everything should be made as simple as possible, but not simpler."
--- Albert Einstein ---
Mar 19 '06 #32

P: n/a
On 2006-03-17, Martin Jørgensen <un*********@spam.jay.net> wrote:
Michael Mair wrote:
-snip-
Cheers
Michael
Do you like my new program?

I find it *REALLY* useful :-)


Hi Martin,

I think you need to take a step back and consider making it about
1/3rd of the size and 100 times more readable. I really believe you
have overcomplicated this : as a result of you learning C as you go I suspect.

Some hints:

1) create a struct for representing rows & column count - then have an
array of these. all this n_x and n_y is not nice on the eye. And be
concistent in your naming conventions. "y" is not a proper
alternative for "number of columns".
2) Consider reading in the data a line at the time using fscanf/fgets or
something. Reading in by character is often inefficient.
3) What is "count" and why are you passing a reference to it when the
function always increments it? Sloppy. Return a success/fail code.
4) never call a function "getdata" and especially never make such a
function a void IMO : return a success code or a count or a pointer
to a result of interest.
5) stop exiting from the lower level funtions. If you *must* have a
function called "testwronginput" return a success code and
certainly do not pass in pointers to column & row data : it doesnt
need to know about them - it should only be interested in the
character it is checking. You have complicated this function and
made it heavy on the eye. Keep it simple.
6) I'm always suspicous of anything which counts anything in a "next"
line. It should be counting things in "current" line. Whenever I
see two calls to something like "countColsInNextLine" next to each
other I have to wonder if there is a better, clearer way to handle
it. Often turning the loop upside down works.
7) comment your functions : good clear C is self explanatory
manytimes, unfortunately functions like "testwronginput" are far
from clear - it seems an almost arbitrary attack on various forms
of white space etc. Hence a spec would be appreciated.

Finally : use google. I googled "reading lines in from file in c" ...

http://www.mrx.net/c/program.html

fgets might be helpful. fcanf even more so for a strict input
format. How "strict" is your input detail? Maybe its ok to assume the
format is rigid?

It is still far from clear what format the data file is in. Explain
this clearly in words - not as a c comment.

good luck!


- - - - - - - - - - - -

#include <stdlib.h> /* system("PAUSE") */
#include <stdio.h>
#include <stddef.h>
#include <ctype.h> /* for isspace */

#define max_number_of_files 50

/* prototypes */
void getdata(char *filename, unsigned *pCols, unsigned *pRows, int *count);
int countColsInNextLine (FILE *pFile, unsigned *pCols, unsigned *pRows);
void testwronginput(int c, unsigned cols, unsigned rows);

int main()
{
int i, count;
unsigned n_x[max_number_of_files], n_y[max_number_of_files]; /* one
space for each data file */

count = 0;
getdata("unknowns.dat", &n_x[0], &n_y[0], &count );
getdata("BC_types.dat", &n_x[1], &n_y[1], &count );
getdata("BC_values.dat", &n_x[2], &n_y[2], &count );

for(i=0; i<count; i++)
printf("Data file number %i has properties: Columns (x) = %u,
Rows y= %u\n", i+1, n_x[i], n_y[i]);

system("PAUSE"); /* give the user at chance to see this error
before the windows shuts down */
return 0;
}
void getdata(char *filename, unsigned *pCols, unsigned *pRows, int *count)
{
FILE *pFile;

unsigned rows, cols, oldcols;

printf("Opening file: %s.\n", filename);
if ( (pFile = 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);
}

*pRows = 0;
*pCols = 0;

/* get nx and ny */
cols = 0;
rows = 0;
if (countColsInNextLine(pFile, &oldcols, &rows) != EOF) { /* return
oldcols for first row */
rows++;
while (countColsInNextLine(pFile, &cols, &rows) != EOF) { /*
check row 2 -> EOF */
rows++;
if (cols != oldcols) { /* verify that number of cols didn't
change */
printf("ERROR: Number of columns is not a constant in
file: %s\n\n", filename);
printf("In line %u, the number of columns is %u
cols.\n", rows, cols);
printf("In the previous line it was counted to
%u.\n\nPlease fix this problem now.\n", oldcols);
exit(1);
}
}
}

if (cols != 0 && cols != oldcols) {
printf("ERROR: Line %u (last line) consisted of %u
columns.\nLine %u had %u columns.\n", rows, cols, rows-1, oldcols);
exit(1);
}

*pRows = rows; /* update results */
*pCols = oldcols;
(*count)++;

printf("Finished reading from file %s.\n\n", filename);
fclose(pFile); /* close input file, finished reading values in */
}

int countColsInNextLine (FILE *pFile, unsigned *pCols, unsigned *pRows)
{
int c;
unsigned cols = 0;

c = getc(pFile); /* get first character to start the loop */
do {
testwronginput(c, cols, *pRows);
if (c != EOF && !isspace(c)) { /* first time non-space
encountered, update cols */
cols++;
do { /* skip digits and commas, after first digit */
c = getc(pFile);
testwronginput(c, cols, *pRows);
} while (c != EOF && !isspace(c) || c == ',' || c == '.');
/* comma should also be valid input in number */
}
while (c != EOF && c != '\n' && isspace(c)) { /* skip through
blank spaces, but not '\n' ! */
c = getc(pFile);
testwronginput(c, cols, *pRows);
}
} while (c != EOF && c != '\n'); /* is the line finished or is EOF
reached? */

*pCols = cols;
return c;
}

void testwronginput(int c, unsigned cols, unsigned rows) /* I tried
isblank() but my system complained about it */
{
if (isalpha(c)) {
printf("Error! Alphabetic character '%c' encountered before
EOF\n", c);
printf("Last succesful location read was: Line %u, Column
%u\n", 1+rows, cols);
system("PAUSE"); /* give the user at chance to see this error
before the windows shuts down */
exit(1);
}
if (iscntrl(c) && c != 10) {
printf("Error! Control character '%c' encountered before
EOF\n", c);
printf("Last succesful location read was: Line %u, Column
%u\n", 1+rows, cols);
system("PAUSE"); /* give the user at chance to see this error
before the windows shuts down */
exit(1);
}
if (!isprint(c) && c != EOF && c != '\n') {
printf("Error! Non-printing character '%c' encountered before
EOF\n", c);
printf("Last succesful location read was: Line %u, Column
%u\n", 1+rows, cols);
system("PAUSE"); /* give the user at chance to see this error
before the windows shuts down */
exit(1);
}
}

- - - - - - - - - - - -
Best regards / Med venlig hilsen
Martin Jørgensen

--
Debuggers : you know it makes sense.
http://heather.cs.ucdavis.edu/~matlo...g.html#tth_sEc
Mar 19 '06 #33

P: n/a
Martin Jørgensen wrote:
The most critical thing must have been that I used double **T = ...
instead of just T = malloc... I wouldn't have figured that out myself
since I haven't worked that much with malloc. What's the difference
anyway, just to point it completely out?


When you have an array of arrays dynamically allocated
(eg double ** table;) you /first/ have to allocate the rows, and then
/for each row/ allocate the columns;

#include <stdlib.h>

#define NUM_ROWS 10
#define NUM_COLS 12

int main(void) {
size_t i;
double ** table;

/* allocate space for NUM_ROWS * NUM_COLS elements */

/* first the rows */
table = malloc(NUM_ROWS * sizeof *table);
if (!table) {
fprintf(stderr, "Not enough memory. Program aborted.\n")
exit(EXIT_FAILURE);
}

/* and then the columns */
for (i = 0; i < NUM_ROWS; ++i) {
table[i] = malloc(NUM_COLS * sizeof *(table[i]));
if (!table[i]) {
if (i > 0) {
/* release previously allocated memory */
size_t j;
/* NOTE: as j is size_t (some kind of unsigned int)
* `--j` is perfectly defined and will not break */
for (j = i-1; j < i; --j) {
free(table[j]);
}
}
free(table);
fprintf(stderr, "Not enough memory. Program aborted.\n")
exit(EXIT_FAILURE);
}
}

/* work with table */

/* release memory in reverse order: first the columns */
for (i=0; i<NUM_ROWS; ++i) {
free(table[i]);
}
/* and then the rows */
free(table);

return 0;
}

--
If you're posting through Google read <http://cfaj.freeshell.org/google>
Mar 19 '06 #34

P: n/a
Martin Jørgensen wrote:
Keith Thompson wrote:

.... snip ...

Keep any code you post below 72 columns. Use only spaces, not tabs.

And be very careful throwing around words like "stupid".


The problem is that if I force outlook to make a new line after 72
columns, you will be having a *much* harder time reading the code. I
still don't know how and if possible to make visual studio restrict
itself to whatever columns. I couldn't find anything in options.


You don't need to use such stupid software as Outhouse. There are
many available decent newsreaders. As far as the VS editor is
concerned, you should be capable of hitting the return (enter) key
at the end of code lines. There is almost never any need for lines
of over 72 chars length. C has some useful provisions, such as
concatenating adjacent strings, or continuation lines, in the rare
case.

You can also fix your source with indent. The following line will
wrap, but will keep code lines suitably short.

-kr -l66 -i3 -bad -di16 -lc66 -nce -ncs -cbi0 -bbo -pmt -psl -ts1
-cdw

That could be the content of indent.pro on your windoze machine,
and will configure indent 2.2.9. Note the -l66, which sets the
right margin, while -i3 sets indentation.

--
"If you want to post a followup via groups.google.com, don't use
the broken "Reply" link at the bottom of the article. Click on
"show options" at the top of the article, then click on the
"Reply" at the bottom of the article headers." - Keith Thompson
More details at: <http://cfaj.freeshell.org/google/>
Also see <http://www.safalra.com/special/googlegroupsreply/>
Mar 19 '06 #35

P: n/a
Martin Jørgensen wrote:
Barry Schwarz wrote:

-snip-
Sorry, your formatting makes it impossible to compile your code
and I didn't spot these in my review.
Okay, forget about this wrapping thing. Guess you're right. I
just can't restrict Visual studio from making lines longer than
65 characters or so. I went through all the options and help. The
following should be better in that I don't think it inserts
ekstra linebreaks in places never intended to have linebreaks. So
what's important is what's inside main() and I hope that
copy/pasting should work - I manually fixed some comments etc.

.... snip ...
void getdata(char *filename, unsigned *pCols, unsigned *pRows, int *count)
{
FILE *pFile;

unsigned rows, cols, oldcols;

printf("Opening file: %s.\n", filename);
if ( (pFile = fopen(filename, "r") ) == NULL)
{
printf("Cannot open file %s.\n", filename);
/* give the user at chance to see this error before the windows
shuts down */
system("PAUSE");
exit(1);
}


As an example, lets just deal with the above extract, and see a
reasonable way to format it that will work everywhere.

void getdata(char *filename, /* room to describe */
unsigned *pCols, /* the various parameters */
unsigned *pRows, /* if desired */
int *count)
{
FILE *pFile;

unsigned rows, cols, oldcols;

printf("Opening file: %s.\n", filename);
if ( (pFile = fopen(filename, "r") ) == NULL) {
printf("Cannot open file %s.\n", filename);

/* give the user at chance to see this error */
/* before the windows shuts down */
system("PAUSE");
exit(1);
}

And, instead of the very questionable use of system("PAUSE") etc.,
I would use:

printf("Cannot open file %s.\n"
"Hit <enter> to continue",
filename);
fflush(stdout);

/* give the user at chance to see this error */
/* before the windows shuts down */
getchar();
exit(EXIT_FAILURE);
}

Note the use of string concatenation to avoid long lines, and
simultaneously provide an image of the output screen in the source
code. Now that portion is also portable. You can also easily
change to using fprintf(stderr, "..., which is a preferable place
for error messages.

--
"If you want to post a followup via groups.google.com, don't use
the broken "Reply" link at the bottom of the article. Click on
"show options" at the top of the article, then click on the
"Reply" at the bottom of the article headers." - Keith Thompson
More details at: <http://cfaj.freeshell.org/google/>
Also see <http://www.safalra.com/special/googlegroupsreply/>
Mar 19 '06 #36

P: n/a
Martin Jørgensen wrote:
Mark F. Haigh wrote:

.... snip ...

You have to help us so we can help you. We're not mind readers!


I already told that a couple of times: Now I want to get number of
rows and number of cols for malloc'ing a 2D-array. You don't have
to be a mind reader to understand that. I wrote that a couple of
times since <k3************@news.tdc.dk> and I even posted a
program that just don't compile in <fs***********@news.tdc.dk> and
I don't know why. So if there's any problem in answering this
question, the reason is not that you aren't a mind reader.


Now don't get all snippy with your panties in a knot, or you will
find your help rapidly disappears. We all have better things to do
than laboriously research a thread. Articles should stand by
themselves, and if something is unclear just explain it. Articles
should also be short.

--
"If you want to post a followup via groups.google.com, don't use
the broken "Reply" link at the bottom of the article. Click on
"show options" at the top of the article, then click on the
"Reply" at the bottom of the article headers." - Keith Thompson
More details at: <http://cfaj.freeshell.org/google/>
Also see <http://www.safalra.com/special/googlegroupsreply/>
Mar 19 '06 #37

P: n/a
Joe Wright wrote:
Martin Jørgensen wrote:
Keith Thompson wrote:


[ snip ]

That's the problem. If you post code with very long lines, some
software somewhere between your computer and mine is likely to wrap
the lines. If a line is wrapped in the middle of a string literal,
the result will not compile.

Keep any code you post below 72 columns. Use only spaces, not tabs.

And be very careful throwing around words like "stupid".

The problem is that if I force outlook to make a new line after 72
columns, you will be having a *much* harder time reading the code. I
still don't know how and if possible to make visual studio restrict
itself to whatever columns. I couldn't find anything in options.
Best regards / Med venlig hilsen
Martin Jørgensen

Martin, you are making excuses instead of solving problems. That you
don't know how to do it right is not a good reason to keep on doing it
wrong.

Outlook is not the only or even the preferable news client. There's
Thunderbird, Free Agent, etc. Look 'em up.

I don't know either how to make the VS editors emit spaces instead of
tabs (Anybody else know?). But in preparing a code snippet to be
included in a usenet post I will run it through GNU indent to remove
tabs and indent to 3 spaces.

If you can't be bothered to prepare your code for us, don't be surprised
if we are not prepared to even read what you offer.


Don't be surprised if new users in this group don't know how to prepare
the code for you. It really has a obvious reason, believe it or not. As
somebody else wrote, I'm not a mind-reader too.
Best regards / Med venlig hilsen
Martin Jørgensen

--
---------------------------------------------------------------------------
Home of Martin Jørgensen - http://www.martinjoergensen.dk
Mar 19 '06 #38

P: n/a
CBFalconer wrote:
Martin Jørgensen wrote:
Keith Thompson wrote:


... snip ...
Keep any code you post below 72 columns. Use only spaces, not tabs.

And be very careful throwing around words like "stupid".


The problem is that if I force outlook to make a new line after 72
columns, you will be having a *much* harder time reading the code. I
still don't know how and if possible to make visual studio restrict
itself to whatever columns. I couldn't find anything in options.

You don't need to use such stupid software as Outhouse. There are
many available decent newsreaders. As far as the VS editor is
concerned, you should be capable of hitting the return (enter) key
at the end of code lines. There is almost never any need for lines
of over 72 chars length. C has some useful provisions, such as
concatenating adjacent strings, or continuation lines, in the rare
case.

You can also fix your source with indent. The following line will
wrap, but will keep code lines suitably short.

-kr -l66 -i3 -bad -di16 -lc66 -nce -ncs -cbi0 -bbo -pmt -psl -ts1
-cdw

That could be the content of indent.pro on your windoze machine,
and will configure indent 2.2.9. Note the -l66, which sets the
right margin, while -i3 sets indentation.


I will take a look at that.
Best regards / Med venlig hilsen
Martin Jørgensen

--
---------------------------------------------------------------------------
Home of Martin Jørgensen - http://www.martinjoergensen.dk
Mar 19 '06 #39

P: n/a
Pedro Graca wrote:
Martin Jørgensen wrote:
The most critical thing must have been that I used double **T = ...
instead of just T = malloc... I wouldn't have figured that out myself
since I haven't worked that much with malloc. What's the difference
anyway, just to point it completely out?

When you have an array of arrays dynamically allocated
(eg double ** table;) you /first/ have to allocate the rows, and then
/for each row/ allocate the columns;


Yeah, I have that under control... I think I can figure out the rest myself.
#include <stdlib.h>

#define NUM_ROWS 10
#define NUM_COLS 12

int main(void) {
size_t i;
double ** table;

/* allocate space for NUM_ROWS * NUM_COLS elements */

/* first the rows */
table = malloc(NUM_ROWS * sizeof *table);
if (!table) {
fprintf(stderr, "Not enough memory. Program aborted.\n")
exit(EXIT_FAILURE);
}

/* and then the columns */
for (i = 0; i < NUM_ROWS; ++i) {
table[i] = malloc(NUM_COLS * sizeof *(table[i]));
if (!table[i]) {
if (i > 0) {
/* release previously allocated memory */
size_t j;
/* NOTE: as j is size_t (some kind of unsigned int)
* `--j` is perfectly defined and will not break */
for (j = i-1; j < i; --j) {
free(table[j]);
}
}
free(table);
fprintf(stderr, "Not enough memory. Program aborted.\n")
exit(EXIT_FAILURE);
}
}

/* work with table */

/* release memory in reverse order: first the columns */
for (i=0; i<NUM_ROWS; ++i) {
free(table[i]);
}
/* and then the rows */
free(table);

return 0;
}


I'll take a closer look later. Thanks again.
Best regards / Med venlig hilsen
Martin Jørgensen

--
---------------------------------------------------------------------------
Home of Martin Jørgensen - http://www.martinjoergensen.dk
Mar 19 '06 #40

P: n/a
Mark F. Haigh wrote:
Martin Jørgensen wrote: -snip-

It may "work", but it's certainly a childish effort, at best. Let me
guess, you're a first year student? Your code sucks. Unclear,
unmaintainable, unportable. Amateur.
No, I'm not a first a first year student.
<snip>
It is not a homework assignment.


<snip>
It is not a homework assignment.

Very cute. I'm impressed. I think all of us are.


I see you have a very big problem with me telling you that this wasn't a
homework assignment. You don't have to be impressed by that. That is
nothing.
Notice that nowhere have you:

1. Described concisely the format of the file you wish to be able to
parse. Do you control the file format? Or is it generated by another
program not under your control?


I did that already in the beginning of the thread:

Hi,

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


You can replace some of them with decimal numbers if you don't trust me.

2. Described what you wish to do with the file. What's the point of
this exercise? What's the big picture? I take it you want to read it
into a multidimensional array so you can manipulate it somehow. What
for?

You have to help us so we can help you. We're not mind readers!


I already told that a couple of times: Now I want to get number of rows
and number of cols for malloc'ing a 2D-array. You don't have to be a
mind reader to understand that. I wrote that a couple of times since
<k3************@news.tdc.dk> and I even posted a program that just don't
compile in <fs***********@news.tdc.dk> and I don't know why.

We all know why it doesn't compile. It's because you don't know what
you're talking about. Your code sucks. Most regulars here can write
the complete program you've been struggling with for 3 days in about 10
minutes.


Wauw... Am I supposed to be impressed now?

I have other things to do, than to program.
So if
there's any problem in answering this question, the reason is not that
you aren't a mind reader.

Fuck off. You are quite possibly the most worthless programmer (and
human being) I've ever seen. You'll get no further responses.

I have better things to do than waste my time dealing with morons like
you.
Mark F. Haigh
mf*****@sbcglobal.net


.... "with morons like you"... Look who's talking now...

What exactly is your problem?

"the most worthless programmer (and human being) I've ever seen".

"Fuck off".
Best regards / Med venlig hilsen
Martin Jørgensen

--
---------------------------------------------------------------------------
Home of Martin Jørgensen - http://www.martinjoergensen.dk
Mar 19 '06 #41

P: n/a
CBFalconer wrote:
Martin Jørgensen wrote:
Mark F. Haigh wrote:


... snip ...
You have to help us so we can help you. We're not mind readers!


I already told that a couple of times: Now I want to get number of
rows and number of cols for malloc'ing a 2D-array. You don't have
to be a mind reader to understand that. I wrote that a couple of
times since <k3************@news.tdc.dk> and I even posted a
program that just don't compile in <fs***********@news.tdc.dk> and
I don't know why. So if there's any problem in answering this
question, the reason is not that you aren't a mind reader.

Now don't get all snippy with your panties in a knot, or you will
find your help rapidly disappears. We all have better things to do
than laboriously research a thread. Articles should stand by
themselves, and if something is unclear just explain it. Articles
should also be short.


I already explained it several times, pretty clear IMO, but if people
don't want to read what is very clear then it not my fault. Do I really
have to remind you, that Pedro already solved this problem without
whining like a pig like Mark who has a problem which I never understood
and probably never will understand.

I just answered his questions and assured him that this wasn't a
homework exercise - what else should I do? I really don't see his
problem and those stupid accusations is just too much.
Best regards / Med venlig hilsen
Martin Jørgensen

--
---------------------------------------------------------------------------
Home of Martin Jørgensen - http://www.martinjoergensen.dk
Mar 19 '06 #42

P: n/a
Richard G. Riley wrote:
On 2006-03-17, Martin Jørgensen <un*********@spam.jay.net> wrote:
Michael Mair wrote:
-snip-

Cheers
Michael


Do you like my new program?

I find it *REALLY* useful :-)

Hi Martin,

I think you need to take a step back and consider making it about
1/3rd of the size and 100 times more readable. I really believe you
have overcomplicated this : as a result of you learning C as you go I suspect.

Some hints:

1) create a struct for representing rows & column count - then have an
array of these. all this n_x and n_y is not nice on the eye. And be
concistent in your naming conventions. "y" is not a proper
alternative for "number of columns".
2) Consider reading in the data a line at the time using fscanf/fgets or
something. Reading in by character is often inefficient.
3) What is "count" and why are you passing a reference to it when the
function always increments it? Sloppy. Return a success/fail code.
4) never call a function "getdata" and especially never make such a
function a void IMO : return a success code or a count or a pointer
to a result of interest.
5) stop exiting from the lower level funtions. If you *must* have a
function called "testwronginput" return a success code and
certainly do not pass in pointers to column & row data : it doesnt
need to know about them - it should only be interested in the
character it is checking. You have complicated this function and
made it heavy on the eye. Keep it simple.
6) I'm always suspicous of anything which counts anything in a "next"
line. It should be counting things in "current" line. Whenever I
see two calls to something like "countColsInNextLine" next to each
other I have to wonder if there is a better, clearer way to handle
it. Often turning the loop upside down works.
7) comment your functions : good clear C is self explanatory
manytimes, unfortunately functions like "testwronginput" are far
from clear - it seems an almost arbitrary attack on various forms
of white space etc. Hence a spec would be appreciated.

Finally : use google. I googled "reading lines in from file in c" ...

http://www.mrx.net/c/program.html

fgets might be helpful. fcanf even more so for a strict input
format. How "strict" is your input detail? Maybe its ok to assume the
format is rigid?

It is still far from clear what format the data file is in. Explain
this clearly in words - not as a c comment.

good luck!

-snip-

Hi Richard. Thanks for the professional and constructive contribution.
Those suggestions look pretty good to me. This thread has been
"polluted" a bit too much for me, I think.

The good thing is that I think I have the programming part under
control, more or less...
Best regards / Med venlig hilsen
Martin Jørgensen

--
---------------------------------------------------------------------------
Home of Martin Jørgensen - http://www.martinjoergensen.dk
Mar 19 '06 #43

P: n/a
CBFalconer wrote:
Martin Jørgensen wrote:
Barry Schwarz wrote:

-snip-

Sorry, your formatting makes it impossible to compile your code
and I didn't spot these in my review.


Okay, forget about this wrapping thing. Guess you're right. I
just can't restrict Visual studio from making lines longer than
65 characters or so. I went through all the options and help. The
following should be better in that I don't think it inserts
ekstra linebreaks in places never intended to have linebreaks. So
what's important is what's inside main() and I hope that
copy/pasting should work - I manually fixed some comments etc.


... snip ...
void getdata(char *filename, unsigned *pCols, unsigned *pRows, int *count)
{
FILE *pFile;

unsigned rows, cols, oldcols;

printf("Opening file: %s.\n", filename);
if ( (pFile = fopen(filename, "r") ) == NULL)
{
printf("Cannot open file %s.\n", filename);
/* give the user at chance to see this error before the windows
shuts down */
system("PAUSE");
exit(1);
}

As an example, lets just deal with the above extract, and see a
reasonable way to format it that will work everywhere.

void getdata(char *filename, /* room to describe */
unsigned *pCols, /* the various parameters */
unsigned *pRows, /* if desired */
int *count)
{
FILE *pFile;

unsigned rows, cols, oldcols;

printf("Opening file: %s.\n", filename);
if ( (pFile = fopen(filename, "r") ) == NULL) {
printf("Cannot open file %s.\n", filename);

/* give the user at chance to see this error */
/* before the windows shuts down */
system("PAUSE");
exit(1);
}

And, instead of the very questionable use of system("PAUSE") etc.,
I would use:

printf("Cannot open file %s.\n"
"Hit <enter> to continue",
filename);
fflush(stdout);

/* give the user at chance to see this error */
/* before the windows shuts down */
getchar();
exit(EXIT_FAILURE);
}

Note the use of string concatenation to avoid long lines, and
simultaneously provide an image of the output screen in the source
code. Now that portion is also portable. You can also easily
change to using fprintf(stderr, "..., which is a preferable place
for error messages.


I get the idea, but don't be surprised about that I'm going to tell you
that I couldn't possible know that you felt that way about reading some
code I copy/pasted since I haven't subscribed to this group for long and
only have about 1,5 months of C programming experience.

I guess I have subscribed to this group for about 1,5 months and being
called "a moron", being told to "fuck off" and being told that "You are
quite possibly the most worthless programmer (and human being) I've ever
seen" is just too childish.
Best regards / Med venlig hilsen
Martin Jørgensen

--
---------------------------------------------------------------------------
Home of Martin Jørgensen - http://www.martinjoergensen.dk
Mar 19 '06 #44

P: n/a
On Sun, 19 Mar 2006 07:18:56 -0500, in comp.lang.c , CBFalconer
<cb********@yahoo.com> wrote:
Martin Jørgensen wrote:
void getdata(char *filename, unsigned *pCols, unsigned *pRows, int *count)
{


void getdata(char *filename, /* room to describe */
unsigned *pCols, /* the various parameters */
unsigned *pRows, /* if desired */
int *count)


personally I consider this an abomination. The first form is way more
readable.

Please don't put comments to the right of your variable declarations,
if you have some comment to make, do it above the code where it can be
sensibly read and isn't going to end up bizarrely indented when
variable names get altered. .
Mark McIntyre
--
"Debugging is twice as hard as writing the code in the first place.
Therefore, if you write the code as cleverly as possible, you are,
by definition, not smart enough to debug it."
--Brian Kernighan
Mar 19 '06 #45

P: n/a
Mark McIntyre <ma**********@spamcop.net> writes:
On Sun, 19 Mar 2006 07:18:56 -0500, in comp.lang.c , CBFalconer
<cb********@yahoo.com> wrote:
Martin Jxrgensen wrote:
void getdata(char *filename, unsigned *pCols, unsigned *pRows, int *count)
{


void getdata(char *filename, /* room to describe */
unsigned *pCols, /* the various parameters */
unsigned *pRows, /* if desired */
int *count)


personally I consider this an abomination. The first form is way more
readable.


I work for a company that has the latter as required style.
(If you violate it you get scorched in code reviews.)
--
"Given that computing power increases exponentially with time,
algorithms with exponential or better O-notations
are actually linear with a large constant."
--Mike Lee
Mar 19 '06 #46

P: n/a
Richard G. Riley schrieb:
6) I'm always suspicous of anything which counts anything in a "next"
line. It should be counting things in "current" line. Whenever I
see two calls to something like "countColsInNextLine" next to each
other I have to wonder if there is a better, clearer way to handle
it. Often turning the loop upside down works.


The (potential) misnomer is my fault -- as long as it is not
clear that there is a line, I like to think of the potential
input line as "next line if any".
If we had some sort of readLine(&line, ....) and a check whether
a line has been read, then a subsequent call to a line counting
function could of course call countColsInCurrentLine(line, ....)
or countColsInLine().

The original code is from me (<47************@individual.net>):
,---
rows = 0;
if (countColsInNextLine(pFile, &oldcols) != EOF) {
rows++;
while (countColsInNextLine(pFile, &cols) != EOF) {
rows++;
if (cols != oldcols) {
isConsistent = 0;
/* Your error message here */
}
}
}
`---
The two calls "next to each other" maybe could be done
in a nicer way -- the alternative to differentiate between
"oldcols unset because we have not yet read in the first
line" and "oldcols set" within the loop IMO is a poor one.
I went with the obvious course: "If there is no line, ...;
if there is at least one line, set oldcols; if there are
further lines, compare oldcols with the new line's number
of columns".
How would you express that differently in C without putting
tests that do not structurally belong there inside the
loop?

Cheers
Michael
--
E-Mail: Mine is an /at/ gmx /dot/ de address.
Mar 19 '06 #47

P: n/a
Martin Jørgensen wrote:
.... snip ...
I guess I have subscribed to this group for about 1,5 months and
being called "a moron", being told to "fuck off" and being told
that "You are quite possibly the most worthless programmer (and
human being) I've ever seen" is just too childish.


You didn't get that from me, and usenet is full of ignorant boors.
Ignore them, or at least their boorish behaviour.

--
"If you want to post a followup via groups.google.com, don't use
the broken "Reply" link at the bottom of the article. Click on
"show options" at the top of the article, then click on the
"Reply" at the bottom of the article headers." - Keith Thompson
More details at: <http://cfaj.freeshell.org/google/>
Also see <http://www.safalra.com/special/googlegroupsreply/>
Mar 19 '06 #48

P: n/a
CBFalconer opined:
Martin Jørgensen wrote:
... snip ...

I guess I have subscribed to this group for about 1,5 months and
being called "a moron", being told to "fuck off" and being told
that "You are quite possibly the most worthless programmer (and
human being) I've ever seen" is just too childish.


You only got that from one person (I can vouch for two out of three),
on one occasion, and they have already been criticised for it (by
me ;-) ).
You didn't get that from me, and usenet is full of ignorant boors.
Ignore them, or at least their boorish behaviour.


Good advice. Heed it.

--
BR, Vladimir

Tact is the ability to tell a man he has an open mind when he has a
hole in his head.

Mar 19 '06 #49

P: n/a
On 2006-03-19, Ben Pfaff <bl*@cs.stanford.edu> wrote:
Mark McIntyre <ma**********@spamcop.net> writes:
On Sun, 19 Mar 2006 07:18:56 -0500, in comp.lang.c , CBFalconer
<cb********@yahoo.com> wrote:
Martin Jxrgensen wrote:
void getdata(char *filename, unsigned *pCols, unsigned *pRows, int *count)
{

void getdata(char *filename, /* room to describe */
unsigned *pCols, /* the various parameters */
unsigned *pRows, /* if desired */
int *count)


personally I consider this an abomination. The first form is way more
readable.


I work for a company that has the latter as required style.
(If you violate it you get scorched in code reviews.)


Required always, or required for non-self-explanatory argument lists
and/or argument lists over a certain length?

In other words, are we talking about

void f(void /* room to describe void */
)

or is there some wiggle room here?
Mar 19 '06 #50

68 Replies

This discussion thread is closed

Replies have been disabled for this discussion.