【问题标题】:Issue with fgets() inside of a do-while loop in CC中do-while循环内的fgets()问题
【发布时间】:2017-12-06 20:38:17
【问题描述】:

你好。我创建的用于确定输入字符串是否为回文的代码存在问题(如果以错误的方向阅读,单词是相同的)。实际代码本身按预期工作,但是当我尝试在整个代码上放置一个循环时,它开始表现得很奇怪。

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>

#define STRING_MAX 100

int isPalindrome();
char* removeNonAlpha();
char* strLowerCase();

int main()
{
    int x = 0;
    char inputString[STRING_MAX];
    char cont='y';

    do
    {
        printf("Hello. Please enter a word or sentence: ");
        fgets(inputString, STRING_MAX, stdin);

        printf("You entered: %s\n", inputString);

        //Remove all non alphabetical symbols from the string
        removeNonAlpha(inputString);
        printf("First we have to remove everything non-alphabetical: %s\n", inputString);

        //Make sure all the alphabetical symbols are lower case
        strLowerCase(inputString);
        printf("Then we have to make everything lower-case: %s\n", inputString);

        //After that, check if the string is a palindrome
        x = isPalindrome(inputString);

        if(x)
        {
            printf("The string you entered is a palindrome! :D\n");
        }
        else
        {
            printf("The string you entered is not a palindrome... :|\n");
        }
        printf("Would you like to enter another word or sentence? (y/n): ");
        cont = getchar();

        inputString[strlen(inputString)-1] = '\0';

    } while (cont == 'y');

    return 0;
}

int isPalindrome(char inputString[])
{
    int l = 0, r = strlen(inputString) - 1;

    if (l == r)
        return 1;

    while (r > l)
    {
        if (inputString[l++] != inputString[r--])
            return 0;
    }
    return 1;
}

char* removeNonAlpha(char inputString[])
{
    int i, j;

    for(i=0,j=0; i<strlen(inputString); i++,j++)
    {
        if (isalpha(inputString[i]))
            inputString[j] = inputString[i];
        else
            j--;
    }
    inputString[j] = '\0';

    return inputString;

}

char* strLowerCase(char inputString[])
{
    int i;

    for(i=0; i<strlen(inputString); i++)
        inputString[i] = tolower(inputString[i]);


    return inputString;
}

所以我期望的是代码再次运行并要求输入另一个字符串,但事实并非如此。我对此进行了一些阅读,看起来正在发生的事情是换行符 (\n) 仍在输入缓冲区中,并且 fgets 被跳过。我尝试在 fgets 之后使用 getchar() 来消耗最终的换行符,但它并没有解决我的问题。这是我得到的输出:

关于如何解决这个问题的任何想法?我是编程新手,我很想听听如何总体上改进我的代码,尽管我现在主要关心的是解决这个循环问题。

编辑: string.h 中唯一允许我使用的函数是 strlen()。

【问题讨论】:

  • 附带问题:for(i=0,j=0; i&lt;strlen(inputString); i++,j++) { if (isalpha(inputString[i])) inputString[j] = ... 是对strlen(inputString) 的多次调用的低效代码。简单使用i&lt;strlen(inputString) --> inputString[i]
  • 首先检查fgets是否成功。该函数的返回值是有原因的。此外,fgets 使用换行符,将其添加到字符串读取的末尾,当它成功时,如果所有输入都通过fgets,则后续getchar 是没有保证的。
  • @chux 感谢您的反馈!我对 for 循环不是很熟悉,这到底是做什么的?因为我认为 for 循环需要某种形式的条件,例如 while i 小于 inputString 的长度。
  • @WhozCraig 对不起,如果我听起来很笨,但是我将如何检查 fgets 是否成功?如果没有成功,这意味着什么?
  • @user3121023 这会从根本上改变什么?因为我使用了cont = getchar();,所以如果用户输入'y',代码就会循环。抱歉,如果我的问题看起来很愚蠢,我真的很想了解我在做什么。

标签: c loops fgets


【解决方案1】:

换行符留在缓冲区中的位置是在循环底部的getchar 调用之后。它只读取一个字符,因此换行符(以及您可能输入的任何额外字符)仍然存在。因此,当在下一次迭代中调用 fgets 时,它只会读取换行符。

您需要通过重复调用getchar 来清除循环底部的输入缓冲区,直到看到换行符:

cont = getchar();

int nextchar;
do {
    nextchar = getchar();
} while (nextchar != '\n' && nextchar != EOF);

【讨论】:

  • 非常感谢!这行得通。我只是想知道,dowhile 循环中的 getchar() 是否真的自动使用换行符,它是如何工作的?另外,EOF 代表什么?
  • @MemErkanEktiren 它不会自动使用换行符,它一次只读取一个字符。因此,如果您按下“ABC [ENTER]”。第一次调用getchar 返回'A',下一次调用'B',下一次调用'C',下一次调用'\n'EOF 是一个常数,表示已到达流的末尾,原因是 getchar 返回 int
  • 您可能会发现fread 更适合这种“阅读并测试角色”的场景。 char c; while (fread(&amp;c, 1, 1, file) &amp;&amp; c != '\n');;初学者也似乎更难出错。或者你可以使用scanf作为你的循环:scanf("%*[^\n]"); getchar(); ...事实上,整行可以被扫描,在同一个调用中获得用户输入:int answer = 0; fscanf("%*[Yy]%n%*[^\n]", &amp;answer); getchar();...跨度>
  • 别介意我...我只是提供更具表现力的替代方案。我不同意这个解决方案;提供cont 被声明为int(即像nextchar),这是一个很好的答案。我只是认为最好将其他替代品放在同一个地方。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-06-19
  • 1970-01-01
相关资源
最近更新 更多