【问题标题】:How to store multiple integers in one variable, so I can get their total later [closed]如何将多个整数存储在一个变量中,以便稍后获得它们的总数[关闭]
【发布时间】:2018-08-30 07:22:24
【问题描述】:

我希望将输入的数字存储在某个地方,以便以后可以得到他们的总数,有人可以帮忙吗?

#include<stdio.h>
#include<conio.h>

main() {
    int range;
    int num;
    int i;
    int total = 0;

    printf("how many numbers will you put?\n");
    scanf("%d", &range);

    for(i=0;i<range;i++) {
        printf("please enter the number\n");
        scanf("%d", &num); 
    }
    printf("%d", total);

    return 0;
}

【问题讨论】:

  • 你只需要计算总权利,为什么不在输入的时候做呢
  • 您可以尝试在处理输入时计算总数
  • 注意:除了未能检查返回 scanf 的返回 的新 C 用户传统上在日出时拍摄 - 您还将受益于避免 Undefined Behavior 同时...例如只需if (scanf ("%d", &amp;num) == 1) total += num;,那么当你离开循环:) 时,你已经有了总数(你还应该在那里添加一个else 条件来处理任何错误(比如输入一个杂散字符)删除stdin 中未读的无关字符,以防止您的代码从那时起像“土拨鼠日”一样工作......)
  • 您可以使用 array,但正如 zenwraight 和 Zendy 所说,您最好即时计算总和
  • 只需添加:for(i=0;i&lt;range;i++) { printf("please enter the number\n"); scanf("%d", &amp;num); total += num; }

标签: c arrays loops


【解决方案1】:

除了您收到的其他建议外,您仍然必须处理删除任何导致scanf 失败的字符。为什么?当 scanf 发生 matchinginput 失败时,所有从 stdin 的读取都会停止并且不再读取字符(导致问题的字符只是等待在您下次致电scanf 时再次咬您。

为解决问题,您有责任对剩余的任何字符负责(您只能通过检查来自scanf 的返回来确定。如果匹配输入 失败,然后您可以使用简单的帮助功能来读取和丢弃所有字符,直到您的下一个 '\n'EOF 以先发生者为准,例如

void empty_stdin (void)
{
    int c = getchar();

    while (c != '\n' && c != EOF)
        c = getchar();
}

然后,只要您遇到匹配或输入失败(以及将控制权传递到另一个需要输入的区域时,只需将其合并到您的代码中 - 只是为了确保输入缓冲区是干净的。

将这些部分放在一起,您可以执行类似于以下的操作:

#include <stdio.h>
// #include <conio.h>  /* don't use conio.h -- it is DOS only */

void empty_stdin (void)
{
    int c = getchar();

    while (c != '\n' && c != EOF)
        c = getchar();
}

int main (void) {
    int range,
        num,
        i,
        total = 0;

    printf ("how many numbers will you enter: ");
    if (scanf ("%d", &range) != 1) {
        fputs ("error: invalid input - range.\n", stderr);
        return 1;
    }

    for (i = 0; i < range; i++) {
        for (;;) {  /* loop continually until you get the input you need */
            int rtn;
            printf ("\n  enter number[%2d]: ", i + 1);
            rtn = scanf("%d", &num);
            if (rtn == EOF) {   /* handle user EOF */
                fputs ("user canceled input.\n", stderr);
                return 1;
            }
            else if (rtn == 0) {    /* handle matching or input failure */
                fprintf (stderr, "error: invalid input, number[%d]\n", i + 1);
                empty_stdin ();
            }
            else        /* good conversion, break read loop */
                break;
        }
        total += num;   /* add num to total */
    }
    printf ("\nTotal: %d\n", total);

    return 0;
}

使用/输出示例

在输入中引发故意匹配失败:

$ ./bin/scanftotal
how many numbers will you enter: 4

  enter number[ 1]: 10

  enter number[ 2]: 20

  enter number[ 3]: foo
error: invalid input, number[3]

  enter number[ 3]: 30

  enter number[ 4]: 40

Total: 100

查看一下,如果您还有其他问题,请告诉我。 (并避免我在对您的问题的评论中提到的命运......)

【讨论】:

  • 你能把scanf("%*[^\n] "); 简化成empty_stdin() 吗?
  • 嗯,你可以,但你必须有一个足够大的缓冲区来容纳输入缓冲区中所有可能不需要的字符。 (如果一只猫踩在键盘上,那可能是几千)。使用getchar() 消除了所有缓冲区约束。但可以肯定的是,它可以工作。
  • 转换说明符中的* 禁止赋值,因此不需要缓冲区。 (是的,我确实编译并运行了!)
  • 呃,对了——来晚了,眼睛累了。使用赋值抑制运算符它会起作用,但是您会看到调用 variadic 输入函数或简单地调用字符函数(这最终是 scanf 将在场景)。 Linux 上的 IO 缓冲区一次将 8192 个字符加载到输入缓冲区中,使用 getchar 只需迭代内存中的字符,因此速度很快(Windows 为相同目的提供了 500 个字符的缓冲区)您可以通过输出BUFSIZ 常量。
【解决方案2】:

您的尝试非常接近。正如 David C. Rankin 所说,您真正做错的只是没有检查 scanf() 的返回值。

#include <stdio.h>

int main(int argc, char **argv)
{
    int range, num, i;
    int total = 0;
    int scanf_result = 0;

    setbuf(stdout, NULL);

    printf("How many numbers will you enter?\n");
    scanf_result = scanf("%d", &range);
    if((scanf_result != 1) || (range < 1))
    {
        printf("Invalid number");
        return 1;
    }

    for(i=0; i<range; i++) {
        printf("Please enter a number: \n");
        scanf_result = scanf("%d", &num);
        if(scanf_result != 1)
        {
            printf("Invalid number");
            return 1;
        } else
        {
            total = total + num;
        }
    }
    printf("Total is: %d", total);

    return 0;
}

【讨论】:

    【解决方案3】:

    其他评论者说得对,在一般情况下,您可能应该在阅读数字时只计算总和。遵循其他答案建议,例如清除标准输入,并可能为用户提供一种在出现错误时重试输入的方法。

    但是,也要小心未定义的行为。例如,用有符号整数计算总和可能会导致接近INT_MAXINT_MIN 的未定义行为。您可能应该在求和之前检查这些边界的距离是否低于当前添加的数字 (顺便请看Detecting integral overflow with scanf

    或者,您可以将您的数字放入一个数组中,并受益于整数加法可交换以尽可能取消溢出这一事实。这是一种可能的方法(经过测试,但可能仍然存在错误):

    #include <stdio.h>
    #include <limits.h>
    
    /* arbitrary limit */
    #define MAX_RANGE 32
    
    /* numbers being read */
    int numbers[MAX_RANGE];
    
    /* non-zero if number was already added in sum */
    int added[MAX_RANGE];
    
    int main()
    {
        int scan;
        int range;
        int num;
        int i;
        int sum;
        int overflow;
        int changed;
    
        printf("INT_MAX is %d\n", INT_MAX);
        printf("How many numbers will you put? (0-%d): ", MAX_RANGE-1);
        fflush(stdout);
        scan = scanf("%d", &range);
        if (scan != 1) {
            perror("Cannot read range: ");
            return -1;
        }
    
        if (!(0 <= range && range <= MAX_RANGE)) {
            fprintf(stderr, "Out of range");
            return -1;
        }
    
        for(i = 0; i < range; i++) {
            printf("Please enter a number\n");
            scan = scanf("%d", &num);
            if (scan != 1) {
                perror("Error when reading number: ");
                return -1;
            }
            numbers[i] = num;
            added[i] = 0;
        }
    
        sum = 0;
        do {
            changed = 0;
            overflow = 0;
            printf("loop: %d\n", sum);
            for (i = 0; i < range; i++) {
                if (added[i]) { 
                    continue;
                }
                num = numbers[i];
                if (sum > 0) {
                    if (num > (INT_MAX - sum)){
                        overflow = 1;
                        continue;
                    }
                } else {
                    if (num < (INT_MIN - sum)) {
                        overflow = 1;
                        continue;
                    }
                }
                printf("adding %d\n", num);
                added[i] = 1;
                changed = 1;
                sum += num;
            }
        } while (overflow && changed);
    
        if (overflow) {
            fprintf(stderr, "Overflow\n");
            return -2;
        }
    
        printf("Total: %d\n", sum);
        return 0;
    }
    

    for 循环尝试对所有数字求和,但会跳过导致溢出的数字。 do...while 循环尝试for 循环,直到我们找到一个和或溢出是不可避免的。例如:

    INT_MAX is 2147483647
    How many numbers will you put? (0-31): 5
    Please enter a number
    2147483647
    Please enter a number
    2147483647
    Please enter a number
    -2147483647
    Please enter a number
    -2147483647
    Please enter a number
    0
    loop: 0
    adding 2147483647
    adding -2147483647
    adding -2147483647
    adding 0
    loop: -2147483647
    adding 2147483647
    Total: 0
    

    【讨论】:

      猜你喜欢
      • 2021-10-04
      • 2020-05-18
      • 2012-04-11
      • 2017-08-04
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多