如何在C语言中将用户输入字符串中的浮点数/整数翻倍?

3

很抱歉,因为我对编程还比较新,我的代码中有些东西可能看起来像完全没有意义!我不确定我是否正确使用了atoi

我正在尝试创建一个程序,将用户输入的句子拆分成单词,并在用户输入数字时将数字加倍(浮点数/整数)。例如,我有3只猫会输出:

I
have
6
cats

我的程序现在能够分割句子,但我无法将整数加倍。有人能帮忙吗?

以下是代码:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

void main()
{
    char sentence[100];

    printf("Enter a sentence to split: ");
    scanf("%[^\n]s", sentence);
    char *pch;
    int y;

    y = atoi(sentence);
    printf("After splitting:\n", sentence);
    pch = strtok(sentence," ");
    while (pch != NULL) {
        printf("%s\n", pch);
        pch = strtok(NULL, " ");
    }
    system("PAUSE");
}

我的输出如下:

Enter a sentence to split: Hi, I have 7 cats.
After splitting:
Hi,
I
have
7
cats.
Press any key to continue . . .

你想要一个特定的解决方案还是通用的解决方案? - Sossenbinder
atoi()将字符串转换为整数。您在程序开头对整个句子调用它,而不是单个单词(标记)。您真的希望整个句子都是一个整数,还是只有其中的一个单词?将您的atoi()放在处理每个单词(标记)的循环内。另一件要考虑的事情:您如何知道标记是否为整数?请参见atoi手册。 - e0k
@Bluth,我建议您检查我的答案并说出这是否是您需要的或其他内容。 - Simply Me
一个整数严格来说是一串数字,还是+2-30x20这样的表示也可以呢? - chqrlie
@Bluth: 你提到了整数 integer,因此小数不应该可以。 - chqrlie
显示剩余3条评论
4个回答

1
这里有一个更简单的版本,可测试所有数字类型:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

int main(void) {
     char sentence[100];
     char *pch;

     printf("Enter a sentence to split: ");
     if (!fgets(sentence, sizeof sentence, stdin))
          return 1;

     printf("After splitting:\n");
     for (pch = strtok(sentence, " \n"); pch != NULL; pch = strtok(NULL, " \n")) {
         if (pch[strspn(pch, "0123456789")] == '\0') {
             printf("%d\n", atoi(pch) * 2);
         } else {
             printf("%s\n", pch);
         }
     }
     system("PAUSE");
     return 0;
}

如果您想解析浮点数,您可以使用以下代码:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <math.h>

int main(void) {
     char sentence[100];
     char *pch, *pend;
     double value;

     printf("Enter a sentence to split: ");
     if (!fgets(sentence, sizeof sentence, stdin))
          return 1;

     printf("After splitting:\n");
     for (pch = strtok(sentence, " \n"); pch != NULL; pch = strtok(NULL, " \n")) {
         value = strtod(pch, &pend);
         if (*pend == '\0' && isfinite(value)) {
             printf("%g\n", value * 2);
         } else {
             printf("%s\n", pch);
         }
     }
     system("PAUSE");
     return 0;
}

请注意测试isfinite()以避免将infnan识别为数字。

注意:isfinite是C99的一部分,不受VisualStudio 12支持,但更新的版本支持它。对于这个较旧的版本,请使用<float.h>中定义的_finite()


谢谢!我正在使用VS 12,但我不认为它支持 "isfinite()" 函数,因为我已经尝试添加了不同的库,但似乎无法让它正常工作。你知道有什么解决方法吗? - Bluth
isfinite() 是标准 C 的一部分。你是否包含了 <math.h> - chqrlie
是的,我已经包含了它。我在谷歌上搜索了一下,显然它不是在VS 12版本的"<math.h>"或"<cmath>"中的一部分。我会尝试在另一个版本上运行它,并确保它对我有效。非常感谢您的帮助! - Bluth
这是在VisualStudio 12.0中的一个错误。请参见https://dev59.com/Z2Uq5IYBdhLWcg3wV_Ai和https://connect.microsoft.com/VisualStudio/feedback/details/783412/isnan-and-isfinite-support-does-not-exist-in-math-h-or-cmath 。要进行特定修复,请使用<float.h>中定义的_finite(x)或升级您的VisualStudio版本到更高版本。 - chqrlie
@Bluth:你能否给你接受的答案点个赞? - chqrlie

0

对于分割部分,我建议使用这个版本,它更容易理解(假设你已经学会了 for 工作方式)。它执行相同的操作,但可以帮助您组织代码。

char *p;
int i;
    for(p = strtok(sentence, " "); p != NULL; p = strtok(NULL, " "))
    {
        int isNumber = 1;
        for(i = 0; i < strlen(p); i ++)
        {
            if(!isDigit(p[i])
            {
                isNumber = 0;
                break;
            }
        }
        if(isNumber == 1)
        {
            int number = atoi(pch);
            number *= 2;
            printf("%d\n", number);
        }
        else
        {
            printf("%s\n", p);
        }
    }

对于数字,我建议使用atoi函数。这里有一个很好的参考。

要解决你的问题,首先,你需要检查每个单词。例如:逐个单词检查,看看“单词”是否仅包含数字。如果它仅包含数字,则可以使用atoi将其转换为数字,乘以2并打印结果。

另一方面,如果你发现一个字符不是数字,那么你的单词中有字母或任何其他字符,因此它不是一个单词,所以你只需按原样打印。


使用for循环是个好主意。你应该使用isdigit((unsigned char)p[i]))——缺少了一个) - chqrlie
是的,但如果字符溢出,它将取模,如果您使用特殊字符。感谢提示,这是一个很好的观察。 - Simply Me
不,它不应该这样做,因为它被定义为所有unsigned char和值EOF。取模运算会在EOF\377(通常为iso-latin1中的ÿ)之间产生冲突。glibc使用一个384个条目的数组来处理有符号和无符号字符参数,但对于'\377'仍然是错误的,并且它没有屏蔽int参数,因此任何足够大的参数都将导致程序崩溃(我已经检查了1000000)。Darwin使用一种不太高效的方法,即进行显式测试:它认为0..127之外的所有值都没有属性。 - chqrlie

0

这里有一个工作示例,即使它不是非常精确。基本上,我们需要找出当前字符串是否为数字。在这种情况下,我只尝试获取当前字符串的第一个元素,并尝试确定它是否为数字。

当然,如果你想要真正确定,我们需要迭代字符串并检查每个字符是否为数字。

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

void main()
{
    char sentence[100];

    printf("Enter a sentence to split: ");
    scanf("%[^\n]s", sentence);
    char * pch;
    int y;
    y = atoi(sentence);
    printf("After splitting:\n", sentence);
    pch = strtok (sentence," ");
    while (pch != NULL)
    {
        if(isdigit(pch[0]))
        {
            int number = atoi(pch);
            number *=2;
            printf("%d\n",number);
            pch = strtok (NULL, " ");
            continue;
        }
        printf("%s\n",pch);
        pch = strtok (NULL, " ");
    }

    system("PAUSE");
}

@SimplyMe 的确如此。这取决于 OP 需要多么强大的答案。我编辑了我的帖子来考虑这一点。 - Sossenbinder
我怀疑你的代码能否捕捉到那个问题。你需要检查所有的东西。 - Simply Me
@SimplyMe:程序会如何崩溃?它只会忽略末尾的 a - chqrlie
@Sossenbinder:这应该可以工作,但是您可以删除初始的 atoi(sentence),最好将 unsigned char 传递给 isdigit(),使用 isdigit((unsigned char)pch[0]) - chqrlie
@chqrlie,是的,它会忽略它,但7a不是一个数字,所以你不应该使其加倍。这是很主观的。它主要取决于OP的需求。 - Simply Me
显示剩余3条评论

0

这里是另一个(更紧凑的)答案:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>

int is_numeric(char *s)
{
    int i = 0;
    while (s[i] != '\0') {
        if (!isdigit(s[i]))
            return 0;
        ++i;
    }
    return 1;
}

int main()
{
    char sentence[255];
    char *pch;

    printf("Enter a sentence to split: ");
    if (!fgets(sentence, sizeof(sentence), stdin)) {
        return 1;
    }
    sentence[strcspn(sentence, "\n\r")] = 0; /* Strip newline */

    pch = strtok(sentence, " ");
    while (pch != NULL) {
        if (atoi(pch)) {
            printf("%d\n", 2 * atoi(pch));
        } else {
            printf("%s\n", pch);
        }
        pch = strtok(NULL, " ");
    }
    return 0;
    /* system("PAUSE"); */
}

关键在于atoi将对非数字参数返回0。

有趣!但它不能处理 7a。您还可以删除 y 的定义,并使用 if (scanf("%99[^\n]", sentence) != 1) return 1; 保护缓冲区。 - chqrlie
另一个紧凑版本的想法,带有有效数字测试:char *p; if (strtol(pch, &p, 10) && !*p) - chqrlie

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接