Thread: Weird problem in C.

  1. #1
    Fountain of knowledge.
    Join Date
    May 2006
    Posts
    794

    Weird problem in C.

    This relates to something else I was doing, but anyway, basically I have this program which has a 'bug' in it. To use the program you must first compile and run it with the variable "readwrite" set to 0 for it to create a data file. Then change it to 1 and recompile it and run it.

    Basically the program creates some data and reads it back in again and it should be the same, however the data is wrong (shifted).
    Can anyone eplain why?


    Code:
    #include <stdio.h>
    #include <string.h>
    #include <stdlib.h>
    #include <io.h>
    #include <fcntl.h>
    #include <errno.h>
    
    
    #define TRUE 1
    #define FALSE 0
    #define MINUS -1
    #define POSITIVE 0
    #define MAXLIST 8000
    
    
    FILE *ptr1, *ptr2, *ptr3, *ptr4;
    
    FILE  *dataptr;
    
    
    typedef struct {
    			char name[11];		
    			float stack;	
    			float dolstack;
    			float tempval;
    			float crap;
    			int	gamesplayed;
    			int tookpart;
    			int tookpart3;
    			int tookpart5;
    			int tookpart8;
    			int five;
    			int eight;
    			int three;
    			int unmatched;
    			int pfr;
    			int afr;
    			int atr;
    			int arr;
    			float win;
    			float win5;
    			float tempstack;
    			float crap2;
    			} PLYR;
    			
    PLYR  pname[MAXLIST];	
    
    int readwrite=1;	
    int lc=0;
    
    main(argc,argv)
    	int  argc;
    	char *argv[]; 
    {
    	
    if (!readwrite){
    	
    	while(lc<200){
    	
    	    strcpy(pname[lc].name,"hellothere");
    		pname[lc].stack=12.4;
    		pname[lc].dolstack=123.4;
    		pname[lc].tempval=23.43;
    		pname[lc].gamesplayed=66;
    		pname[lc].tookpart=5432;
    		pname[lc].tookpart3=624;
    		pname[lc].tookpart5=62222;			
    		pname[lc].five=3536;
    		pname[lc].eight=994;
    		pname[lc].three=6365;
    		pname[lc].unmatched=653;
    		lc++;
    		
    	}
    	datasave();
    		
    } else {
    		lc=0;
    	
    		dataread();
    		
    		while (  lc<200)  {
    			printf("\n<%s>",    pname[lc].name);
    			printf("<%f>",  pname[lc].stack);
    			printf("<%f>",  pname[lc].dolstack);
    			printf("<%f>",  pname[lc].tempval);
    			printf("<%d>",  pname[lc].gamesplayed);
    			printf("<%d>",  pname[lc].tookpart);
    			printf("<%d>",  pname[lc].tookpart3);
    			printf("<%d>",  pname[lc].tookpart5);			
    			printf("<%d>",  pname[lc].five);
    			printf("<%d>",  pname[lc].eight);
    			printf("<%d>",  pname[lc].three);
    			printf("<%d>",  pname[lc].unmatched);
    
    			
    			
    			lc++;
    
    		
    	
    			}
    
    
    }
    }
    
    datasave(){
    int i;
    
    	
    		printf("\n openinig %d", errno);
    	
    		if (	(dataptr=fopen("data.doc", "w+" )) != NULL) {
    				fwrite(  pname, sizeof( pname   ), 1, dataptr);
    				fclose(dataptr);
    			
    		}
    		else {
    			printf("\n error %d", errno);
    			puts("\nCant creat datafile");
    			exit(2);
    
    		}
    		printf("\n error after %d", errno);
    
    }
    
    dataread(){
    
    		if (	(dataptr=fopen("data.doc", "r" )) != NULL) {
    			fread(  pname, sizeof( pname   ), 1, dataptr);
    			fclose(dataptr);
    			
    		}
    		else {
    			printf("\n read errorerror %d", errno);
    			puts("\nCant read datafile");
    			exit(2);
    
    		}
    
    }


    The output

    Code:
    <hellothere><12.400000><123.400002><23.430000><66><5432><624><62222><-503316272><-587202557><-1929379816><2>
    <ellothere><-202663520.000000><0.000000><0.000000><939524096><1879048213><234881026><243><65142784><417136640><42795008><0>
    <llothere><-107612720.000000><406691939335599541850000000000.000000><0.000000><355991552><40894464><-217186304><0><254464><1629440><167168><0>
    <lothere><-2076936724493001671600000000000000.000000><-0.003672><0.000000><1390592><159744><15928832><0><994><6365><653><0>
    <othere><123.400002><23.430000><0.000000><5432><624><62222><0><-587202557><-1929379816><2><0>
    <there><0.000000><0.000000><32.000000><1879048213><234881026><243><-805306368><417136640><42795008><0><0>
    <here><406691939335599541850000000000.000000><0.000000><0.000000><40894464><-217186304><0><13631488><1629440><167168><0><0>
    <ere><-0.003672><0.000000><0.000000><159744><15928832><0><53248><6365><653><0><0>
    <re><23.430000><0.000000><0.000000><624><62222><0><-503316272><-1929379816><2><0><0>
    <e><0.000000><32.000000><0.000031><234881026><243><-805306368><65142784><42795008><0><0><0>
    <><0.000000><0.000000><0.000000><-217186304><0><13631488><254464><167168><0><0><0>
    <><0.000000><0.000000><0.000000><15928832><0><53248><994><653><0><0><0>
    <ffFA迒蠛小翠><0.000000><0.000000><0.000000><62222><0><-503316272><-587202557><2><0><0><0>
    <fFA迒蠛小翠><32.000000><0.000031><158456721707313236230000000000.000000><243><-805306368><65142784><417136640><0><0><0><0>
    <FA迒蠛小翠><0.000000><0.000000><0.000000><0><13631488><254464><1629440><0><0><0><0>
    <A迒蠛小翠><0.000000><0.000000><0.000000><0><53248><994><6365><0><0><0><0>
    As you can see the data is being shifted to the left (well the "hellothere" string is anyway so I assume the rest is. So do you get the same results and can you explain why this happes?

  2. #2
    Fountain of knowledge.
    Join Date
    May 2006
    Posts
    794
    I should add that the data file is written correctly, as you can see that using a hex editor, or similar

  3. #3
    Fountain of knowledge.
    Join Date
    May 2006
    Posts
    794
    Actually eventually the data comes back into alignment as can be seen futher down the output, it is correct again at line 97.
    Here is lines 92-100

    Code:
    <><0.000000><14745.500000><-2076936724493001671600000000000000.000000><65><16896><1390592><159744><0><53248><994><6365>
    <><0.000000><12.400000><123.400002><0><66><5432><624><0><-503316272><-587202557><-1929379816>
    <><151117546906078104510000.000000><-202663520.000000><0.000000><1107296256><939524096><1879048213><234881026><-805306368><65142784><417136640><42795008>
    <><271536072765004599800000.000000><-107612720.000000><406691939335599541850000000000.000000><4325376><355991552><40894464><-217186304><13631488><254464><1629440><167168>
    <><14745.500000><-2076936724493001671600000000000000.000000><-0.003672><16896><1390592><159744><15928832><53248><994><6365><653>
    <hellothere><12.400000><123.400002><23.430000><66><5432><624><62222><-503316272><-587202557><-1929379816><2>
    <ellothere><-202663520.000000><0.000000><0.000000><939524096><1879048213><234881026><243><65142784><417136640><42795008><0>
    <llothere><-107612720.000000><406691939335599541850000000000.000000><0.000000><355991552><40894464><-217186304><0><254464><1629440><167168><0>
    <lothere><-2076936724493001671600000000000000.000000><-0.003672><0.000000><1390592><159744><15928832><0><994><6365><653><0>

  4. #4
    Fountain of knowledge.
    Join Date
    May 2006
    Posts
    794
    Actually I think I may be on the way to finding a solution

  5. #5
    Fountain of knowledge.
    Join Date
    May 2006
    Posts
    794
    Well I thuoght I was anyway, what I found is that the results change if I stick a char at the end of the structure as so
    Code:
    typedef struct {
    			char name[11];		
    			float stack;	
    			float dolstack;
    			float tempval;
    			float crap;
    			int	gamesplayed;
    			int tookpart;
    			int tookpart3;
    			int tookpart5;
    			int tookpart8;
    			int five;
    			int eight;
    			int three;
    			int unmatched;
    			int pfr;
    			int afr;
    			int atr;
    			int arr;
    			float win;
    			float win5;
    			float tempstack;
    			float crap2;
    			char a;
    		} PLYR;
    I found this changes the output so it is shifted by 5 characters not 1.
    As so:-

    Code:
    <hellothere><12.400000><123.400002><23.430000><66><5432><624><62222><-503316272><-587202557><-1929379816><2>
    <there><0.000000><0.000000><32.000000><1879048213><234881026><243><-805306368><417136640><42795008><0><0>
    <><0.000000><0.000000><0.000000><-217186304><0><13631488><254464><167168><0><0><0>
    <A迒蠛小翠><0.000000><0.000000><0.000000><0><53248><994><6365><0><0><0><0>
    <小翠><0.000000><0.000000><0.000000><-503316272><-587202557><-1929379816><2><0><0><0><0>
    <><0.000000><0.000000><-8589934592.000000><417136640><42795008><0><0><0><0><0><0>
    <
    But if I add another character it just stays the same, (same for 3 and 4 characters too), however it is a clue to what is going on. I think it something to do with how things are stored, but I can't find a solution (yet).

  6. #6
    Fountain of knowledge.
    Join Date
    May 2006
    Posts
    794
    OK, I am pretty sure this maybe compiler related. I am using the GCC compiler
    and there is something about this here
    http://www.delorie.com/djgpp/v2faq/faq22_11.html

    "The padding of struct members should be considered when you read or write struct contents from or to a disk file. In general, this should only be done if the file is read and written by the same program, because the exact layout of the struct members depends on some subtle aspects of code generation and the compiler switches used, and these may differ between programs, even if they were compiled by the same compiler on the same system. If you do need this method, be aware of the struct member padding and don't assume that the number of the file bytes that the structure uses is equal to the sum of the members' sizes, even if you instructed the compiler to pack structs: GCC still can add some padding after the last member. So always use sizeof struct foo to read and write a structure. "

  7. #7
    Fountain of knowledge.
    Join Date
    May 2006
    Posts
    794
    If you can crack this I will give you a coconut!!

  8. #8
    Frequently Quite Prolix dwks's Avatar
    Join Date
    Apr 2005
    Location
    Canada
    Posts
    8,057
    On my computer (Dev-C++ 4.9.9.2 with GCC 3.4.2 on Windows XP SP2) I get the output you were expecting, that is, the same line repeated over and over again:
    Code:
    <hellothere><12.400000><123.400002><23.430000><66><5432><624><62222><3536><994><6365><653>
    <hellothere><12.400000><123.400002><23.430000><66><5432><624><62222><3536><994><6365><653>
    <hellothere><12.400000><123.400002><23.430000><66><5432><624><62222><3536><994><6365><653>
    ...
    I'm using the code you posted in your first post. First I set readwrite to 0, then I ran it again with it set to 1.

    You are reading and writing the file with the same program under the same platform with the same compiler, right?

    The only other thing I can suggest is to open your files in binary mode (add a "b" to the end of your modes: "rb", "w+b" or "wb+"), which is how you should be opening them, since you're fread() and fwrite()ing to them.
    dwk

    Seek and ye shall find. quaere et invenies.

    "Simplicity does not precede complexity, but follows it." -- Alan Perlis
    "Testing can only prove the presence of bugs, not their absence." -- Edsger Dijkstra
    "The only real mistake is the one from which we learn nothing." -- John Powell


    Other boards: DaniWeb, TPS
    Unofficial Wiki FAQ: cpwiki.sf.net

    My website: http://dwks.theprogrammingsite.com/
    Projects: codeform, xuni, atlantis, nort, etc.

  9. #9
    Fountain of knowledge.
    Join Date
    May 2006
    Posts
    794
    Thanks dwks!!! That did the trick!! (putting the "b") in the open statement that is.
    I can't say I have ever used that before or understand the reason for its existance. I mean a file is a file, and I can choose to interpretate it which ever why I like, I don't really see why I should have to tell the compiler what it is as its "none of it's business" as far as I can see.

    But anyway thanks for the help because it is great that I can store the data this way rather than using fprintf and scanf, which means I avoid loads of pointless and time consuming formatting. I wil have about 100,000 structures to store and I need to be able to read them
    in quickly (in a matter of seconds), that might not be possible if there is a lot of formatting do to.

  10. #10
    Officially An Architect brewbuck's Avatar
    Join Date
    Mar 2007
    Location
    Portland, OR
    Posts
    7,396
    Quote Originally Posted by esbo View Post
    Thanks dwks!!! That did the trick!! (putting the "b") in the open statement that is.
    I can't say I have ever used that before or understand the reason for its existance. I mean a file is a file, and I can choose to interpretate it which ever why I like, I don't really see why I should have to tell the compiler what it is as its "none of it's business" as far as I can see.
    It's none of the compiler's business, but it IS the operating system's business. On many systems the "b" doesn't change the behavior at all. On Windows it makes a huge difference. If you want to blame something, blame the OS, not the language (it's not C's fault).

    The idea of "a file is a file, period," is a very UNIX-ish concept that doesn't really translate other places. Heck, on some operating systems like the derivatives of VMS, there are files that can't even be read byte-by-byte ("record oriented.")

  11. #11
    Fountain of knowledge.
    Join Date
    May 2006
    Posts
    794
    Quote Originally Posted by brewbuck View Post
    It's none of the compiler's business, but it IS the operating system's business. On many systems the "b" doesn't change the behavior at all. On Windows it makes a huge difference. If you want to blame something, blame the OS, not the language (it's not C's fault).

    The idea of "a file is a file, period," is a very UNIX-ish concept that doesn't really translate other places. Heck, on some operating systems like the derivatives of VMS, there are files that can't even be read byte-by-byte ("record oriented.")
    Yes most of my early C programming was on UNIX systems so I had never really came across the "b" switch before. I am not saying it is the languages fault, I mean it does have this option to 'cure' the (unnecessary, in my opinion) interference by the the OS.
    As far as I am concerned a file is just a sequence of bytes (or bits or integers etc..) and it is up to the application to determine what 'format' it is in.

    Incidently did it work for anyone without the "b" switch? (on a windows machine). I though I did manage this at one point after I had deleted some redundant variables by I never managed to do it again after I put them back in and took them out again. Anyway I am glad it works now,
    it means I can quicky save various 'databases' and reload them as I wish.

  12. #12
    Frequently Quite Prolix dwks's Avatar
    Join Date
    Apr 2005
    Location
    Canada
    Posts
    8,057
    Incidently did it work for anyone without the "b" switch? (on a windows machine). I though I did manage this at one point after I had deleted some redundant variables by I never managed to do it again after I put them back in and took them out again. Anyway I am glad it works now,
    it means I can quicky save various 'databases' and reload them as I wish.
    Yes, it did for me, since I took your original code. But on that same computer I've had problems before that were fixed by opening a file in binary mode, so perhaps it was a fluke. Who knows.
    dwk

    Seek and ye shall find. quaere et invenies.

    "Simplicity does not precede complexity, but follows it." -- Alan Perlis
    "Testing can only prove the presence of bugs, not their absence." -- Edsger Dijkstra
    "The only real mistake is the one from which we learn nothing." -- John Powell


    Other boards: DaniWeb, TPS
    Unofficial Wiki FAQ: cpwiki.sf.net

    My website: http://dwks.theprogrammingsite.com/
    Projects: codeform, xuni, atlantis, nort, etc.

  13. #13
    Fountain of knowledge.
    Join Date
    May 2006
    Posts
    794
    Well I seem to have got my main program working now, it reads in 10,000+structures, a 3 megabyte file in the blink of an eyelid! Which is good since it takes almost an hour to create them!
    I would imagine it would take a good deal longer it I had to use scanf for to read each structure member!
    I might modify it to see how long how mch longer that would take!

  14. #14
    Woof, woof! zacs7's Avatar
    Join Date
    Mar 2007
    Location
    Australia
    Posts
    3,459
    Please stop yelling!
    Okay!

    Now you can tidy up your code perhaps ?

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Weird Problem With Pointer
    By DarkDot in forum C++ Programming
    Replies: 3
    Last Post: 05-07-2007, 07:50 PM
  2. Weird problem on '02 3.4L V6 auto
    By VirtualAce in forum A Brief History of Cprogramming.com
    Replies: 8
    Last Post: 01-12-2006, 12:05 AM
  3. Really Weird itoa Problem
    By Grantyt3 in forum C++ Programming
    Replies: 8
    Last Post: 12-20-2005, 12:44 AM
  4. Replies: 6
    Last Post: 05-12-2005, 03:39 AM
  5. Weird class problem!
    By aker_y3k in forum C++ Programming
    Replies: 2
    Last Post: 09-25-2002, 06:12 AM