为什么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)
。 这个快速修复的问题在于它将传递无效输入,即如果word
是eject
,并且guess
是ejection
,则比较将通过。
最后,没有理由在循环的每次迭代中为新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。
要解决此问题,请在fgets
和strncmp
部分之间添加以下代码:
if ( guess[guessLen-1] == '\n' ) { guess[guessLen-1] = '\0'; }
这样,尾随的换行符(如果有的话)会被删除,而你不再是一个。
您的代码的一些问题/建议列表,太长,不适合评论:
- 你的函数返回一个奇怪的
char
。 我没有看到逻辑,更重要的是,你实际上永远不会返回一个值。 不要那样做,它会给你带来麻烦 - 查看C中的其他控制结构,特别是不要做
exit
事情。 首先,在C中exit
是一个函数,它执行它所说的,它退出程序。 然后有一个break
语句来留下循环。
一个常见的习语是
do { if (something) break; } while(1)
- 你在每次迭代中分配一个缓冲区,但你永远不会
free
它。 这将为您提供大量内存泄漏,浪费的缓冲区以及代码无法访问 - 你的
strncmp
方法只有在字符串具有相同的长度时才是正确的,所以你必须先测试它