繁体   English   中英

C编程:只从fgets打印int

[英]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;
}

我想从用户那里得到数字,并获得所有数字,没有任何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,实际上是跳过空格。

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

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提供的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的数字,并将它们解释为数值。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM