C编程:只从fgets打印int

看到这个main

 int main(void) { int i; int ch; char str[512]; fgets(str, sizeof str, stdin); for (i = 0; i <= (strlen(str)); i++) { if (str[i] != '\0' && str[i] != '\n') { int num = atoi(&str[i]); printf("%d\n", num); } } return 0; } 

我希望得到用户的数字,并获得所有数字,没有任何spacestabs

例如:

输入1 2 3 。 但在这种情况下这输出:

 1 2 2 3 3 

那么为什么我两次收到23

这是我将如何做到这一点:

 char line[256]; if (fgets(line, sizeof line, stdin) != NULL) { const char *ptr = line; while (*ptr != '\0') { char *eptr = NULL; const long value = strtol(ptr, &eptr, 10); if (eptr != ptr) printf("%ld\n", value); else break; ptr = eptr; } } 

这使用strtol()因此它也将处理负数; 如果这不正确,您当然可以添加检查以过滤掉它们。 我认为这比使用strtok()更好。

因为你也传递了以空格开头的字符串的位置。 他们得到的第一个数字分别是23两次。 这就是返回的内容。

 for (i = 0; i <= (strlen(str)); i++) { if (str[i] != '\0' && !isspace(str[i]) ) { int num = atoi(&str[i]); printf("%d\n", num); } } 

打印:

 1 2 3 

出于标记化的目的,您可以使用strtok并将其转换为数字strtol等。这些可以比atol/atoi更好地控制错误情况。

当它到达输入中的空格字符时,它将使用" 2 3" (导致2)调用atoi() ,然后调用" 3" (导致3),这将创建意外的数字。

atoi()的参考 :

该函数首先丢弃尽可能多的空白字符(如在isspace中),直到找到第一个非空白字符。 […]

这意味着如果您将该函数作为输入“2”,它将返回2。


改变这个:

 if (str[i] != '\0' && str[i] != '\n') 

对此:

 if (str[i] != ' ' && str[i] != '\0' && str[i] != '\n') 

你会得到:

 1 2 3 

以下是有关调试此代码的提示:在输出中,您有2次和3次,但不是1次。

换句话说,你获得两次空格后的数字。 1之前没有空格。

这应该会让你觉得那里的空间有点怪异。

实际上,即使str[i]是一个空格,你也会输入if语句的主体!

通过添加条件来检查当前字符是否不是空格,要输入if语句的boby,实际上会跳过这些空格。

始终考虑error handling是个好主意。 如果用户错误地按空格和制表符,该怎么办? 首先删除空格和制表符(如果存在):

 char *c = string; while ((*c == ' ') || (*c == '\t')) ++c; 

然后使用atoi()

strtok的解决方案也不是那么难:

 #include  #include  #include  int main(void) { char s[128]; fgets(s, sizeof s, stdin); const char *delim = " \t\n"; char *p = strtok(s, delim); while(p) { int val = strtol(p, NULL, 10); printf("%d\n", val); p = strtok(NULL, delim); } return 0; } 

虽然请记住它有点不确定因为它使用隐藏状态(不适合multithreading程序),当然它会修改输入字符串,所以它不能是常量(但为什么你会这样做)。

您可以使用ctype.h提供的isdigitisalpha()函数(基于您的使用)。 以下是使用isdigit函数的代码片段:

 for (i = 0; i <= (strlen(str)); i++) { if (isdigit(str[i])) { int num = atoi(&str[i]); if(i && str[i-1]=='-') num *= -1; printf("%d\n", num); i += ( num==0 ) ? 1 : (int)log10(abs(num))+1; } } 

看到它在这里工作。
点击这里查看isdigitisalpha()函数。

关于你的问题:

那么为什么我两次收到2和3?

请参阅cplusplus.com上提供的以下说明,其中解释了atoi()函数。

该函数首先丢弃尽可能多的空白字符(如在isspace中),直到找到第一个非空白字符。 然后,从该字符开始,采用可选的初始加号或减号,后跟尽可能多的10位数字,并将它们解释为数值。