C newbie in a jam

S

Sheldon

Hi,
I have a program here that I am trying to take to another level. That
is to say that I call a function from main, pass an array pointer,
populate the array, and then write it to a file, read it again and the
print it. The problem is that i can't get past certain errors in
compiling. I am using several online tutorials that only give simple
examples.

#define row 15
#define col 15
double readfile(double, int,int, double); 2nd error !!!
int main() {
FILE *fp;
char FILENAME[50] = "test_array.dat";
double tmp[row][col];
double *arp = &tmp[0][0]; /* pointer */
int i, j;
double count;
double array = readfile(*arp, row, col, count);
fp = fopen(FILENAME, "wb")
fwrite(tmp, sizeof count, row*col, fp)
fclose(fp);
fp = fopen(FILENAME, "rb")
fread(tmp, sizeof count, row*col, fp)
fclose(fp);
for (i = 0; i < row; i++) {
for (j = 0; j < col; j++) {
printf("tmp[%d,%d] = %f\n", i,j, tmp[j]);}}
return 0;}
double readfile(double *arp,int row,int col, double count){ First
error line!
int i, j;
double count;
double *arp;
count = 0.0;
for(i = 0; i < row; i++) {
for(j = 0; j < col; j++){
*arp[j] = count; 3rd error!
count++; } }
return EXIT_SUCCESS;}

The errors in compilation are:
test_readfile.c: error: parse error before numeric constant
test_readfile.c: In function `readfile':
test_readfile.c: error: number of arguments doesn't match prototype
test_readfile.c: error: prototype declaration
test_readfile.c: error: subscripted value is neither array nor pointer

I compressed the code to make it compact to publish.

Any help is greatly appreciated.

Sheldon
 
B

Bill Pursell

Sheldon said:
Hi,
I have a program here that I am trying to take to another level. That
is to say that I call a function from main, pass an array pointer,
populate the array, and then write it to a file, read it again and the
print it. The problem is that i can't get past certain errors in
compiling. I am using several online tutorials that only give simple
examples.

#define row 15
#define col 15
double readfile(double, int,int, double); 2nd error !!!
int main() {

Make that "int main(void)".
FILE *fp;
char FILENAME[50] = "test_array.dat";
double tmp[row][col];
double *arp = &tmp[0][0]; /* pointer */
int i, j;
double count;
double array = readfile(*arp, row, col, count);

Make that two lines: "double array; array = readfile..."
fp = fopen(FILENAME, "wb")

I realize you probably deleted the error checking for
the sake of posting. Make sure you check that fopen
succeeds.
fwrite(tmp, sizeof count, row*col, fp)

This is clearer if you write "fwrite(tmp, sizeof *tmp, ...)"
fclose(fp);
fp = fopen(FILENAME, "rb")
fread(tmp, sizeof count, row*col, fp)
fclose(fp);
for (i = 0; i < row; i++) {
for (j = 0; j < col; j++) {
printf("tmp[%d,%d] = %f\n", i,j, tmp[j]);}}
return 0;}
double readfile(double *arp,int row,int col, double count){ First


Yeah, that's a big error. Above you declared readfile as
taking a double, two ints, and a double. Now you say the
first argument is a double *.
error line!
int i, j;
double count;
double *arp;
count = 0.0;
for(i = 0; i < row; i++) {
for(j = 0; j < col; j++){
*arp[j] = count; 3rd error!


woah!! You declared arp as a double*, so
*arp[j] makes no sense. *arp[j] only
makes sense if arp is a 2 dimensional array
of pointers (or a ***, or something else equvialent)

You need to decide what the first argument should be.
You probably want it to be a double **.
 
A

attn.steven.kuo

Sheldon wrote:

(snipped)
i can't get past certain errors in
compiling. I am using several online tutorials that only give simple
examples.

#define row 15
#define col 15
double readfile(double, int,int, double); 2nd error !!!
(snipped)
double readfile(double *arp,int row,int col, double count){ First
error line!
int i, j;
double count;
double *arp;
count = 0.0;
for(i = 0; i < row; i++) {
for(j = 0; j < col; j++){
*arp[j] = count; 3rd error!
count++; } }
return EXIT_SUCCESS;}

The errors in compilation are:
test_readfile.c: error: parse error before numeric constant
test_readfile.c: In function `readfile':
test_readfile.c: error: number of arguments doesn't match prototype
test_readfile.c: error: prototype declaration
test_readfile.c: error: subscripted value is neither array nor pointer

I compressed the code to make it compact to publish.

Any help is greatly appreciated.

Sheldon



The declaration for function 'readfile'
says to expect (double, int, int, double)
as argments.

The definition for function 'readfile'
says to expect ( double *, int 15, int 15, double)
as arguments.

Notice that the first argument here is a
pointer-to-double instead of a double?

Notice that the pre-processor has replaced
'row' and 'col' in your definition with
numeric constants? That becomes
a syntax error.

If arp is a pointer-to-double:

double *arp

then

arp is a double

arg[j] is a syntax error

A subscripted index of
a double doesn't make sense.
 
R

Richard Heathfield

Sheldon said:
Hi,
I have a program here that I am trying to take to another level. That
is to say that I call a function from main, pass an array pointer,
populate the array, and then write it to a file, read it again and the
print it. The problem is that i can't get past certain errors in
compiling. I am using several online tutorials that only give simple
examples.

You are also not showing us the code you are actually compiling, or you're
not telling us about all the diagnostic messages you're getting. When I
compiled your code, the compiler almost fainted! You had dropped semicolons
like a Cockney drops the letter 'h'. Still, let's see what we can do with
it.
#define row 15
#define col 15

The convention of making such constants UPPER CASE is a good one.

double readfile(double, int,int, double);

Should be:

double readfile(double *, int, int, double);

It is badly named, since it doesn't actually have anything to do with
reading, or with files.
int main() {

Not exactly wrong, but the following is better:

int main(void) {

since it explicitly defines the types of its parameters.

FILE *fp;

This should have given you an error, since you have no definition of FILE.
To fix this, add:

#include <stdio.h>

above main() somewhere.
char FILENAME[50] = "test_array.dat";

The convention of avoiding ALL UPPER CASE for ordinary object names is a
good one. ;-)
double tmp[row][col];
double *arp = &tmp[0][0]; /* pointer */
int i, j;
double count;
double array = readfile(*arp, row, col, count);

readfile requires a pointer-to-double as its first argument. Since arp has
the type pointer-to-double, *arp has the type double, which isn't the same
thing. This whole business of telling C functions about two-dimensional
arrays is far less obvious than it perhaps ought to be (although it is
eminently logical when you think it through).

I'm torn here, because I don't want to have to write a ten-page explanation
of why your whole approach to this 2D-array handling is wrong and how to
fix it, but on the other hand I don't want to leave you in the lurch.

Right now, I think the simplest fix is to show you a correct (or at least a
*more* correct) version of your program, and leave it to you to ask
questions about anything you don't understand. I don't claim to have put in
all the necessary error-checking, but I think I've got most of it:

#include <stdio.h>
#include <stdlib.h>

#define ROW 15
#define COL 15
void readfile(double (*)[ROW][COL],
int,
int,
double);
int main(void)
{
FILE *fp = NULL;
char filename[50] = "test_array.dat";
double array[ROW][COL] = { 0 };
int i, j;
double count;

readfile(&array, ROW, COL, count);

fp = fopen(filename, "wb");
if(fp != NULL)
{
fwrite(array, sizeof array, 1, fp);
fclose(fp);
fp = fopen(filename, "rb");
if(fp != NULL)
{
fread(array, sizeof count, ROW * COL, fp);
fclose(fp);
for(i = 0; i < ROW; i++)
{
for(j = 0; j < COL; j++)
{
printf("array[%d, %d] = %f\n", i, j, array[j]);
}
}
}
}
return 0;
}

void readfile(double (*array)[ROW][COL],
int row,
int col,
double count)
{
int i, j;

count = 0.0;
for(i = 0; i < row; i++)
{
for(j = 0; j < col; j++)
{
(*array)[j] = count;
count++;
}
}
}
 
S

Sheldon

Bill Pursell skrev:
Sheldon said:
Hi,
I have a program here that I am trying to take to another level. That
is to say that I call a function from main, pass an array pointer,
populate the array, and then write it to a file, read it again and the
print it. The problem is that i can't get past certain errors in
compiling. I am using several online tutorials that only give simple
examples.

#define row 15
#define col 15
double readfile(double, int,int, double); 2nd error !!!
int main() {

Make that "int main(void)".
FILE *fp;
char FILENAME[50] = "test_array.dat";
double tmp[row][col];
double *arp = &tmp[0][0]; /* pointer */
int i, j;
double count;
double array = readfile(*arp, row, col, count);

Make that two lines: "double array; array = readfile..."
fp = fopen(FILENAME, "wb")

I realize you probably deleted the error checking for
the sake of posting. Make sure you check that fopen
succeeds.
fwrite(tmp, sizeof count, row*col, fp)

This is clearer if you write "fwrite(tmp, sizeof *tmp, ...)"
fclose(fp);
fp = fopen(FILENAME, "rb")
fread(tmp, sizeof count, row*col, fp)
fclose(fp);
for (i = 0; i < row; i++) {
for (j = 0; j < col; j++) {
printf("tmp[%d,%d] = %f\n", i,j, tmp[j]);}}
return 0;}
double readfile(double *arp,int row,int col, double count){ First


Yeah, that's a big error. Above you declared readfile as
taking a double, two ints, and a double. Now you say the
first argument is a double *.
error line!
int i, j;
double count;
double *arp;
count = 0.0;
for(i = 0; i < row; i++) {
for(j = 0; j < col; j++){
*arp[j] = count; 3rd error!


woah!! You declared arp as a double*, so
*arp[j] makes no sense. *arp[j] only
makes sense if arp is a 2 dimensional array
of pointers (or a ***, or something else equvialent)

You need to decide what the first argument should be.
You probably want it to be a double **.


Thanks Bill. Like I explained earlier I want to learn how to use a
function and how to use pointers.
So I guess I need to make the first argument a pointer. I read up on
pointers but obviously there is something I missed. What I don't get is
if I create tmp[][] and then the pointer that is sent to the function,
why do I need the other variable array? How should I then declare the
pointer *arp?

/Sheldon
 
S

Sheldon

Richard Heathfield skrev:
Sheldon said:
Hi,
I have a program here that I am trying to take to another level. That
is to say that I call a function from main, pass an array pointer,
populate the array, and then write it to a file, read it again and the
print it. The problem is that i can't get past certain errors in
compiling. I am using several online tutorials that only give simple
examples.

You are also not showing us the code you are actually compiling, or you're
not telling us about all the diagnostic messages you're getting. When I
compiled your code, the compiler almost fainted! You had dropped semicolons
like a Cockney drops the letter 'h'. Still, let's see what we can do with
it.
#define row 15
#define col 15

The convention of making such constants UPPER CASE is a good one.

double readfile(double, int,int, double);

Should be:

double readfile(double *, int, int, double);

It is badly named, since it doesn't actually have anything to do with
reading, or with files.
int main() {

Not exactly wrong, but the following is better:

int main(void) {

since it explicitly defines the types of its parameters.

FILE *fp;

This should have given you an error, since you have no definition of FILE.
To fix this, add:

#include <stdio.h>

above main() somewhere.
char FILENAME[50] = "test_array.dat";

The convention of avoiding ALL UPPER CASE for ordinary object names is a
good one. ;-)
double tmp[row][col];
double *arp = &tmp[0][0]; /* pointer */
int i, j;
double count;
double array = readfile(*arp, row, col, count);

readfile requires a pointer-to-double as its first argument. Since arp has
the type pointer-to-double, *arp has the type double, which isn't the same
thing. This whole business of telling C functions about two-dimensional
arrays is far less obvious than it perhaps ought to be (although it is
eminently logical when you think it through).

I'm torn here, because I don't want to have to write a ten-page explanation
of why your whole approach to this 2D-array handling is wrong and how to
fix it, but on the other hand I don't want to leave you in the lurch.

Right now, I think the simplest fix is to show you a correct (or at least a
*more* correct) version of your program, and leave it to you to ask
questions about anything you don't understand. I don't claim to have put in
all the necessary error-checking, but I think I've got most of it:

#include <stdio.h>
#include <stdlib.h>

#define ROW 15
#define COL 15
void readfile(double (*)[ROW][COL],
int,
int,
double);
int main(void)
{
FILE *fp = NULL;
char filename[50] = "test_array.dat";
double array[ROW][COL] = { 0 };
int i, j;
double count;

readfile(&array, ROW, COL, count);

fp = fopen(filename, "wb");
if(fp != NULL)
{
fwrite(array, sizeof array, 1, fp);
fclose(fp);
fp = fopen(filename, "rb");
if(fp != NULL)
{
fread(array, sizeof count, ROW * COL, fp);
fclose(fp);
for(i = 0; i < ROW; i++)
{
for(j = 0; j < COL; j++)
{
printf("array[%d, %d] = %f\n", i, j, array[j]);
}
}
}
}
return 0;
}

void readfile(double (*array)[ROW][COL],
int row,
int col,
double count)
{
int i, j;

count = 0.0;
for(i = 0; i < row; i++)
{
for(j = 0; j < col; j++)
{
(*array)[j] = count;
count++;
}
}
}


--
Richard Heathfield
"Usenet is a strange place" - dmr 29/7/1999
http://www.cpax.org.uk
email: rjh at above domain (but drop the www, obviously)


Thanks Richard! I truly appreciated how pedagogic your answer was. I
understand now what mistakes I made. The one thing that eludes me is
the VOID infront of the function.
I will paste in the entire code this time. I left it out because I
thought it might discourage you guys from helping. As you can see, the
";" are back :<) They just got lost in the cut and paste.

#include <stdio.h>
#include <stdlib.h>
/* #define FILENAME
"/data/proj/safworks/sheldon/MSG_PPS_COMP/data/aux/test_array.dat" */
/* ROW = atoi(argv[1]); */
/* COL = atoi(argv[2]); */
#define ROW 15
#define COL 15

void readfile(double *[ROW][COL],int,int,double); /* Declaring function
parameter names are optional */

int main(void) /* why is this ?? */
{
FILE *fp = NULL; /* declare a file pointer */
char Filename[50] = "test_array.dat";
double array[ROW][COL] = {0};
int i, j;
double count;
/* Calling function for populating array */
readfile(&array, ROW, COL, count);

/* Saving data to file */
printf("Opening file: %s\n",Filename);
if ((fp = fopen(Filename, "wb")) == NULL)
{
fprintf(stderr, "Error opening file %s in write mode.\n",
Filename);
fclose(fp);
return EXIT_FAILURE;
}
else
printf("File opened successfully.\n\n");

/* Write data to file */
if(ROW*COL != fwrite(array, sizeof *array, ROW*COL, fp))
{
fprintf(stderr, "Error writing to file.\n");
fclose(fp);
return EXIT_FAILURE;
}
else
printf("File written successfully.\n\n");
fclose(fp);
/* done writing to file */

/* Reopening the file again */
printf("Opening file a second time: %s\n",Filename);
if ((fp = fopen(Filename, "rb")) == NULL)
{
fprintf(stderr, "Error opening file %s in read mode.\n",
Filename);
fclose(fp);
return EXIT_FAILURE;
}
else
printf("File opened successfully a second time.\n\n");
if (ROW*COL != fread(array, sizeof *array, ROW*COL, fp))
{
fprintf(stderr, "Error reading file: %s.\n", Filename);
fclose(fp);
return EXIT_FAILURE;
}
else
printf("File read successfully.\n\n");

/* Done reading from file */
fclose(fp);
printf("Exiting function and returning array\n");

/* display read array for debuging */
printf("Printing array\n");
for (i = 0; i < ROW; i++)
{
for (j = 0; j < COL; j++)
{
printf("array[%d,%d] = %f\n", i,j, array[j]);
}
}
return 0;
}

/************************************* FUNCTIONS
**************************************************/
void readfile(double (*array)[ROW][COL],int ROW,int COL, double count)
{
int i, j;
count =0.0;
printf("Entering readfile function\n");
/* Assigning data to the array */
for(i = 0; i < ROW; i++)
{
for(j = 0; j < COL; j++)
{
(*array)[j] = count; /* Arrays are accessed with [j] and not
[i,j] */
count++;
/* printf("%f\n",count); */
}
}
printf("Finished writing to array\n");
return EXIT_SUCCESS;
}

The errors (complete) are:
% cc test_readfile.c
test_readfile.c: In function `main':
test_readfile.c:19: warning: passing arg 1 of `readfile' from
incompatible pointer type
test_readfile.c: At top level:
test_readfile.c:80: error: parse error before numeric constant
test_readfile.c: In function `readfile':
test_readfile.c:81: error: number of arguments doesn't match prototype
test_readfile.c:9: error: prototype declaration
test_readfile.c:83: error: `count' undeclared (first use in this
function)
test_readfile.c:83: error: (Each undeclared identifier is reported only
once
test_readfile.c:83: error: for each function it appears in.)
test_readfile.c:90: error: `array' undeclared (first use in this
function)
test_readfile.c:96: warning: `return' with a value, in function
returning void


/Sheldon
 
R

Richard Heathfield

Sheldon said:
The one thing that eludes me is the VOID infront of the function.

void, not VOID

You were returning a pointless value of the wrong type from your readfile
function. It was supposed to return a double, and EXIT_SUCCESS is an int -
and you weren't using the value anyway, so I just ripped it out, and let
the function return nothing at all, since there didn't seem to be any
useful value it *could* return.
I will paste in the entire code this time. I left it out because I
thought it might discourage you guys from helping. As you can see, the
";" are back :<) They just got lost in the cut and paste.

#include <stdio.h>
#include <stdlib.h>
/* #define FILENAME
"/data/proj/safworks/sheldon/MSG_PPS_COMP/data/aux/test_array.dat" */

You might be better passing this in as an argument, rather than hard-coding
it into your program!
/* ROW = atoi(argv[1]); */
/* COL = atoi(argv[2]); */

Several points here. Firstly, now I understand why you had them as lower
case! Secondly, when you come to put the argv stuff back, bear in mind that
not everybody (not even you) will necessarily remember how to use your
program, so make sure you handle incorrect or absent arguments elegantly.
Thirdly, use strtol, not atoi. Fourthly, what was fourthly? Oh yes. When
you make these dynamic, you won't be able (portably) to use them in the
definition of your array any more. Instead, you'll have to use malloc to
get space for a bunch of pointers, and then use malloc again on each of
these in turn, to get space for a line of doubles.
#define ROW 15
#define COL 15

void readfile(double *[ROW][COL],int,int,double); /* Declaring function
parameter names are optional */

But getting the types right is not. There is a huge difference between
double(*)[ROW][COL] (which I suggested) and double *[ROW][COL] (which you
now have).

The first is a pointer to an array of ROW x COL doubles. The second is an
attempt to define an array of ROW x COL pointers to double - an attempt
that is doomed to fail, since you can't pass arrays in parameters in C.
 
S

Sheldon

Richard Heathfield skrev:
Sheldon said:
The one thing that eludes me is the VOID infront of the function.

void, not VOID

You were returning a pointless value of the wrong type from your readfile
function. It was supposed to return a double, and EXIT_SUCCESS is an int -
and you weren't using the value anyway, so I just ripped it out, and let
the function return nothing at all, since there didn't seem to be any
useful value it *could* return.
I will paste in the entire code this time. I left it out because I
thought it might discourage you guys from helping. As you can see, the
";" are back :<) They just got lost in the cut and paste.

#include <stdio.h>
#include <stdlib.h>
/* #define FILENAME
"/data/proj/safworks/sheldon/MSG_PPS_COMP/data/aux/test_array.dat" */

You might be better passing this in as an argument, rather than hard-coding
it into your program!
/* ROW = atoi(argv[1]); */
/* COL = atoi(argv[2]); */

Several points here. Firstly, now I understand why you had them as lower
case! Secondly, when you come to put the argv stuff back, bear in mind that
not everybody (not even you) will necessarily remember how to use your
program, so make sure you handle incorrect or absent arguments elegantly.
Thirdly, use strtol, not atoi. Fourthly, what was fourthly? Oh yes. When
you make these dynamic, you won't be able (portably) to use them in the
definition of your array any more. Instead, you'll have to use malloc to
get space for a bunch of pointers, and then use malloc again on each of
these in turn, to get space for a line of doubles.
#define ROW 15
#define COL 15

void readfile(double *[ROW][COL],int,int,double); /* Declaring function
parameter names are optional */

But getting the types right is not. There is a huge difference between
double(*)[ROW][COL] (which I suggested) and double *[ROW][COL] (which you
now have).

The first is a pointer to an array of ROW x COL doubles. The second is an
attempt to define an array of ROW x COL pointers to double - an attempt
that is doomed to fail, since you can't pass arrays in parameters in C.


--
Richard Heathfield
"Usenet is a strange place" - dmr 29/7/1999
http://www.cpax.org.uk
email: rjh at above domain (but drop the www, obviously)

Thanks,

Now most of the bugs are gone but it still says that there are the
following errors:

test_readfile.c:79: error: parse error before numeric constant
test_readfile.c: In function `readfile':
test_readfile.c:80: error: number of arguments doesn't match prototype
test_readfile.c:9: error: prototype declaration

I will work on this tomorrow as it is late and I a tired of looking at
this today. Thanks for your help!

/Sheldon
 
O

Old Wolf

Richard said:
Sheldon said:
#define ROW 15
#define COL 15

void readfile(double *[ROW][COL],int,int,double); /* Declaring function
parameter names are optional */
When you make these dynamic, you won't be able (portably) to use
them in the definition of your array any more.

To clarify: you can use variable array dimensions in C99 and gcc,
but not C90.
Instead, you'll have to use malloc to get space for a bunch of pointers,
and then use malloc again on each of these in turn, to get space for
a line of doubles.

I'd prefer to allocate a single block of row*col entries, and adjust
the
access syntax accordingly.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,995
Messages
2,570,228
Members
46,818
Latest member
SapanaCarpetStudio

Latest Threads

Top