为什么fgets()和strncmp()在这个C代码中无法进行字符串比较?

时间:2012-07-31 19:28:22

标签: c string fgets c-strings strncmp

这是我遇到的一个非常有趣的问题。我做了很多关于堆栈溢出的搜索,发现其他人遇到了类似的问题。所以我相应地写了我的代码。我最初有fscan()strcmp(),但这完全轰炸了我。因此,其他帖子建议使用fgets()strncmp()并使用长度来比较它们。

我尝试通过打印出两个字符串的大小来调试我正在做的事情。我想,也许他们有/n漂浮在那里或者其他东西搞乱了(另一篇文章谈到了这一点,但我认为这不会发生在这里)。因此,如果大小相同,strncmp()的限制应该相同。对?只是为了确保他们被认为是正确的比较。现在,我知道如果字符串相同,则返回0,否则返回strncmp()的否定字符串。但它不起作用。

以下是我得到的输出:

perk
repk
Enter your guess: perk
Word size: 8 and Guess size: 8
Your guess is wrong
Enter your guess: 

这是我的代码:

void guess(char *word, char *jumbleWord)
{
        size_t wordLen = strlen(word);
        size_t guessLen; 
        printf("word is: %s\n",word);
        printf("jumble is: %s\n", jumbleWord);


        char *guess = malloc(sizeof(char) * (MAX_WORD_LENGTH + 1));
        do
        {
            printf("Enter your guess: ");
            fgets(guess, MAX_WORD_LENGTH, stdin);
            printf("\nword: -%s- and guess: -%s-", word, guess); 
            guessLen = strlen(guess);
            //int size1 = strlen(word);
            //int size2 = strlen(guess); 

            //printf("Word size: %d and Guess size: %d\n",size1,size2);


            if(strncmp(guess,word,wordLen) == 0)
            {
                printf("Your guess is correct\n"); 
                break; 
            }

            }while(1);
    }

我从下面的建议中更新了它。特别是在学习char *作为指针之间的区别并将某些内容称为字符串之后。但是,它仍然给我同样的错误。

请注意MAX_WORD_LENGTH是我的程序顶部使用的定义语句

#define MAX_WORD_LENGTH 25

4 个答案:

答案 0 :(得分:4)

使用strlen,而不是sizeof。此外,您不应在此处使用strncmp,如果您的猜测是该字词的前缀,则会错误地报告匹配。使用strcmp

答案 1 :(得分:2)

sizeof(guess)返回char * 的大小而不是字符串guess的长度。您的问题是您使用sizeof来管理字符串长度。 C有一个字符串长度函数:strlen

sizeof用于确定数据类型和数组的大小。 sizeof仅适用于一个特定情况下的字符串 - 我不会在这里进行 - 但即使这样,也总是使用strlen来处理字符串长度。

您需要决定您允许的字数。这是你游戏的一个属性,即游戏中的单词永远不会超过11个字符。

所以:

// define this somewhere, a header, or near top of your file
#define MAX_WORD_LENGTH 11

// ...

size_t wordlen = strlen(word);
size_t guessLen;

// MAX_WORD_LENGTH + 1, 1 more for the null-terminator:
char *guess = malloc(sizeof(char) * (MAX_WORD_LENGTH + 1));

printf("Enter your guess: ");
fgets(guess, MAX_WORD_LENGTH, stdin);

guessLen = strlen(guess);

另请查看fgets的文档,并注意输入中保留换行符 ,因此如果要比较这两个单词,则需要考虑该字符。一个快速解决方法是仅比较word的长度, guess的长度,因此:if( strncmp(guess, word, wordLen) == 0)。此快速解决方案的问题在于它会传递无效输入,即如果wordejectguessejection,则比较将通过。

最后,没有理由在循环的每次迭代中为新的guess分配内存,只需使用已经分配的字符串。您可以将功能设置更改为:

char guess(char *word, char *jumbledWord)
{
    int exit;

    size_t wordLen = strlen(word);
    size_t guessLen; 

    char *guess = malloc(sizeof(char) * (MAX_WORD_LENGTH + 1));

    do
    {
        printf("Enter your guess: ");
        // ...

答案 2 :(得分:2)

正如其他人所说,使用strlen而不是sizeof。发生这种情况的原因是,C的基本概念与Java不同。

Java不允许您访问pointersC不仅有指针,而且它们是语言设计的基础。如果你不理解并在C中正确使用指针,那么事情就没有意义了,你会遇到很多麻烦。

因此,在这种情况下,sizeof返回char *指针的大小,通常是4或8个字节。你想要的是指针“在另一端”的数据结构的长度。这就是strlen封装的内容。

如果您没有strlen,则需要取消引用指针,然后遍历字符串,直到找到标记结尾的空字节。

i = 1;
while(*guess++) { i++ }

之后,i将保留字符串的长度。

<强>更新

您的代码很好,除了一个小细节。 docs for fgets注意它将保留尾随换行符。

要解决此问题,请在fgetsstrncmp部分之间添加以下代码:

if ( guess[guessLen-1] == '\n' ) {
    guess[guessLen-1] = '\0'; 
}

这样,尾随的换行符(如果有的话)会被删除,而你不再是一个。

答案 3 :(得分:1)

您的代码的一些问题/建议列表,太长而无法填写评论:

  • 你的函数返回一个奇怪的char。我没看到 逻辑,更重要的是,你实际上永远不会返回一个值。不要这样做,它会给你带来麻烦
  • 查看C中的其他控件结构,特别是不要执行exit事情。首先,C中的exit是一个函数,它执行它所说的,它退出程序。然后有一个break语句留下循环。

常见的习语是

do {

   if (something) break;
} while(1)
  • 你在每次迭代中分配一个缓冲区,但你永远不会free它。这会给你带来大量的内存泄漏,浪费和代码无法访问的缓冲区
  • 您的strncmp方法只有正确如果字符串长度相同,那么您必须先测试