Thread: Errors with struct and I/O

  1. #16
    Registered User
    Join Date
    Aug 2005
    Location
    Austria
    Posts
    1,990
    so it's from the menu functions.
    a simple solution would be to change the scanf formatstrings in all the menu functions to
    Code:
    scanf("%d ", &op1);
    see the space after the %d this will consume the '\n'
    Kurt

  2. #17
    Registered User
    Join Date
    Apr 2012
    Posts
    159
    Sorry...don't get it

    I don't see any space after %d in my menu function

    Wich function are you talking about??

    regards

  3. #18
    Registered User
    Join Date
    Aug 2005
    Location
    Austria
    Posts
    1,990
    I meant that you should put this extra space there.
    Code:
    void menu_ad()
    {
    	int op;
    	printf("1 - Inserir perguntas na BD \n");
    	printf("2 - Ver perguntas da BD \n");
    	// scanf("%d", &op); // here you leave a \n in the input buffer 
                        // change to
    	scanf("%d ", &op);
    	switch (op)
    	{
    	case 1:
    		ad_perguntas();
    		break;
    	case 2:
    		ver_perguntas();
    	default:
    		printf("Escolha inválida \n");
    	}
    }
    Guess you will have problems with the other menu functions as well.
    That extra space shouldn't make any damage
    Kurt

  4. #19
    Registered User
    Join Date
    Apr 2012
    Posts
    159
    Hi

    already did it but now i have to input twice to go to the questio...see

    1 - Inserir perguntas na BD
    2 - Ver perguntas da BD
    1
    1
    Quantos registos quer criar? tmp2='1
    '
    But now he reads the variable...but why two inputs??

    Code:
    menu_ad()
    {
    	int op;
    	printf("1 - Inserir perguntas na BD \n");
    	printf("2 - Ver perguntas da BD \n");
    	scanf("%d ", &op);
    	switch (op)
    	{
    	case 1:
    		ad_perguntas();
    		break;
    	case 2:
    		ver_perguntas();
    	default:
    		printf("Escolha inválida \n");
    	}
    }

  5. #20
    Registered User
    Join Date
    Aug 2005
    Location
    Austria
    Posts
    1,990
    guess that extra space wasn't a good idea.
    that one should work
    Code:
    void menu_ad()
    {
        int op;
        printf("1 - Inserir perguntas na BD \n");
        printf("2 - Ver perguntas da BD \n");
        scanf("%d", &op);
        getchar(); // this will read the '\n'
        switch (op)
        {
        case 1:
            ad_perguntas();
            break;
        case 2:
            ver_perguntas();
        default:
            printf("Escolha inválida \n");
        }
    }
    Kurt

  6. #21
    Registered User
    Join Date
    Apr 2012
    Posts
    159
    Hi

    Thanks for your help, the getchar() resolves the situation but if i add one record it's ok, with 2 records i have this fatal error..

    This is the program running:

    Bem vindo
    1 - Inserir perguntas na BD
    2 - Ver perguntas da BD
    1
    Quantos registos quer criar? 2
    tmp2='2
    '
    Introduza ID para a pergunta:
    1
    Introduza a pergunta:
    dgsdfg
    Opção 1 :
    gsdhdfh
    Opção 2 :
    hsdfhdfh
    Opção 3 :
    hsdhsdf
    Opção 4 :
    etweytwr
    Introduza o número da resposta correta:
    2
    Introduza ID para a pergunta:
    2
    Introduza a pergunta:
    fgjghjh
    Opção 1 :
    vcxbb
    Opção 2 :
    hjhgj
    Opção 3 :
    eteytr
    Opção 4 :
    ryrtrtu
    Introduza o número da resposta correta:
    1

    after that answer i get this




    *** glibc detected *** /home/gil/workspace/Trabalho Final/Debug/TrabalhoFinal: double free or corruption (top): 0x00000000016ba010 ***
    ======= Backtrace: =========
    /lib/x86_64-linux-gnu/libc.so.6(+0x7a6e6)[0x7f61e1db46e6]
    /lib/x86_64-linux-gnu/libc.so.6(cfree+0x6c)[0x7f61e1db89cc]
    /lib/x86_64-linux-gnu/libc.so.6(fclose+0x155)[0x7f61e1da4365]
    /home/gil/workspace/Trabalho Final/Debug/TrabalhoFinal[0x400d96]
    /home/gil/workspace/Trabalho Final/Debug/TrabalhoFinal[0x40106b]
    /home/gil/workspace/Trabalho Final/Debug/TrabalhoFinal[0x401170]
    /home/gil/workspace/Trabalho Final/Debug/TrabalhoFinal[0x400f1b]
    /home/gil/workspace/Trabalho Final/Debug/TrabalhoFinal[0x4011f7]
    /lib/x86_64-linux-gnu/libc.so.6(__libc_start_main+0xed)[0x7f61e1d5b30d]
    /home/gil/workspace/Trabalho Final/Debug/TrabalhoFinal[0x4008b9]
    ======= Memory map: ========
    00400000-00402000 r-xp 00000000 07:00 506279 /home/gil/workspace/Trabalho Final/Debug/TrabalhoFinal
    00601000-00602000 r--p 00001000 07:00 506279 /home/gil/workspace/Trabalho Final/Debug/TrabalhoFinal
    00602000-00603000 rw-p 00002000 07:00 506279 /home/gil/workspace/Trabalho Final/Debug/TrabalhoFinal
    016ba000-016db000 rw-p 00000000 00:00 0 [heap]
    7f61dc000000-7f61dc021000 rw-p 00000000 00:00 0
    7f61dc021000-7f61e0000000 ---p 00000000 00:00 0
    7f61e1b24000-7f61e1b39000 r-xp 00000000 07:00 2117 /lib/x86_64-linux-gnu/libgcc_s.so.1
    7f61e1b39000-7f61e1d38000 ---p 00015000 07:00 2117 /lib/x86_64-linux-gnu/libgcc_s.so.1
    7f61e1d38000-7f61e1d39000 r--p 00014000 07:00 2117 /lib/x86_64-linux-gnu/libgcc_s.so.1
    7f61e1d39000-7f61e1d3a000 rw-p 00015000 07:00 2117 /lib/x86_64-linux-gnu/libgcc_s.so.1
    7f61e1d3a000-7f61e1ed1000 r-xp 00000000 07:00 650243 /lib/x86_64-linux-gnu/libc-2.13.so
    7f61e1ed1000-7f61e20d0000 ---p 00197000 07:00 650243 /lib/x86_64-linux-gnu/libc-2.13.so
    7f61e20d0000-7f61e20d4000 r--p 00196000 07:00 650243 /lib/x86_64-linux-gnu/libc-2.13.so
    7f61e20d4000-7f61e20d5000 rw-p 0019a000 07:00 650243 /lib/x86_64-linux-gnu/libc-2.13.so
    7f61e20d5000-7f61e20db000 rw-p 00000000 00:00 0
    7f61e20db000-7f61e20fc000 r-xp 00000000 07:00 2926 /lib/x86_64-linux-gnu/ld-2.13.so
    7f61e22e3000-7f61e22e6000 rw-p 00000000 00:00 0
    7f61e22f7000-7f61e22fb000 rw-p 00000000 00:00 0
    7f61e22fb000-7f61e22fc000 r--p 00020000 07:00 2926 /lib/x86_64-linux-gnu/ld-2.13.so
    7f61e22fc000-7f61e22fe000 rw-p 00021000 07:00 2926 /lib/x86_64-linux-gnu/ld-2.13.so
    7fff02bed000-7fff02c0e000 rw-p 00000000 00:00 0 [stack]
    7fff02c72000-7fff02c73000 r-xp 00000000 00:00 0 [vdso]
    ffffffffff600000-ffffffffff601000 r-xp 00000000 00:00 0 [vsyscall]



    what's wrong now?

    Thanks for your help, best regards

  7. #22
    Registered User
    Join Date
    Nov 2010
    Location
    Long Beach, CA
    Posts
    5,909
    That error is usually from one of two things:
    1. Calling free on a pointer that does not contain an address returned by malloc (e.g. uninitialized pointer, static array, etc).
    2. Calling free twice on the same pointer.

    You most likely have case 1. You do allocate memory, but:
    Code:
            struct perg* per;
            per= malloc(sizeof(*per));
            fread(&per[0], sizeof(struct perg), 100, data);
            free(per);
    You malloc only enough space for one perg struct, then you read in 100. This goes off of the end of your array and may damage the internal pointers malloc uses to keep track of memory. Try
    Code:
    malloc(100 * sizeof(*per));
    Also, you need to check the return value of malloc before using the memory. If per == NULL, you need to print an error and exit. Lastly, in that same function (ver_perguntas), you need to exit the function immediately if you can't open data.txt. If you don't, you run the risk of a seg fault from trying to read from a file that isn't open.

  8. #23
    Registered User
    Join Date
    Aug 2005
    Location
    Austria
    Posts
    1,990
    Code:
               for (n = 0; n < quantos; n++) {
                   fprintf(data, "%d - %s %s|%s|%s|%s|Resposta correta: %d \n",per[n].id, per[n].ques, per[n].op1, per[n].op2, per[n].op3, per[n].op4, per[n].res);
                   fclose(data);
                   //menu_admin();
               }
    You're closing the file inside of the for loop -> the second record is written into a closed FILE *.
    Kurt
    EDIT: this happens because of badly formatted ( indented ) code
    Last edited by ZuK; 04-23-2012 at 05:45 PM.

  9. #24
    Registered User
    Join Date
    Nov 2010
    Location
    Long Beach, CA
    Posts
    5,909
    @Kurt:
    Good call. I just looked for usage of free, didn't bother looking at the call stack in the error output.

  10. #25
    Registered User
    Join Date
    Apr 2012
    Posts
    159
    Hi

    It works now, finally, mny thanks to all.

    The only thing i don't understand is the way the text is recorded in my file. It comes like this.

    1 - Clube ganhador
    benfica
    |braga
    |faro
    |afife
    |Resposta correta: 1

    and by the code

    Code:
     fprintf(data, "%d - %s %s|%s|%s|%s|Resposta correta: %d \n",per[n].id, per[n].ques, per[n].op1, per[n].op2, per[n].op3, per[n].op4, per[n].res);
    it should come in just one line right??

    And i have several warnings...don't knwo why

    Description Resource Path Location Type
    conflicting types for ‘jogo’ [enabled by default] Trabalho Final.c /Trabalho Final/src line 145 C/C++ Problem
    conflicting types for ‘menu_ad’ [enabled by default] Trabalho Final.c /Trabalho Final/src line 178 C/C++ Problem
    control reaches end of non-void function [-Wreturn-type] Trabalho Final.c /Trabalho Final/src line 226 C/C++ Problem
    control reaches end of non-void function [-Wreturn-type] Trabalho Final.c /Trabalho Final/src line 237 C/C++ Problem
    implicit declaration of function ‘adm’ [-Wimplicit-function-declaration] Trabalho Final.c /Trabalho Final/src line 131 C/C++ Problem
    implicit declaration of function ‘jogo’ [-Wimplicit-function-declaration] Trabalho Final.c /Trabalho Final/src line 135 C/C++ Problem
    implicit declaration of function ‘menu_ad’ [-Wimplicit-function-declaration] Trabalho Final.c /Trabalho Final/src line 99 C/C++ Problem
    return type defaults to ‘int’ [-Wreturn-type] Trabalho Final.c /Trabalho Final/src line 196 C/C++ Problem



    any help?

    best regards and thanks you all.

  11. #26
    Registered User
    Join Date
    Dec 2007
    Posts
    2,675
    fgets() leaves the newline character in the received input. You must remove it.

    http://faq.cprogramming.com/cgi-bin/...&id=1043284385

  12. #27
    Registered User
    Join Date
    Apr 2012
    Posts
    159
    Quote Originally Posted by rags_to_riches View Post
    fgets() leaves the newline character in the received input. You must remove it.

    Don't understand this...
    I must use only one fgets() for all the inputs?


    regards

  13. #28
    Registered User
    Join Date
    Nov 2010
    Location
    Long Beach, CA
    Posts
    5,909
    fgets is used to read a line of input. When you type a line of input, you press the enter key, which inserts a new line (the '\n' character) at the end of your input. fgets puts that in the buffer, so if you type
    foo<enter>
    the string that fgets reads looks like
    "foo\n"
    Thus, when you use that string in the printf statement where the %s is, you are putting a new line in your output. That's why you get each string on it's own line. The link rags_to_riches posted gave an example of how to remove that new line (the if (p = strchr...) lines). You must do that after every call to fgets.

  14. #29
    Registered User
    Join Date
    Apr 2012
    Posts
    159
    Hi

    Thanks for your help.
    I made those change but now nothing is writed in my txt file....

    Code:
    void ad_perguntas()
    {
    	struct perg per[100];
    	int quantos;
    	char tmp2[200];
    	char tmp[200];
    	char tmp1[200];
    	char *p;
    	printf("Quantos registos quer criar? ");
    	fgets(tmp2, sizeof tmp2, stdin);
    	quantos=strtol(tmp2, NULL, 10);
    	int n;
    	    for (n = 0; n < quantos; n++)
    	    {
    	    	printf("Introduza ID para a pergunta: \n");
    	    	fgets(tmp, sizeof tmp, stdin);
    	    	per[n].id = strtol(tmp, NULL, 10);
    	    	printf("Introduza a pergunta: \n");
    	    	fgets(per[n].ques, 200, stdin);
    	    	 if ((p = strchr(per[n].ques, '\n')) != NULL)
    	    		    	 *p = '\0';
    	    	printf("Opção 1 : \n");
    	    	fgets(per[n].op1, 14, stdin);
    	    	 if ((p = strchr(per[n].op1, '\n')) != NULL)
    	    		    	 *p = '\0';
    	    	printf("Opção 2 :\n");
    	    	fgets(per[n].op2, 14, stdin);
    	    	 if ((p = strchr(per[n].op2, '\n')) != NULL)
    	    		    	 *p = '\0';
    	    	printf("Opção 3 : \n");
    	    	fgets(per[n].op3, 14, stdin);
    	    	 if ((p = strchr(per[n].op3, '\n')) != NULL)
    	    		    	 *p = '\0';
    	    	printf("Opção 4 : \n");
    	    	fgets(per[n].op4, 14, stdin);
    	    	 if ((p = strchr(per[n].op4, '\n')) != NULL)
    	    		    	 *p = '\0';
    	    	printf("Introduza o número da resposta correta: \n");
    	    	fgets(tmp1, sizeof tmp1, stdin);
    	    	per[n].res = strtol(tmp1, NULL, 10);
    	    	 if ((p = strchr(per[n].res, '\n')) != NULL)
    	    		    	 *p = '\0';
    
    
    }
    	    FILE* data;
    	       if ( (data = fopen("data.txt", "a")) == NULL )
    	       {
    	           printf("Erro \n");
    	       }
    	       for (n = 0; n < quantos; n++) {
    	           fprintf(data, "%d - %s %s|%s|%s|%s|Resposta correta: %d \n",per[n].id, per[n].ques, per[n].op1, per[n].op2, per[n].op3, per[n].op4, per[n].res);
    	           adm();
    	       }
    	      fclose(data);
    	   }
    And why nothing appears from my txt file when i use this fucntion??

    Code:
    void ver_perguntas()
    {
        {
    char c;
            FILE* data;
            if ((data = fopen("data.txt", "rb")) == NULL)
            {
                printf("Erro ao abrir ficheiro\n");
            }
            struct perg* per;
            per= malloc(100 * sizeof(*per));
            fread(per[0].ques, sizeof(struct perg), 100, data);
            free(per);
            fclose(data);
            printf("Quer voltar ao menu anterior? \n");
            scanf("%c", &c);
            if (c=='s'||c=='S')
            {
                menu_ad();
            }
        }
    }
    
    It was working...now no.
    
    :(
    Last edited by Gil Carvalho; 04-24-2012 at 10:33 AM.

  15. #30
    Registered User
    Join Date
    Nov 2010
    Location
    Long Beach, CA
    Posts
    5,909
    Taking your code from post #15, and making the changes in post #20 and #29, here are all the warnings I get when I compile your code:
    Code:
    $ make foo
    gcc -Wall -g -std=c99  -lm -lpthread -lcurses -lefence  foo.c   -o foo
    foo.c: In function ‘ad_perguntas’:
    foo.c:84: warning: passing argument 1 of ‘strchr’ makes pointer from integer without a cast
    /usr/include/string.h:233: note: expected ‘const char *’ but argument is of type ‘int’
    foo.c:96: warning: implicit declaration of function ‘adm’
    foo.c: In function ‘ver_perguntas’:
    foo.c:118: warning: implicit declaration of function ‘menu_ad’
    foo.c: In function ‘menu_principal’:
    foo.c:157: warning: implicit declaration of function ‘jogo’
    foo.c: At top level:
    foo.c:167: warning: conflicting types for ‘jogo’
    foo.c:157: note: previous implicit declaration of ‘jogo’ was here
    foo.c:202: warning: conflicting types for ‘menu_ad’
    foo.c:118: note: previous implicit declaration of ‘menu_ad’ was here
    foo.c:223: warning: return type defaults to ‘int’
    foo.c: In function ‘adm’:
    foo.c:252: warning: control reaches end of non-void function
    The line numbers might not match up exactly with your code, but should be close.

    All the "implicit declaration" and "conflicting types" errors are because you call a function before you define it, and you don't prototype it. C reads from top down, so when it sees the call to jogo(), it doesn't know how many and what type of parameters it takes, and what it returns. When C doesn't know that, it assumes a function returns an int. Then, later, when you actually define it as void jogo(), it says "well, jogo used to return an int, now you're telling me it returns nothing", hence the conflict. Put a line like this just below the #include statements:
    Code:
    void jogo(void);  // the first 'void' means returns nothing, the second 'void' means it takes exactly zero parameters
    The "control reaches end of non-void funciton" is because you declare adm() without a return type. Again, C assumes it returns int, but you don't have a return statement in the funciton, so it complains. It seems you don't intend for it to return anything, so declare it "void adm()".

    The other error is because you pass the wrong thing to strchr after calling fgets. Remember, strchr find a char ins a string. You must pass it a string (or char array) like tmp, not an integer like per[n].res. It should look like this:
    Code:
    fgets(tmp, sizeof(tmp), stdin);
    // no need to remove the newline here, since strtol will stop when it reaches it.  You only really need it for reading in strings.
    per[n].res = strtol(tmp, NULL, 10);
    Note, you don't need tmp, tmp1 and tmp2. You can reuse the same tmp variable since you call strtol on it to get a number right away, then you're done with it's contents.

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Replies: 11
    Last Post: 03-06-2011, 09:12 PM
  2. struct holding data inside a linked list struct
    By icestorm in forum C Programming
    Replies: 2
    Last Post: 10-06-2009, 12:49 PM
  3. Making a (atom) class in a (struct) class makes big errors!
    By Yarin in forum Windows Programming
    Replies: 4
    Last Post: 09-11-2007, 07:18 PM
  4. Script errors - bool unrecognized and struct issues
    By ulillillia in forum Windows Programming
    Replies: 10
    Last Post: 12-18-2006, 04:44 AM
  5. Struct errors...
    By Cale in forum C Programming
    Replies: 2
    Last Post: 12-12-2002, 11:49 PM