c - 在进入循环之前 fgets() 不断被跳过

标签 c string stdin fgets

一直在尝试删除一个字符,但调用 fgets被跳过/跳过。在不同的计算机上,它按应有的方式运行,但由于某种原因,它会跳过并基本上跳到程序的末尾。有任何想法吗?

最佳答案

您的代码中有几个问题,但我没有看到 fgets() 跳过或跳过的任何原因。 getchar() 函数从 stdin 读取下一个字符。通常,当我们向 getchar() 函数输入内容时,我们输入字符并按 ENTER 键。这在输入流中留下了 \n 字符,可供下一个调用的输入函数使用。但在您的情况下,您在 getchar() 之后没有调用任何其他输入函数。
[尝试在 fgets() 之上调用 getchar() 并提供输入 - 输入一个字符,然后按 ENTER 键。您将看到 fgets() 被跳过,因为它消耗了输入流 stdin 中剩余的 \n 字符。]

问题1:
看一下这个声明:

str[j] = str + 1;

由于 str 是一个 char 数组,因此 str[j] 表示位置 j 处的字符str + 1 是指针。因此,此分配是不兼容的,因为您尝试将 char * 类型分配给 char。应该是:

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

问题2:
你的代码有逻辑问题。它无法处理要删除的字符在输入字符串中连续出现的情况。测试您的代码是否有“Hello World”之类的输入[字符l连续出现]。您的程序输出将是[解决问题 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

您的程序无法处理这种特定情况,因为一旦删除一个字符,在下一次迭代中它将从下一个字符开始。

问题3:
strlen() 返回类型为 size_t,并且您使用 char 类型接收其返回值。相反,您应该使用 size_t 类型。
getchar() 返回类型为 int [因为当到达输入流末尾时它返回特殊值 EOF] 。您正在使用 char 类型变量来接收 getchar() 返回值。

还有一点(这不是问题,但您应该意识到这一点并采取预防措施):
来自 fgets() [强调我的]:

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.

因此,传递给 fgets() 的输入缓冲区中可能包含换行符 ('\n')。例如,如果您输入 Hello World 后跟 ENTER 键,则输入缓冲区 str 将具有 "Hello World\n" 在其中。在你的情况下,这不会导致任何问题,但循环的额外迭代很少。您可以从 str 缓冲区中删除 \n,如下所示:

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

此外,您应该检查 fgets() 返回。如果失败,fgets() 返回 NULL

把这些放在一起,你可以这样做:

#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;
}

输出:

# ./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

关于c - 在进入循环之前 fgets() 不断被跳过,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/53900369/

相关文章:

string - 以Scala方式从同一行读取多个输入

string - Go 语言 : A way to tokenize a string

python - 使用 NumPy 快速进行 token 到索引的转换

vector - 如何从所有可能的流中读取具有任意分隔符和可选限制的泛型向量?

将整数值转换为位并将其存储到字符数组中?

C如何计算没有浮点精度的百分比(perthousands)

c - 为什么这是返回指针的偏移量? "smashing the stack"

c - 独立的 C 模块通过控制模块下的 stdin stdout 协同工作

ruby - Ruby 中 STDIN 的最佳实践?

将未知类型的数据复制到 C 中的数组中