Thread: fgets not truncating text

  1. #1
    Registered User
    Join Date
    Apr 2012
    Posts
    35

    fgets not truncating text

    Hello,

    My program actually works but has bugs in it and I don't know why the bugs are showing up.

    Background
    I am teaching myself how to program in C. I have been studying this for a while in my spare time and have written a program to test out what what I can remember from the skills I have learned. This isn't for anything other than my own self satisfaction and testing my skills thus far.

    I am programming in a Linux environment and am a beginner with gdb, linux, C and the GCC compiler. I cannot get gdb to get past any fgets functions I have in the program. It hangs every time it gets to fgets so gdb is pretty much useless to me in trying to figure this out. Even when I try to type something in and hit enter it doesn't work. I even push ENTER 500 times (dramatization but not far off) and that finally gets past it but then proceeds too far in to the program even using next function and I have tried to manually set the variable by using set x="Whatever" to no avail.

    Issue
    When running the program if you type in text longer than what fgets is expecting instead of dropping the excess text like I have seen it do before, the excess text is getting copied over to the next question and causing the next questions to be answered automatically by the excess text.

    Example
    What is the 1st employees first name:
    Correct Answer: Kammi
    Buggy Answer: Kammiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiii iiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiii iiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiii iiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiii i

    Result
    The correct answer is perfect. It will cause the next question to come up. The buggy answer will cause the unexpected result of the immediate question being answered with kammiiiiiiiiiiiiiii (19 characters because fgets is set to take in 20 characters including the NUL terminator '\0') however then it answers the next question which ends up as "What is Kammiiiiiiiiiiiiiii's last name? " as "iiiiiiiiiiiiiiiii" and continues this behavior until all of the iiiiiiii's have been used up.

    Attempts
    • I have tried to use fflush(stdout) after the question to no avail.
    • I have attempted to look at the length of the string and clear out the string if it is over what is expected. If I use a printf("Length of String: %d",strlen(storage)); it prints out the string length I was expecting.
    • I remove the new line that fgets inserts automatically and replace it with a 0 already (if it finds one), I have attempted to set it to a NUL terminator instead.


    Question
    I have no idea what is causing this issue and need some help telling me what's wrong and how to fix it. Can someone please look over the code and tell me what's wrong with it?

    Code
    CodePaste.NET - Working code for using structures, arrays and pointers all together. - Every line has been commented.

    GCC Compiling Command
    gcc -ggdb -std=c99 -Wall -Werror ptr-strct.c -lcrypt -lcs50 -lm -o ptr-strct

    Other Notes
    There may be other commands not recognized by some people such as -lcs50 and also questions as to why I am using other settings such as -std=c99. This is because I am going through the Harvard classes and am using the CS50 appliance provided by Harvard.

  2. #2
    TEIAM - problem solved
    Join Date
    Apr 2012
    Location
    Melbourne Australia
    Posts
    1,907
    The '\0' character is not being put at the end of the string.
    Fact - Beethoven wrote his first symphony in C

  3. #3
    Registered User
    Join Date
    Apr 2012
    Posts
    35
    It is automatically placed in there when I use fgets. I shouldn't need to add it. Is that not correct? I have actually also tried to update the removenew line to replace the \n with '\0' instead and that didn't fix it.

  4. #4
    TEIAM - problem solved
    Join Date
    Apr 2012
    Location
    Melbourne Australia
    Posts
    1,907
    Give your string an extra character and initialise this last character to '\0'
    Fact - Beethoven wrote his first symphony in C

  5. #5
    Registered User
    Join Date
    Apr 2012
    Posts
    35
    It doesn't work. Here is what I did.
    I updated the MAXNAME macro from 20 to 21.

    I changed the removenewline function from changing the '\n' to 0 to change it to '\0'. This will ensure that there will indeed be a NUL terminator in there. I have done this before.

    The result:
    What is the 1st employees first name? Kammiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiii iiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiii
    What is Kammiiiiiiiiiiiiiiii's last name? How old is Kammiiiiiiiiiiiiiiii iiiiiiiiiiiiiiiiiiii? What is Kammiiiiiiiiiiiiiiii iiiiiiiiiiiiiiiiiiii's hourly wage? $What is the date of hire for Kammiiiiiiiiiiiiiiii iiiiiiiiiiiiiiiiiiii (ie. 04-20-1975)? When was the last pay raise date for Kammiiiiiiiiiiiiiiii iiiiiiiiiiiiiiiiiiii (ie. 04-20-1975)? What is the home phone for Kammiiiiiiiiiiiiiiii iiiiiiiiiiiiiiiiiiii (ie. 555-555-5555)?

  6. #6
    TEIAM - problem solved
    Join Date
    Apr 2012
    Location
    Melbourne Australia
    Posts
    1,907
    Just update the declaration to MAXNAME + 1, not the value of MAXNAME
    Fact - Beethoven wrote his first symphony in C

  7. #7
    TEIAM - problem solved
    Join Date
    Apr 2012
    Location
    Melbourne Australia
    Posts
    1,907
    Code:
    char *storage; // Create a storage container to store the answer from the user in fgets.
    storage=malloc(sizeof(company)); // Allocate memory for the pointer just created with malloc
    
    ...
    
    
    printf(" employees first name? "); // End the question to the user and wait for input with fgets.
    fgets(storage->fname,MAXNAME,stdin); // Store the retreived information into the structure.
    storage=removenewline(storage->fname); // Remove the new line added by fgets so we can print on the same line.
    Last edited by Click_here; 12-18-2012 at 06:29 PM.
    Fact - Beethoven wrote his first symphony in C

  8. #8
    Registered User
    Join Date
    Apr 2012
    Posts
    35
    I have tried this is multiple places. In the struct I tried fname[MAXNAME+1]. This did not work. I tried in in the fgets function: fgets(storage,MAXNAME+1,stdin); and that didn't work.

    Now realize that I have this function that removes the newline that fgets automatically adds to the string. It looks for '/n' and replaces it with '/0'. This means that a NUL terminator is in the string. Now the code above will replace it with only 0 because I have already attempted to replace it with a '\0' and that didn't work. I guess the point I am trying to get to is that I have ensured that there is indeed a NUL terminator at the end of the string and that is not causing the issue.

    The issue even happens on the float's and integers. If you include 20.77777777777777777777777777777777777777777777777 7777777777777777777777777 it does the same thing. I accept it as a string and then convert it using the atoi and atof functions.

    Wayne

  9. #9
    Registered User
    Join Date
    Apr 2012
    Posts
    35
    Quote Originally Posted by Click_here View Post
    Code:
    char *storage; // Create a storage container to store the answer from the user in fgets.
    storage=malloc(sizeof(company)); // Allocate memory for the pointer just created with malloc
    
    ...
    
    
    printf(" employees first name? "); // End the question to the user and wait for input with fgets.
    fgets(storage->fname,MAXNAME,stdin); // Store the retreived information into the structure.
    storage=removenewline(storage->fname); // Remove the new line added by fgets so we can print on the same line.
    I used to have that in there but I received the following errors which is why I had to go to the strcpy function.

    ptr-strct.c:75:22: error: request for member 'fname' in something not a structure or union
    ptr-strct.c:76:38: error: request for member 'fname' in something not a structure or union

  10. #10
    TEIAM - problem solved
    Join Date
    Apr 2012
    Location
    Melbourne Australia
    Posts
    1,907
    Code:
    char *storage; // Create a storage container to store the answer from the user in fgets.
    
    //Should be
    
    company *storage; // Create a storage container to store the answer from the user in fgets.
    Fact - Beethoven wrote his first symphony in C

  11. #11
    Registered User
    Join Date
    Apr 2012
    Posts
    35
    Quote Originally Posted by Click_here View Post
    Code:
    char *storage; // Create a storage container to store the answer from the user in fgets.
    
    //Should be
    
    company *storage; // Create a storage container to store the answer from the user in fgets.
    When I do that I get the following errors:

    jharvard@appliance (~/Desktop/CS50/source code files): make ptr-strct
    gcc -ggdb -std=c99 -Wall -Werror ptr-strct.c -lcrypt -lcs50 -lm -o ptr-strct
    ptr-strct.c: In function 'storedata':
    ptr-strct.c:75:9: error: passing argument 1 of 'fgets' from incompatible pointer type [-Werror]
    /usr/include/stdio.h:626:14: note: expected 'char * restrict' but argument is of type 'struct company *'
    ptr-strct.c:76:9: error: passing argument 1 of 'removenewline' from incompatible pointer type [-Werror]
    ptr-strct.c:29:7: note: expected 'char *' but argument is of type 'struct company *'
    ptr-strct.c:76:16: error: assignment from incompatible pointer type [-Werror]
    ptr-strct.c:77:9: error: passing argument 2 of 'strcpy' from incompatible pointer type [-Werror]
    /usr/include/string.h:128:14: note: expected 'const char * restrict' but argument is of type 'struct company *'
    ptr-strct.c:81:9: error: passing argument 1 of 'strlen' from incompatible pointer type [-Werror]
    /usr/include/string.h:399:15: note: expected 'const char *' but argument is of type 'struct company *'
    ptr-strct.c:82:29: error: invalid operands to binary == (have 'company' and 'int')
    ptr-strct.c:87:9: error: passing argument 1 of 'fgets' from incompatible pointer type [-Werror]
    /usr/include/stdio.h:626:14: note: expected 'char * restrict' but argument is of type 'struct company *'
    ptr-strct.c:88:9: error: passing argument 1 of 'removenewline' from incompatible pointer type [-Werror]
    ptr-strct.c:29:7: note: expected 'char *' but argument is of type 'struct company *'
    ptr-strct.c:88:16: error: assignment from incompatible pointer type [-Werror]
    ptr-strct.c:89:9: error: passing argument 2 of 'strcpy' from incompatible pointer type [-Werror]
    /usr/include/string.h:128:14: note: expected 'const char * restrict' but argument is of type 'struct company *'
    ptr-strct.c:98:9: error: passing argument 1 of 'fgets' from incompatible pointer type [-Werror]
    /usr/include/stdio.h:626:14: note: expected 'char * restrict' but argument is of type 'struct company *'
    ptr-strct.c:99:9: error: passing argument 1 of 'atoi' from incompatible pointer type [-Werror]
    /usr/include/stdlib.h:148:12: note: expected 'const char *' but argument is of type 'struct company *'
    ptr-strct.c:103:9: error: passing argument 1 of 'strlen' from incompatible pointer type [-Werror]
    /usr/include/string.h:399:15: note: expected 'const char *' but argument is of type 'struct company *'
    ptr-strct.c:105:29: error: invalid operands to binary == (have 'company' and 'int')
    ptr-strct.c:110:9: error: passing argument 1 of 'fgets' from incompatible pointer type [-Werror]
    /usr/include/stdio.h:626:14: note: expected 'char * restrict' but argument is of type 'struct company *'
    ptr-strct.c:113:9: error: passing argument 1 of 'strlen' from incompatible pointer type [-Werror]
    /usr/include/string.h:399:15: note: expected 'const char *' but argument is of type 'struct company *'
    ptr-strct.c:118:13: error: passing argument 1 of 'removenewline' from incompatible pointer type [-Werror]
    ptr-strct.c:29:7: note: expected 'char *' but argument is of type 'struct company *'
    ptr-strct.c:118:20: error: assignment from incompatible pointer type [-Werror]
    ptr-strct.c:119:13: error: passing argument 1 of 'atof' from incompatible pointer type [-Werror]
    /usr/include/stdlib.h:145:15: note: expected 'const char *' but argument is of type 'struct company *'
    ptr-strct.c:124:9: error: passing argument 1 of 'fgets' from incompatible pointer type [-Werror]
    /usr/include/stdio.h:626:14: note: expected 'char * restrict' but argument is of type 'struct company *'
    ptr-strct.c:125:9: error: passing argument 1 of 'removenewline' from incompatible pointer type [-Werror]
    ptr-strct.c:29:7: note: expected 'char *' but argument is of type 'struct company *'
    ptr-strct.c:125:16: error: assignment from incompatible pointer type [-Werror]
    ptr-strct.c:126:9: error: passing argument 2 of 'strcpy' from incompatible pointer type [-Werror]
    /usr/include/string.h:128:14: note: expected 'const char * restrict' but argument is of type 'struct company *'
    ptr-strct.c:129:9: error: passing argument 1 of 'fgets' from incompatible pointer type [-Werror]
    /usr/include/stdio.h:626:14: note: expected 'char * restrict' but argument is of type 'struct company *'
    ptr-strct.c:130:9: error: passing argument 1 of 'removenewline' from incompatible pointer type [-Werror]
    ptr-strct.c:29:7: note: expected 'char *' but argument is of type 'struct company *'
    ptr-strct.c:130:16: error: assignment from incompatible pointer type [-Werror]
    ptr-strct.c:131:9: error: passing argument 2 of 'strcpy' from incompatible pointer type [-Werror]
    /usr/include/string.h:128:14: note: expected 'const char * restrict' but argument is of type 'struct company *'
    ptr-strct.c:134:9: error: passing argument 1 of 'fgets' from incompatible pointer type [-Werror]
    /usr/include/stdio.h:626:14: note: expected 'char * restrict' but argument is of type 'struct company *'
    ptr-strct.c:135:9: error: passing argument 1 of 'removenewline' from incompatible pointer type [-Werror]
    ptr-strct.c:29:7: note: expected 'char *' but argument is of type 'struct company *'
    ptr-strct.c:135:16: error: assignment from incompatible pointer type [-Werror]
    ptr-strct.c:136:9: error: passing argument 2 of 'strcpy' from incompatible pointer type [-Werror]
    /usr/include/string.h:128:14: note: expected 'const char * restrict' but argument is of type 'struct company *'
    cc1: all warnings being treated as errors
    make: *** [ptr-strct] Error 1

  12. #12
    TEIAM - problem solved
    Join Date
    Apr 2012
    Location
    Melbourne Australia
    Posts
    1,907
    You have a choice -

    Code:
    char *storage; // Create a storage container to store the answer from the user in fgets.
    storage=malloc(sizeof(MAXNAME)); // Allocate memory for the pointer just created with malloc
    
    // And have a string "storage" of size MAXNAME, or
    
    company *storage; // Create a storage container to store the answer from the user in fgets.
    storage=malloc(sizeof(company)); // Allocate memory for the pointer just created with malloc
    
    // And go through making sure that you are writing to the correct members in the structure.
    Fact - Beethoven wrote his first symphony in C

  13. #13
    Registered User
    Join Date
    Sep 2006
    Posts
    8,868
    fgets() does truncates input. Try to add a full row of text, and see for yourself.

    Code:
    #include <stdio.h>
    #include <string.h>
    
    #define SIZE 50
    
    int main(void) {
       char name[SIZE];
       char *pch;
       int len;
    
       fgets(name, sizeof(name), stdin);
       
       len=strlen(name);
       pch=&name[len-1];
       if(*pch=='\n')
          *pch='\0';
       printf("name: %s has %d chars in it\n",name,strlen(name));
    
       return 0;
    }

  14. #14
    Registered User
    Join Date
    Apr 2012
    Posts
    35
    I originally had the MAXNAME in my code for the storage container however I through that perhaps since I was sending the stuff to a struct I need to allocate enough memory to store everything in the struct so I changed it to company.

    I actually has char* storage=malloc((MAXNAME*2)+2) just like char* fullname.

    I will try changing it back right now and report back.

    Wayne

  15. #15
    Just kidding.... fnoyan's Avatar
    Join Date
    Jun 2003
    Location
    Still in the egg
    Posts
    275

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. FGETS from text to array
    By Oonej in forum C Programming
    Replies: 30
    Last Post: 07-10-2011, 01:46 AM
  2. Fgets() & Fputs() to combine text files?
    By d2rover in forum C Programming
    Replies: 5
    Last Post: 11-20-2010, 03:58 PM
  3. truncating front
    By jimmianlin in forum C Programming
    Replies: 2
    Last Post: 10-01-2009, 04:12 PM
  4. Truncating a char *
    By ajb268 in forum C++ Programming
    Replies: 3
    Last Post: 01-31-2005, 02:57 PM
  5. Truncating a double?
    By criticalerror in forum C++ Programming
    Replies: 13
    Last Post: 12-08-2003, 12:49 PM