Thread: Struct File and array problem Please help

  1. #1
    Registered User
    Join Date
    Mar 2009
    Posts
    10

    Struct File and array problem Please help

    Anyone knows why this code isn't working. the problem seems to be related to the size of the char arrays.

    I am trying to read some data into a struct, write the struct to a file, close the file, read the data again and print it.

    when I read and print the data again, it displays a lot of garbage characters.

    Code:
    #include <stdio.h>
    #include <stdlib.h>
    #include <conio.h>
    #include <string.h>
    
    
    struct clientInfo
    {
    
    	char name[25];
    	char address[25];
    	char telNumber[25];
    	char attentionItem [25];
    	char problemDescription[5];
    
    };
    
    
    int main()
    {
    
    	int i;
    	const int size = 2;
    	struct clientInfo data[size];
       struct clientInfo dat;
       FILE *clientFile;
    
       clientFile = fopen("clients.txt","w");
    
    	for (i = 0; i < size; i++)
    	{
          fflush(stdin);
    
    		printf ("Please enter your name\n");
          gets (data[i].name);
    		fflush(stdin);
    		printf ("Please enter your address\n");
    		gets (data[i].address);
    		fflush(stdin);
    		printf ("Please enter your telephone number\n");
    		gets (data[i].telNumber);
    		fflush(stdin);
    		printf ("Please enter the item which aquires attention\n");
    		gets (data[i].attentionItem);
    		fflush(stdin);
    		printf ("Please enter a description of the problem\n");
    		gets (data[i].problemDescription);
    		fflush(stdin);
    
       	fflush(stdin);
          fwrite(*data[i],sizeof(data[i]),1,clientFile);
    
       }//endfor
    
       fclose(clientFile);
    
       clientFile = fopen("clients.txt","r");
    
       while(!feof(clientFile))
       {
       	fread(&dat,sizeof(clientInfo),1,clientFile);
    
       	printf("name is %s\n",dat.name);
       	printf("address is %s\n",dat.address);
       	printf("telephone is %s\n",dat.telNumber);
          printf("attention is %s\n",dat.attentionItem);
       	printf("problem is %s\n",dat.problemDescription);
    
       }//end while
    
       fclose(clientFile);
    
       system("pause");
    
       return 0;
    
    }//endmain

  2. #2
    Registered User
    Join Date
    Sep 2006
    Posts
    8,868
    You're mixing your output and input modes.

    Use fprintf() for text mode, and you can use fscanf(), (or any other text mode file reader), to read the data back into your program.

    Use fwrite() to write out data in binary mode, and use fread() to read it back into your program.

    It's always good to be specific when you open files:

    Not just mode "r" for reading. Either "rt" or "rb", please. Be specific, either text or binary. Don't leave it up to some global variable buried in a header file, somewhere.

  3. #3
    Hurry Slowly vart's Avatar
    Join Date
    Oct 2006
    Location
    Rishon LeZion, Israel
    Posts
    6,788
    Quote Originally Posted by Adak View Post
    Not just mode "r" for reading. Either "rt" or "rb", please. Be specific, either text or binary. Don't leave it up to some global variable buried in a header file, somewhere.
    rt is non-standard extention

    r - is standard for text mode
    rb is standard for binary mode.

    To the OP:

    Also fflush(stdin) is undefined - read FAQ. FAQ has samples how to get rid of junk in the input buffer using standard ways

    gets should not be used - we have FAQ on the issue.


    feof should not be used to control loops. FAQ explains why
    All problems in computer science can be solved by another level of indirection,
    except for the problem of too many layers of indirection.
    – David J. Wheeler

  4. #4
    Registered User Maz's Avatar
    Join Date
    Nov 2005
    Location
    Finland
    Posts
    194
    Also, if you write the data in file member-by-member in binary, it is possible you'll be bitten by struct padding.

  5. #5
    Registered User
    Join Date
    Sep 2006
    Posts
    8,868
    On what compiler do you get an error with file mode "rt"?

    I use three compilers and have not noticed any problem with it.

  6. #6
    Hurry Slowly vart's Avatar
    Join Date
    Oct 2006
    Location
    Rishon LeZion, Israel
    Posts
    6,788
    Quote Originally Posted by Adak View Post
    On what compiler do you get an error with file mode "rt"?

    I use three compilers and have not noticed any problem with it.
    And it makes this mode standard in your opinion?
    All problems in computer science can be solved by another level of indirection,
    except for the problem of too many layers of indirection.
    – David J. Wheeler

  7. #7
    Registered User
    Join Date
    Oct 2008
    Location
    TX
    Posts
    2,059
    Surprised that the compiler did not barf when it came across *data[i] as in.
    Code:
    fwrite(*data[i],sizeof(data[i]),1,clientFile); /* first arg should be a void pointer */
    Instead of testing for feof() on the stream, a better test is to terminate if no. of items read is less than requested.
    Code:
    while(!feof(clientFile))  ???

  8. #8
    Registered User
    Join Date
    Sep 2006
    Posts
    8,868
    Quote Originally Posted by vart View Post
    And it makes this mode standard in your opinion?
    If it works better, I tend to use it. Portability not only means the current compilers, but also the legacy compilers, if you have programs created for them.

    I do, so I use what works best for me. I recommend it here, because a lot of the students are still using the legacy compilers.

    Did you notice the conio.h include file, Vart? That's pretty much a gimme that he's using Turbo C, and my advice is targeted at Turbo C users (like me, sometimes).
    Last edited by Adak; 04-01-2009 at 02:52 AM.

  9. #9
    Registered User
    Join Date
    Mar 2009
    Posts
    10

    Mistake

    it should be &data[i] and not *data[i] * I had changed it while attempting to debug the program. program seems to be fine. if I make all thee arrays sizes small. but gives problems when the array sizes are too large.

    I really would like to continue using fwrite and gets.

    gets because the name and address plus some other fields need to accept spaces.
    fwrite because the struct is much larger than in the code I cut it down to help focus on the problem. And I do not want to have to use individual fprintf and fscanf statements for each field in the struct. Additionally I think fprintf and fscanf has problems with reading and writing spaces.

    The first field is always fine. I might end up with a problem on the secord third fourth or fifth to the last field.

    Thanks for all the replies

  10. #10
    Registered User
    Join Date
    Mar 2009
    Posts
    10

    Half Solution

    I read the faq's that vart suggested on fflush, feof, and fgets. I made the necessary changes I also am now reading in binary mode. the only effect now is that it is ony printing three characters from the string.
    Code:
    #include <stdio.h>
    #include <stdlib.h>
    #include <conio.h>
    #include <string.h>
    
    #define size 2
    
    struct clientInfo
    {
    
    	char name[25];
    	char address[25];
    	char telNumber[25];
    	char attentionItem [25];
    	char problemDescription[6];
    
    };
    
    
    int main()
    {
    
    	int i,ch;
    	struct clientInfo data[size];
       struct clientInfo dat;
       FILE *clientFile;
    
       clientFile = fopen("clients.txt","wb");
    
    	for (i = 0; i < size; i++)
    	{
    
    		printf ("Please enter your name\n");
          fgets (data[i].name,sizeof(sizeof(char) * 25),stdin);
    		//fflush(stdin);
          while ((ch = getchar()) != '\n' && ch != EOF);
    		printf ("Please enter your address\n");
    		fgets (data[i].address,sizeof(sizeof(char) * 25),stdin);
    		//fflush(stdin);
          while ((ch = getchar()) != '\n' && ch != EOF);
    		printf ("Please enter your telephone number\n");
    		fgets (data[i].telNumber,sizeof(sizeof(char) * 25),stdin);
    		//fflush(stdin);
          while ((ch = getchar()) != '\n' && ch != EOF);
    		printf ("Please enter the item which aquires attention\n");
    		fgets (data[i].attentionItem,sizeof(sizeof(char) * 25),stdin);
          while ((ch = getchar()) != '\n' && ch != EOF);
    		//fflush(stdin);
    		printf ("Please enter a description of the problem\n");
    		fgets (data[i].problemDescription,sizeof(sizeof(char) * 6),stdin);
          while ((ch = getchar()) != '\n' && ch != EOF);
    
          fwrite(&data[i],sizeof(data[i]),1,clientFile);
    
       }//endfor
    
       fclose(clientFile);
    
       clientFile = fopen("clients.txt","rb");
    
       while(fread(&dat,sizeof(struct clientInfo),1,clientFile) != 0)
       {
       	printf("name is %s\n",dat.name);
       	printf("address is %s\n",dat.address);
       	printf("telephone is %s\n",dat.telNumber);
          printf("attention is %s\n",dat.attentionItem);
       	printf("problem is %s\n",dat.problemDescription);
    
       }//end while
    
       fclose(clientFile);
    
       system("pause");
    
       return 0;
    
    }//endmain
    Why is it only printing three characters from each string

    for example if I entered Michelle for a name it gives me "Mic" only

    Thanks in advance

  11. #11
    Registered User
    Join Date
    Sep 2008
    Posts
    53
    Code:
    PHP Code:
    #define size 2 
    you only allow it too using fgets this way.
    PHP Code:
    for (0sizei++)     {         printf ("Please enter your name\n");       fgets (data[i].name,sizeof(sizeof(char) * 25),stdin); 
    here is how i use fgets and i am not sure if am doing it right either but it reads the specified max input and prints it out.
    PHP Code:
    #include <stdio.h> int main(int argcchar** argv) {     char str[200];           fgets(str,(sizeof str),stdin);          printf("%s\n",str);         return 0; } 
    you have only allowed it to read the defined 2 bytes as maxsize plus the extra character from the increment of i++ .also
    PHP Code:
     (sizeof char 
    ) is one byte exactly. hope it helps. i am newbie and i have really bad eyesight so apology if i missed anything or made any mistakes.

  12. #12
    Hurry Slowly vart's Avatar
    Join Date
    Oct 2006
    Location
    Rishon LeZion, Israel
    Posts
    6,788
    in general fgets with arrays is used like:

    Code:
    char buf[25];
    if(fgets(buf,sizeof buf, fp))
    {
       /* do something with buf */
    }
    your case is no different...

    Code:
    fgets (data[i].problemDescription,sizeof(data[i].problemDescription),stdin);
    note that after EOF is reached - nothing will be read from the stream - so you should not continue your input after that
    All problems in computer science can be solved by another level of indirection,
    except for the problem of too many layers of indirection.
    – David J. Wheeler

  13. #13
    Registered User
    Join Date
    Oct 2008
    Location
    TX
    Posts
    2,059
    There is really no use for the while loop below:
    Code:
    while ((ch = getchar()) != '\n' && ch != EOF);   /* unnecessary imo */
    fread() should terminate when no. of items read is not equal to 1 as in:
    Code:
    while(fread(&dat,sizeof(struct clientInfo),1,clientFile) == 1)
    Last edited by itCbitC; 04-01-2009 at 02:55 PM.

  14. #14
    Registered User
    Join Date
    Mar 2009
    Posts
    10

    Thumbs up Thanks every one

    The reason for the while loop is to clean out the input stream as suggested in the faq instead of using fflush(stdin) however I removed them and the code still works.

    Thanks a lot to everyone
    Thanks vart for making me read the faqs they were very enlightening.
    cmay your suggestion finally got my code working.

    ItCbitC thanks for all your suggestion.

    Thanks a lot I can't say thanks enough to you guys.

    Here is the modified and working code

    Code:
    #include <stdio.h>
    #include <stdlib.h>
    #include <conio.h>
    #include <string.h>
    
    #define size 2
    
    struct clientInfo
    {
    
    	char name[25];
    	char address[25];
    	char telNumber[25];
    	char attentionItem [25];
    	char problemDescription[200];
    
    };
    
    
    int main()
    {
    
    	int i;
    	struct clientInfo data[size];
       struct clientInfo dat;
       FILE *clientFile;
    
       clientFile = fopen("clients.txt","wb");
    
    	for (i = 0; i < size; i++)
    	{
    
    		printf ("Please enter your name\n");
          fgets (data[i].name,sizeof(data[i].name),stdin);
    
    		printf ("Please enter your address\n");
    		fgets (data[i].address,sizeof(data[i].name),stdin);
    
    		printf ("Please enter your telephone number\n");
    		fgets (data[i].telNumber,sizeof(data[i].name),stdin);
    
    		printf ("Please enter the item which aquires attention\n");
    		fgets (data[i].attentionItem,sizeof(data[i].name),stdin);
    
          printf ("Please enter a description of the problem\n");
    		fgets (data[i].problemDescription,sizeof(data[i].name),stdin);
    
          //write information to file
          fwrite(&data[i],sizeof(data[i]),1,clientFile);
    
       }//endfor
    
       fclose(clientFile);
    
       clientFile = fopen("clients.txt","rb");
    
       while(fread(&dat,sizeof(struct clientInfo),1,clientFile) == 1)
       {
       	printf("name is %s\n",dat.name);
       	printf("address is %s\n",dat.address);
       	printf("telephone is %s\n",dat.telNumber);
          printf("attention is %s\n",dat.attentionItem);
       	printf("problem is %s\n",dat.problemDescription);
    
       }//end while
    
       fclose(clientFile);
    
       system("pause");
    
       return 0;
    
    }//end main

  15. #15
    Registered User caroundw5h's Avatar
    Join Date
    Oct 2003
    Posts
    751
    If it works better, I tend to use it. Portability not only means the current compilers, but also the legacy compilers
    sounds like "quick it compiles! ship it!" lol. Adak, round here we emphasize ISO C, code thats guranteed to work across pretty much all platforms.

    Code:
    #include <stdio.h>
    #include <stdlib.h>
    #include <conio.h>
    #include <string.h>
    what functions are you calling with conio.h programmer, i may have overlooked it but i don't see any reason in your code for it. again, i may have missed it, but let me know.


    There is really no use for the while loop below:
    Code:

    while ((ch = getchar()) != '\n' && ch != EOF); /* unnecessary imo */
    you could make it even more compact
    Code:
    #define FLUSH while ( (getchar() ! = '\n') )
    and then call FLUSH whenever you want to clean out the buffer.

    Code:
     fclose(clientFile);
    
       system("pause");
    you should check the return value of fclose to make sure that your file closed properly, there could be any number of reasons it didn't and then you shut down your program. Also your code may not be mission critical but try to get into the habit of writing portable, clean C code according to the std regardless of what is said other wise - and avoid using system("pause")
    Warning: Opinions subject to change without notice

    The C Library Reference Guide
    Understand the fundamentals
    Then have some more fun

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Problem with file and array
    By paok in forum C Programming
    Replies: 5
    Last Post: 05-01-2008, 04:19 AM
  2. File I/O problem for dynamically allocated struct array
    By veecee in forum C++ Programming
    Replies: 2
    Last Post: 05-05-2006, 09:28 PM
  3. Unknown Memory Leak in Init() Function
    By CodeHacker in forum Windows Programming
    Replies: 3
    Last Post: 07-09-2004, 09:54 AM
  4. Passing pointers between functions
    By heygirls_uk in forum C Programming
    Replies: 5
    Last Post: 01-09-2004, 06:58 PM
  5. what does this mean to you?
    By pkananen in forum C++ Programming
    Replies: 8
    Last Post: 02-04-2002, 03:58 PM