Search code examples
cstringstdinfgets

fgets() keeps getting skipped before entering loop


Been trying to remove a character but the call to fgets gets skipped/jumped over. On different computers it runs like it should but for some reason, it skips and basically jumps to the end of the program. Any ideas?


Solution

  • Several problems in your code but I do not see any reason of fgets() skipped or jumped over. The getchar() function reads the next character from stdin. Generally when we give input to the getchar() function, we enter the character and press ENTER key. This left the \n character in input stream which can be consumed by next input function called. But in your case you are not calling any other input function after getchar().
    [Try calling getchar() above fgets() and give input as - enter a character followed by ENTER key. You will see the fgets() is skipped because it consumes the leftover \n character from input stream stdin.]

    Problem 1:
    Look at this statement:

    str[j] = str + 1;
    

    Since, the str is a char array, str[j] represents a character at location j and str + 1 is pointer. So, this assignment is incompatible because you are trying to assign a char * type to a char. It should be:

    str[j] = str[j + 1];
    

    Problem 2:
    Your code is having a logical problem. It is unable to handle the scenario where the character to be removed occurs consecutively in the input string. Test your code for input like "Hello World" [character l is occurring consecutively]. Your program output will be [after fixing problem 1]:

    Enter a sentence: 
    Hello World
    This is the sentence: Hello World
    
    Enter character to remove: 
    l
    Sentence after removal: Helo Word        <==== character l not removed
    

    Your program is unable to handle this particular scenario because once it removes a character, in the next iteration it starts with next character.

    Problem 3:
    The strlen() return type is size_t and you are using char type to receive its return value. Instead, you should use size_t type.
    The getchar() return type is int [because it returns the special value EOF when the end of the input stream is reached]. You are using char type variable to receive getchar() return value.

    One more point (it is not a problem but you should be aware of it and take the precautionary measures):
    From fgets() [emphasis mine]:

    Reads at most count - 1 characters from the given file stream and stores them in the character array pointed to by str. Parsing stops if end-of-file occurs or a newline character is found, in which case str will contain that newline character. If no errors occur, writes a null character at the position immediately after the last character written to str.

    So, it is possible that your input buffer passed to fgets() can have new line character ('\n') in it. For e.g., if you give input Hello World followed by ENTER key than the input buffer str will have "Hello World\n" in it. In your case this will not cause any problem but few extra iteration of loop. You can remove the \n from str buffer like this:

    fgets(str, 100, stdin);
    str[strcspn(str, "\n")] = 0; // This will remove the trailing newline character from input buffer
    

    Also, you should check the fgets() return. In case of failure, fgets() returns NULL.

    Putting these altogether, you can do:

    #include <stdio.h>
    #include <string.h>
    
    int main() {
        char str[100];
        size_t i, j, len;
        int r;
    
        printf("Enter a sentence: \n");
        if (fgets(str, 100, stdin) == NULL) {
            fprintf (stderr, ("fgets failed"));
            return -1;
        }
    
        str[strcspn(str, "\n")] = 0;
        printf("This is the sentence: %s\n", str);
    
        printf("Enter character to remove: \n");
        r = getchar();
    
        /*If getchar returns EOF, no need to go through character removal logic*/
        if (r != EOF) {
            len = strlen(str);
    
            i = 0;
            while (str[i] != '\0') {
                if (str[i] == (char)r) {
                    for (j = i; j < len; j++) {
                        str[j] = str[j+1];
                    }
                    len--;
                }
                else
                    i++;
            }
        }
    
        printf("Sentence after removal: %s\n", str);
        return 0;
    }
    

    Output:

    # ./a.out
    Enter a sentence: 
    Hello World
    This is the sentence: Hello World
    Enter character to remove: 
    l
    Sentence after removal: Heo Word
    
    # ./a.out
    Enter a sentence: 
    zzzzz
    This is the sentence: zzzzz
    Enter character to remove: 
    z
    Sentence after removal: 
    
    # ./a.out
    Enter a sentence: 
    aazz
    This is the sentence: aazz
    Enter character to remove: 
    a
    Sentence after removal: zz