C语言中的字符串问题

3

当我输入一个以“sum”开头的字符串,然后计算接下来的数字时,问题就出现了。

输入:

sum 10 20 

输出:

30

但是我的代码有问题,输出结果是33(计算过程是11+22=33)。 我认为第二个 while 循环有问题,但是我不知道该如何修改。

我需要一位高手的帮助。

#include<stdio.h>

int main(){

    char a[100];

    while (gets(a))
    {
        if (a[0] == 's'&&a[1] == 'u'&&a[2] == 'm')
        {
            int i;
            int sum = 0;

            for (i = 2; a[i]; i++){
                if (a[i] == ' '){
                    i++;
                    int num = 0;
                    while (1){
                        num += num * 10 + (a[i] - '0');
                        i++;
                        if (a[i] == ' ' || a[i]=='\0') break;
                    }
                    sum += num;
                    i--;
                }
            }

            printf("%d", sum);
        }

    }
    return 0;
}

为什么不使用 scanf 呢? - NobodyNada
2
scanf是一种不安全且糟糕的解析文本的方法,但是它比你这里使用的方法要好。换句话说,你的方法固有的不可扩展性,在即使最微不足道的情况下也会失控。 - Bartek Banachewicz
3个回答

2
num += num * 10 + (a[i] - '0');

应该是

num = num * 10 + (a[i] - '0');

1
双重计数发生在这里:

num += num * 10 + (a[i] - '0');

例如,对于数字 '12',你需要解析出 1,然后将 12 加上 1 得到 13。改为:
num = num * 10 + (a[i] - '0');

0
首先,你应该使用fgetsgets已经被弃用了。其次,我相信通过将它变成一次性程序,你可以将代码减少到目前大小的一半,但你仍然可以轻松地启动它:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

int main(int argc, char *argv[])
{
  if(argc != 3){
    printf("ERROR: Must input two integers!\n");
    return -1;
  }

  int first = strtol(argv[1], NULL, 0);
  int second = strtol(argv[2], NULL, 0);

  int sum = first + second;

  printf("%d\n", sum);

  return 0;
}

在这段代码中,我使用了argcargv。这意味着在命令行上,您可以键入sum 10 20,它将把10和20作为参数传递进去。我使用的第二个东西是strtol,它将一个字符串(10和20最初是字符串)转换为long int
另外,你应该使用GDB。它是GNU调试器。去查一下吧。

Mior:这个解决方案使用 int first = strtol(...) 静默地将 long 转换为 int,可能会导致数据丢失。 - chux - Reinstate Monica
在2014年,我的gcc运行于64位平台上,使用32位的int和64位的long,而嵌入式处理器则使用16位的int和32位的long。"在这个时候所有的'int'都是'long' int"可能是你的经验,但这并不是一般实践,也不符合C11规范,该规范要求'int'至少16位,而long至少32位。 - chux - Reinstate Monica
然而,long intsigned int 已经过时了,如果你真的想确保类型匹配,请将 firstsecondsum 设为 int32_t 并包含头文件 #include <stdio.h> - Gophyr
long 绝对不过时。如果有疑问,建议发布一个 SO 问题“long 是否是过时的术语?”。使用固定宽度整数类型确实有其用处,但同样存在转换问题:int32_t first = strtol(...) 可能会丢失数据。注意:C 指定固定宽度整数类型在 <stdint.h> 中。 - chux - Reinstate Monica
long 没有被指定为32位。这可能是您的经验,但这不是C规范。C规范意味着它必须至少为32位(“...它们的实现定义值的绝对值应等于或大于所示值,并具有相同的符号。... long int类型对象的最小值LONG_MIN -2147483647 ... long int类型对象的最大值LONG_MAX +2147483647 ...” C11 §5.2.4.2.1 1)。正如我之前提到的,在我的PC上,gcc是64位的。 - chux - Reinstate Monica
显示剩余2条评论

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