(Newbie) My Loop Isn't Looping - Aargh!
Author |
Message |
The Wrong Trouse #1 / 8
|
 (Newbie) My Loop Isn't Looping - Aargh!
Hello... I really hope this question isn't as stupid as I have the sinking feeling it might be, but I'm willing to look like a fool at this point, after forty-two straight hours of working on this. (As you might guess, I'm a novice at both C and programming.) This is a small program that refers to an already-created .dat file of ten student records. The program should go through and print these ten records out in order, then die gracefully. Instead, it's printing out just the first record in the dat file ten times. I know I'm doing something wrong, and I know it must be something simple, but at this point I've gone through the book three or four times and tried many different things with no success. (I'm attempting to learn C from a free online course and a couple of textbooks a friend was generous enough to give me.) Any help that anyone can offer will be accepted with crawling, groveling gratitude. Code follows. Thanks, Trou #include <stdio.h> #include <string.h> struct record /*student record structure */ { char fname[16]; char lname[16]; char id[8]; char street[31]; char city[11]; char state[3]; char zip[10]; char ssn[10]; char major[5]; int credits; }; FILE *myfile; /* function to read student records - 23 */ struct record read_record (int c) { struct record student_file[10]; char buffer[255]; /*int c; counter */ myfile = fopen ("roster.dat", "r"); fgets (buffer, 254, myfile); strncpy (student_file[c].fname, buffer, 15); student_file[c].fname[15]='\0'; /*printf ("test fname: %s \n", student_file[c].fname); */ fgets (buffer, 254, myfile); strncpy (student_file[c].lname, buffer, 15); student_file[c].lname[15]='\0'; /*40 printf ("test lname: %s \n", student_file[c].lname);*/ fgets (buffer, 254, myfile); strncpy (student_file[c].id, buffer, 7); student_file[c].id[7]='\0'; /*printf ("test id: %s \n", student_file[c].id);*/ fgets (buffer, 254, myfile); strncpy (student_file[c].street, buffer, 30); student_file[c].street[30]='\0'; /*50 printf ("test street address: %s \n", student_file[c].street);*/ fgets (buffer, 254, myfile); strncpy (student_file[c].city, buffer, 10); student_file[c].city[10]='\0'; /*printf ("test city address: %s \n", student_file[c].city);*/ fgets (buffer, 254, myfile); strncpy (student_file[c].state, buffer, 2); student_file[c].state[2]='\0'; /*60 printf ("test state address: %s \n", student_file[c].state);*/ fgets (buffer, 254, myfile); strncpy (student_file[c].zip, buffer, 9); student_file[c].zip[9]='\0'; /*printf ("test zip: %s \n", student_file[c].zip);*/ fgets (buffer, 254, myfile); strncpy (student_file[c].ssn, buffer, 9); student_file[c].ssn[9]='\0'; /*70 printf ("test ssn: %s \n", student_file[c].ssn);*/ fgets (buffer, 254, myfile); strncpy (student_file[c].major, buffer, 4); student_file[c].major[4]='\0'; /*printf ("%s \n", student_file[c].major);*/ fscanf (myfile, "%d", &student_file[c].credits); /*80 printf ("%d \n", student_file[c].credits);*/ fclose (myfile); return (student_file[c]); } void main () { struct record student_records[10]; int x; int y; for (x=0; x<10; ++x) { student_records[x] = read_record (x); printf ("Student Record Number %i \n", y); printf ("Student's first name: %s \n", student_records[x].fname); printf ("Student's last name: %s \n", student_records[x].lname); printf ("Student's ID number: %s \n", student_records[x].id); printf ("Student's street address: %s \n", student_records[x].street); printf ("Student's city address: %s %s %s \n", student_records[x].city, student_records[x].state, student_records[x].zip); printf ("Student's SSN: %s \n", student_records[x].ssn); printf ("Student's major: %s \n", student_records[x].major); printf ("Student's credits: %d \n", student_records[x].credits); printf ("\n"); y=x+1; printf ("x value: %i \n", x); } Quote: }
|
Fri, 26 Apr 2002 03:00:00 GMT |
|
 |
Riyaz Mansoo #2 / 8
|
 (Newbie) My Loop Isn't Looping - Aargh!
Quote: > This is a small program that refers to an already-created .dat file of > ten student records. The program should go through and print these ten > records out in order, then die gracefully. Instead, it's printing out > just the first record in the dat file ten times. > void main () > { > struct record student_records[10]; > int x; > int y; > for (x=0; x<10; ++x) blah blah > }
the above could be your error. what is happening is you're opening the file and reading in the first record and in that procedure you're closing the file as well. so when u call to read the second record it opens the file again and AGAIN reads in the first record. what u could do is open and close the file in the main procedure. this way it is opened only once and closed only once. as it is now, it is opened 10 times and closed 10 times. riyaz
|
Fri, 26 Apr 2002 03:00:00 GMT |
|
 |
Herbert Martin Dietz #3 / 8
|
 (Newbie) My Loop Isn't Looping - Aargh!
Two things: Quote: > /* function to read student records - 23 */ > struct record read_record (int c) > {
/* ... */ Quote: > myfile = fopen ("roster.dat", "r");
/* ... */ Quote: > fclose (myfile);
If you open and close the file for every record you'll always only read the first record. Open the file in main() and pass the handle of the open file to the function. After all is read close the file in main(). Quote: > void main ()
This is forbidden. ANSI/ISO states main() always returns int. You might also want to put a `void' into the parentheses to state your main() takes no arguments - the way you did it implies any parameter list for calling main() is allowed. Cheers, Herbert -- #define S "Goodbye!\n" main(){exit(printf(S) != strlen(S) ? 0 : 1);}
|
Fri, 26 Apr 2002 03:00:00 GMT |
|
 |
Stephan Wilm #4 / 8
|
 (Newbie) My Loop Isn't Looping - Aargh!
The Wrong Trousers schrieb: Quote: Hi "The Wrong Trousers", Quote: > I really hope this question isn't as stupid as I have the sinking feeling > it might be, but I'm willing to look like a fool at this point, after > forty-two straight hours of working on this. (As you might guess, I'm a > novice at both C and programming.)
I hope my answer reaches you before spending another two days on the problem :-) It's not a big deal and easy to fix. I've mixed a bit of additional advice in the hope that you might find it useful. Quote: > This is a small program that refers to an already-created .dat file of > ten student records. The program should go through and print these ten > records out in order, then die gracefully. Instead, it's printing out > just the first record in the dat file ten times.
The root of the problem is, that "fopen()" makes a file available to your program and places the read pointer firmly at the beginning of the file. when you open for reading you *always* start at the first byte of the file. That's why you read the same stuff 10 times. Simple solution: open the file *outside* of the loop and pass the "FILE*" to the "read_record" function as a parameter One general observation: the indentation of your code looks really horrible in the posted form. This might be due to your use of the "TAB" character in the source code. If so, you should do a conversion (TAB to spaces) before posting source code. Quote: > struct record /*student record structure */ > { > char fname[16]; > char lname[16]; > char id[8]; > char street[31]; > char city[11]; > char state[3]; > char zip[10]; > char ssn[10]; > char major[5]; > int credits; > };
It is a good idea to use macros for maximum array sizes. This enhances the maintainability (and quite often the readability) of the code. Example: #define MAX_FILENAME 16 #define MAX_LASTNAME 16 #define MAX_ID 8 Quote: > FILE *myfile;
This can safely be made a local variable in "main()". Quote: > /* function to read student records - 23 */ > struct record read_record (int c) > {
To pass in the file as a parameter use: struct record read_record( FILE *myfile, int c ) Quote: > struct record student_file[10];
This function is supposed to read a *single* student record. Therefore you do not need an array here. A single record will do: struct record myStudent; Quote: > char buffer[255]; > /*int c; counter */ > myfile = fopen ("roster.dat", "r");
This does not belong here. It should be done by the calling function *before* the loop. And you should *NEVER* forget to check the return value of "fopen()" against NULL ! Quote: > fgets (buffer, 254, myfile);
The "fgets()" function can return an error status that you should not neglect to check: result = fgets (buffer, 254, myfile); if ( result == NULL ) { /* handle file I/O error here */ } Quote: > strncpy (student_file[c].fname, buffer, 15); > student_file[c].fname[15]='\0';
Two things to note: 1) you have commented out "c" above and 2) this is a good place for using the macros ones you have defined them: strncpy( myStudent.fname, buffer, MAX_FILENAME ); myStudent.fname[MAX_FILENAME-1]='\0'; [biggish SNIP] Quote: > fclose (myfile);
Soem as with "fopen()": close the function in the calling function after the loop. Quote: > return (student_file[c]);
This will of course become: return myStudent; Quote: The only real correct return type for "main()" is "int". Some compilers allow "void", but it is not portable and it is not ANSI-C. The correct equivalent form would be: int main( void ) Quote: > {
[more snippage] Now *you* apply the changes, that I mentioned in my comments, to the "main()" function ;-) But do ask again if it should not work as expected. -- Stephan initiator of the campaign against grumpiness in c.l.c fight the bug, read the FAQ: http://www.eskimo.com/~scs/C-faq/top.htm
|
Fri, 26 Apr 2002 03:00:00 GMT |
|
 |
Ashish Agarwa #5 / 8
|
 (Newbie) My Loop Isn't Looping - Aargh!
Hello, The basic problem is that you aren't paying attention to the data writing program. As data reading program shows you must be using fputs statement to write the data stucture to the file. Now if you will open the data file you will see all the data arranged in a line with no specific length now when you read first 254 bytes with this progam it reads the data as string and not as a structure. Firstly you should use fread and fwrite command to read and write to data file .. I am writing a small code to show its usage. #include "stdio.h" #include "string.h" int main(void) { struct record { char name[15]; char id[15]; Quote: }record1;
FILE * in; struct record * recordptr; gets(record1.name); gets(record1.id); in=fopen("data.dat","r+"); recordptr=&record1; fwrite(recordptr,sizeof (struct record), 1,in); fclose(in); in=fopen("data.dat","r+"); fread(recordptr,sizeof (struct record),1,in); printf("%s",record1.name); printf("%s",record1.id); return 0; Quote: }
secondly .. if at all you are determined to make use of fgets and fputs ..then you had to do one thing... you had to write "\n" to file after every fputs {....... char *enter= "\n"; fputs(data1,n); fputs(enter,in); fputs(data2,in); fputs(enter,in); .............. thirdly ... you are reading data into a buffer of 255 bytes which is not at allrequired over here but it is only eating memory and unnecessay confusion ..why the hell you areusing strncpy and the command after it these are all useless Quote: > fgets (buffer, 254, myfile); > strncpy (student_file[c].fname, buffer, 15); > student_file[c].fname[15]='\0'; > /*printf ("test fname: %s \n", student_file[c].fname); */
this work can be done in only one line fgets(student_file[c].fname, sizeof(student_file[c].fname),myfile); one important thing to clearify at this point is the use of strlen and sizeof ... u cannot use strlen because it gives size of the current string and currently no data is present in the structure so you just cannot use strlen where as sizeof tell the size of the current element and so we had to make use of it to get the correct size. fourthly .. you had made use of y in your main with out initializing it to zero ....well you had defined an auto variable and it is not initialized to zero automatically but retain in memory either use the word static or initialize it manually to zero static int y; After reading this please reply me back, I am having problem with this e-mail account, so that I can assure that you had got the reply. If you need to know anything else please let me know. Bye Ashish
Quote: > Hello... > I really hope this question isn't as stupid as I have the sinking feeling > it might be, but I'm willing to look like a fool at this point, after > forty-two straight hours of working on this. (As you might guess, I'm a > novice at both C and programming.) > This is a small program that refers to an already-created .dat file of > ten student records. The program should go through and print these ten > records out in order, then die gracefully. Instead, it's printing out > just the first record in the dat file ten times. > I know I'm doing something wrong, and I know it must be something simple, > but at this point I've gone through the book three or four times and > tried many different things with no success. (I'm attempting to learn C > from a free online course and a couple of textbooks a friend was generous > enough to give me.) > Any help that anyone can offer will be accepted with crawling, groveling > gratitude. Code follows. > Thanks, > Trou > #include <stdio.h> > #include <string.h> > struct record /*student record structure */ > { > char fname[16]; > char lname[16]; > char id[8]; > char street[31]; > char city[11]; > char state[3]; > char zip[10]; > char ssn[10]; > char major[5]; > int credits; > }; > FILE *myfile; > /* function to read student records - 23 */ > struct record read_record (int c) > { > struct record student_file[10]; > char buffer[255]; > /*int c; counter */ > myfile = fopen ("roster.dat", "r"); > fgets (buffer, 254, myfile); > strncpy (student_file[c].fname, buffer, 15); > student_file[c].fname[15]='\0'; > /*printf ("test fname: %s \n", student_file[c].fname); */ > fgets (buffer, 254, myfile); > strncpy (student_file[c].lname, buffer, 15); > student_file[c].lname[15]='\0'; > /*40 printf ("test lname: %s \n", student_file[c].lname);*/ > fgets (buffer, 254, myfile); > strncpy (student_file[c].id, buffer, 7); > student_file[c].id[7]='\0'; > /*printf ("test id: %s \n", student_file[c].id);*/ > fgets (buffer, 254, myfile); > strncpy (student_file[c].street, buffer, 30); > student_file[c].street[30]='\0'; > /*50 printf ("test street address: %s \n", > student_file[c].street);*/ > fgets (buffer, 254, myfile); > strncpy (student_file[c].city, buffer, 10); > student_file[c].city[10]='\0'; > /*printf ("test city address: %s \n", student_file[c].city);*/ > fgets (buffer, 254, myfile); > strncpy (student_file[c].state, buffer, 2); > student_file[c].state[2]='\0'; > /*60 printf ("test state address: %s \n", > student_file[c].state);*/ > fgets (buffer, 254, myfile); > strncpy (student_file[c].zip, buffer, 9); > student_file[c].zip[9]='\0'; > /*printf ("test zip: %s \n", student_file[c].zip);*/ > fgets (buffer, 254, myfile); > strncpy (student_file[c].ssn, buffer, 9); > student_file[c].ssn[9]='\0'; > /*70 printf ("test ssn: %s \n", student_file[c].ssn);*/ > fgets (buffer, 254, myfile); > strncpy (student_file[c].major, buffer, 4); > student_file[c].major[4]='\0'; > /*printf ("%s \n", student_file[c].major);*/ > fscanf (myfile, "%d", &student_file[c].credits); > /*80 printf ("%d \n", student_file[c].credits);*/ > fclose (myfile); > return (student_file[c]); > } > void main () > { > struct record student_records[10]; > int x; > int y; > for (x=0; x<10; ++x) > { > student_records[x] = read_record (x); > printf ("Student Record Number %i \n", y); > printf ("Student's first name: %s \n", > student_records[x].fname); > printf ("Student's last name: %s \n", > student_records[x].lname); > printf ("Student's ID number: %s \n", > student_records[x].id); > printf ("Student's street address: %s \n", > student_records[x].street); > printf ("Student's city address: %s %s %s \n", > student_records[x].city, student_records[x].state, > student_records[x].zip); > printf ("Student's SSN: %s \n", student_records[x].ssn); > printf ("Student's major: %s \n", > student_records[x].major); > printf ("Student's credits: %d \n", > student_records[x].credits); > printf ("\n"); > y=x+1; > printf ("x value: %i \n", x); > } > }
|
Fri, 26 Apr 2002 03:00:00 GMT |
|
 |
Gergo Bara #6 / 8
|
 (Newbie) My Loop Isn't Looping - Aargh!
[snip] Quote: > #include "stdio.h" > #include "string.h"
Use the proper <> forms. Quote: > int main(void) > { > struct record { > char name[15]; > char id[15]; > }record1; > FILE * in; > struct record * recordptr;
Adopt or develop a coding style. Quote: > gets(record1.name); > gets(record1.id);
Never use gets(). Never tell anyone to use gets(). Quote: > in=fopen("data.dat","r+");
Check for NULL. Quote: > recordptr=&record1; > fwrite(recordptr,sizeof (struct record), 1,in); > fclose(in); > in=fopen("data.dat","r+"); > fread(recordptr,sizeof (struct record),1,in);
recordptr is redundant. Quote: > printf("%s",record1.name); > printf("%s",record1.id); > return 0; > } [snip] > > fgets (buffer, 254, myfile); > > strncpy (student_file[c].fname, buffer, 15); > > student_file[c].fname[15]='\0'; > > /*printf ("test fname: %s \n", student_file[c].fname); */ > this work can be done in only one line > fgets(student_file[c].fname, sizeof(student_file[c].fname),myfile);
His code removes the newline that might be hiding in the string. [snip rest] Gergo -- The fortune program is supported, in part, by user contributions and by a major grant from the National Endowment for the Inanities. GU d- s:+ a--- C++>$ UL+++ P>++ L+++ E>++ W+ N++ o? K- w--- !O !M !V PS+ PE+ Y+ PGP+ t* 5+ X- R>+ tv++ b+>+++ DI+ D+ G>++ e* h! !r !y+
|
Fri, 26 Apr 2002 03:00:00 GMT |
|
 |
Nick Keighle #7 / 8
|
 (Newbie) My Loop Isn't Looping - Aargh!
<snip> Quote: > This is a small program that refers to an already-created .dat file of > ten student records. The program should go through and print these > ten records out in order, then die gracefully. Instead, it's printing > out just the first record in the dat file ten times.
<snip> other posters have have pointed out your major errors- repeatedly re-opening the file and void main(). Quote: > #include <stdio.h> > #include <string.h> > struct record /*student record structure */ > { > char fname[16]; > char lname[16]; > char id[8]; > char street[31]; > char city[11]; > char state[3]; > char zip[10]; > char ssn[10]; > char major[5]; > int credits; > }; > FILE *myfile; > /* function to read student records - 23 */ > struct record read_record (int c) > { > struct record student_file[10]; > char buffer[255]; > /*int c; counter */ > myfile = fopen ("roster.dat", "r"); > fgets (buffer, 254, myfile);
this reads the first line of the file Quote: > strncpy (student_file[c].fname, buffer, 15); > student_file[c].fname[15]='\0';
you don't need to do this. strncpy() should terminate the string. Quote: > /*printf ("test fname: %s \n", student_file[c].fname); */ > fgets (buffer, 254, myfile);
this reads the second line of the file. I don't think you meant to do that did you... Quote: > strncpy (student_file[c].lname, buffer, 15); > student_file[c].lname[15]='\0'; > /*40 printf ("test lname: %s \n", student_file[c].lname);*/ > fgets (buffer, 254, myfile);
etc. etc. Quote: > strncpy (student_file[c].id, buffer, 7); > student_file[c].id[7]='\0'; > /*printf ("test id: %s \n", student_file[c].id);*/
<snip> I'm curious, how come your diagnostic printf()s show you what was going on? -- Both the tractability and the invisibility of the software product expose its builders to perpetual changes in requirements... -- Brookes Sent via Deja.com http://www.deja.com/ Before you buy.
|
Sat, 27 Apr 2002 03:00:00 GMT |
|
 |
Homer Simpso #8 / 8
|
 (Newbie) My Loop Isn't Looping - Aargh!
Quote: >> strncpy (student_file[c].fname, buffer, 15); >> student_file[c].fname[15]='\0'; >you don't need to do this. strncpy() should terminate the string.
AFAIK, what you said is correct concerning strncat(), but strncpy() will not add the final 0 if the maximum length is reached. IMO, this is a specification-bug of the C-RTL. -- HS C- FAQ: http://www.eskimo.com/~scs/C-faq/top.html About gets() and fflush(stdin) : - "Even Buffy cannot slay the resulting RhinoDaemons." Martin Ambuhl clc.
|
Sat, 27 Apr 2002 03:00:00 GMT |
|
|
|