-1

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?

  • 2
    You're mixing line-oriented input `fgets()` with character oriented input.(`getchar()`). They handle newlines differently, hence interactions like you see, that programmers often don't expect. The solution is to use one input approach or the other, on a given stream, and NEVER mix them (e.g. use `fgets()` for all input, and extract single characters from the input string if needed). – Peter Dec 23 '18 at 01:01
  • what did you mean that it *skips and jumps*? Have you tried to debut it? – Serge Dec 23 '18 at 01:35
  • Note: `j--;` does nothing, `j` is reset, `for (j = i; ...` each time the loop is encountered. – David C. Rankin Dec 23 '18 at 07:03

2 Answers2

3

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
H.S.
  • 9,215
  • 2
  • 10
  • 25
  • Extraordinarily good, thorough, instructive response! – paulsm4 Dec 23 '18 at 06:29
  • @H.S. is it possible that when I write even more code that consists of fgets() after this that this part is somehow getting messed up by other fgets() – Sketchup Galaxy Dec 25 '18 at 20:21
  • @SketchupGalaxy No, it will not. Just make sure to read about `fgets()` thoroughly and handle the scenario where the input could be bigger than buffer size passed to `fgets()`. You may need this - [how-to-clear-input-buffer-in-c](https://stackoverflow.com/questions/7898215/how-to-clear-input-buffer-in-c). – H.S. Dec 26 '18 at 02:57
1

Try changing r = getchar(); with scanf("%c\n", &r);.

Also, your loop has some bugs or inconsistencies:

  1. You're assigning to str[j] the value of a pointer. Should be assigning to str[j] the value of str[j+1].
  2. The end of the inner loop should be len-1 then.
  3. j-- has no effect at all.
  4. You should end your string with \0 after you're done, otherwise you'll print garbage (in my case it was a bunch of \ns).

Putting everything together:

    for (i = 0; i < len; i++) {
        if (str[i] == r) {
            for (j = i; j < len-1; j++) {
                str[j] = str[j+1];
            }
            len--;
        }
    }
    str[len] = '\0';
    printf("Sentence after removal: %s\n", str);

If you want to remove the \n at the end of the string after you read it, you can do

    str[len] = '\0';
    len--;

before the loop.

Yuri J
  • 119
  • 7