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

这是我遇到的一个非常有趣的问题。 我做了很多关于堆栈溢出的搜索,发现其他人有类似的问题。 所以我相应地写了我的代码。 我最初有fscan()strcmp() ,但这完全轰炸了我。 所以其他post建议使用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语句

 #define MAX_WORD_LENGTH 25 

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) 。 这个快速修复的问题在于它将传递无效输入,即如果wordeject ,并且guessejection ,则比较将通过。

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

 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: "); // ... 

使用strlen ,而不是sizeof 。 此外,你不应该在这里使用strncmp ,如果你的猜测是单词的前缀,它将错误地报告匹配。 使用strcmp

正如其他人所说,使用strlen而不是sizeof 。 之所以发生这种情况,是C一个基本概念,它与Java不同。

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

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

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

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

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

更新:

您的代码很好,除了一个小细节。 fgets的文档指出它将保留尾随换行符char。

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

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

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

您的代码的一些问题/建议列表,太长,不适合评论:

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

一个常见的习语是

 do { if (something) break; } while(1) 
  • 你在每次迭代中分配一个缓冲区,但你永远不会free它。 这将为您提供大量内存泄漏,浪费的缓冲区以及代码无法访问
  • 你的strncmp方法只有在字符串具有相同的长度时才是正确的,所以你必须先测试它