[英]C programming: print only int from fgets
看到这个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;
}
我想从用户那里得到数字,并获得所有数字,没有任何spaces
或tabs
。
例如:
输入1 2 3
。 但在这种情况下这输出:
1
2
2
3
3
那么为什么我两次收到2
和3
?
我是这样做的:
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()
方法更好。
因为你也传递了以空格开头的字符串的位置。 他们得到的第一个数字分别是2
和3
两次。 这就是返回的内容。
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,实际上是跳过空格。
始终考虑错误处理是个好主意。 如果用户错误地按空格和制表符,该怎么办? 首先删除空格和制表符(如果存在):
char *c = string;
while ((*c == ' ') || (*c == '\t'))
++c;
然后使用atoi()
。
strtok
的解决方案也不是那么难:
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
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;
}
虽然请记住它有点不确定因为它使用隐藏状态(不适合多线程程序),当然它会修改输入字符串,所以它不能是常量(但为什么你会这样做)。
您可以使用ctype.h
提供的isdigit
或isalpha()
函数(基于您的使用)。 以下是使用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;
}
}
看到它在这里工作。
点击这里查看isdigit
和isalpha()
函数。
关于你的问题:
那么为什么我两次收到2和3?
请参阅cplusplus.com上提供的以下说明,其中解释了atoi()
函数。
该函数首先丢弃尽可能多的空白字符(如在isspace中),直到找到第一个非空白字符。 然后,从该字符开始,采用可选的初始加号或减号,后跟尽可能多的基数为10的数字,并将它们解释为数值。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.