在scanf之后,fgets不起作用

#include <stdio.h> #include <string.h> #include <ctype.h> void delspace(char *str); int main() { int i, loops; char s1[101], s2[101]; scanf("%d", &loops); while (loops--) { fgets(s1, 101, stdin); fgets(s2, 101, stdin); s1[strlen(s1)] = '\0'; s2[strlen(s2)] = '\0'; if (s1[0] == '\n' && s2[0] == '\n') { printf("YES\n"); continue; } delspace(s1); delspace(s2); for (i = 0; s1[i] != '\0'; i++) s1[i] = tolower(s1[i]); for (i = 0; s2[i] != '\0'; i++) s2[i] = tolower(s2[i]); if (strcmp(s1, s2) == 0) { printf("YES\n"); } else { printf("NO\n"); } } return 0; } void delspace(char* str) { int i = 0; int j = 0; char sTmp[strlen(str)]; while (str[i++] != '\0') { if (str[i] != ' ') { sTmp[j++] = str[i]; } } sTmp[j] = '\0'; strcpy(str, sTmp); } 

进入“循环”后,“s1”被自动分配一个空行。 这是怎么发生的? 我确定我的键盘工作正常。

scanf()完全读取您要求的内容,在fgets()将读取该行的缓冲区的末尾保留下列\n 。 要么做一些消耗新行,或者(我的首选解决scheme) fgets() ,然后sscanf()从该string。

scanf会在input缓冲区中留下空白,包括换行符。 要使用fgets读取下一行,您需要手动删除当前行的其余部分:

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

Vayn,

Geekoaur已经很好的回答了你的问题,我只是用你的代码指出另一个“问题”。

s1[strlen(s1)] = '\0'; 如果s1已经正确空终止,则在执行之前是空操作。

但是,如果s1没有正确的空终止在此行执行(而你是不幸的),它会导致:

  • 一个POSIX(* nix)系统上的SIGSEGV 。
  • Windows上的GPF 。

这是因为strlen basicalyfind现有的空终止符的索引并返回它! 这是strlen的一个有效的,未经优化的实现:

 int strlen(char *string) { int i = 0; while(string[i] != '\0') { ++i; } return i; } 

所以…如果你真的担心string不被空终止,那么你会做一些事情:

  • string[sizeof(string)]='\0';本地自动string(编译器“知道”string的大小);
  • string[SIZE_OF_STRING] ,其中SIZE_OF_STRING (最常见)是#define的d常量,或者是专门用于存储dynamic分配string的当前大小(而非长度)的variables。

如果你是真的,真的,真的很担心string不被空终止(就像你正在处理“脏”的库方法(例如Tuxedo的ATMI),你也“清除”你的“返回string”,然后通过到疑似图书馆的方法有:

  • 之前: memset(string, NULL, SIZE_OF_STRING);
  • invoke: DirtyFunction(/*out*/string) ;
  • after: string[SIZE_OF_STRING]='\0'

SIG11是一个完整的biatch,因为(除非你用信号处理器 “挂钩”它们,否则会导致unix硬性终止你的程序,所以你不能logging任何东西(事后),以帮助找出特别是考虑到在许多情况下,引发SIG11的代码行没有位于string的实际原因附近,从而失去了它的空终止符。

这对你有意义吗?

队友的欢呼声。 基思。

PS:警告: strncpy不会allways nullterminate …你可能意味着strlcpy 。 我以艰难的方式了解到这一点…当6000万美元的计费运行崩溃。


编辑:

仅供参考:这里是strlen的“安全”(未优化)版本,我将称之为strnlen (我认为这应该在stdlib中strnlen )。

 // retuns the length of the string (capped at size-1) int strnlen(char *string, int size) { int i = 0; while( i<size && string[i]!='\0' ) { ++i; } return i; } 

我知道这是非常古老的。 我新来c,想检查我的方法,它使用getchar

 #include <stdio.h> int main() { printf("Please enter your name\n"); char string[10]; scanf("%s", string); printf("Hello %s\n", string); //getchar(); # un commenting this line, fgets perfectly works!! printf("Please enter your name again\n"); fgets ( string, 10, stdin ); printf("Hello again %s", string); getchar(); } 

只是把scanf("%d\n",&loops);

而不是scanf("%d",&loops);