【问题标题】:Scanf a number with 300 digits in C用C扫描一个300位数字的数字
【发布时间】:2022-01-05 17:48:33
【问题描述】:

有一个问题:我应该扫描一个 300 位数字并打印数字总和,但我无法用 long long int 扫描它,我不知道该怎么做。

【问题讨论】:

  • 将其读入char* 并手动求和
  • 提示:将其扫描为字符串,然后解析每个数字
  • 如果您只关心以 10 为基数的数字,那么您实际上不需要或不想存储数字。
  • 是一个很好的学习练习。不幸的是,现在有几张“有用”的海报已经为您提供了完整的答案,因此您错过了寻找解决方案的“啊哈”时刻。

标签: c loops sum c-strings digits


【解决方案1】:

您可以使用fgets() 将数字作为字符串扫描,或者使用getchar() 一次读取一个字节:

#include <stdio.h>

int main() {
    int c;
    int sum = 0;
    while ((c = getchar()) != EOF) {
        if (c >= '0' && c <= '9')
            sum += c - '0';
        else
            break;
    }
    printf("sum: %d\n", sum);
    return 0;
}

你必须使用scanf(),这里有一个替代方案:

#include <stdio.h>

int main() {
    char buf[2];
    int sum = 0;
    while (scanf("%1[0-9]", buf) == 1) {
        sum += *buf - '0';
    }
    printf("sum: %d\n", sum);
    return 0;
}

【讨论】:

    【解决方案2】:

    在这种情况下,您需要输入一个数字作为字符串。

    要输入一个数字,您应该使用标准函数fgets。对应的字符数组必须有 302 个字符:300 个字符用于数字,1 个字符用于由函数 fgets 附加到输入字符串的换行符 '\n',1 个字符用于终止零字符 '\0'字符串。

    如果字符串中不存在换行符'\n',则表示用户输入了超过300个字符。

    用户还可以输入带有前导或尾随空格的数字。

    您需要检查输入的字符串是否包含有效数字。

    这是一个演示程序。

    #include <stdio.h>
    #include <string.h>
    #include <ctype.h>
    
    int is_valid_number( const char *number )
    {
        while ( isblank( ( unsigned char )*number ) ) ++number;
        
        int valid = *number != '\0';
        
        if ( valid )
        {
            while ( isdigit( ( unsigned char )*number ) ) ++number;
            while ( isblank( ( unsigned char )*number ) ) ++number;
            valid = *number == '\0';
        }       
        
        return valid;
    }
    
    int main( void )
    {
        enum { N = 300 };
        char number[N + 2] = { 0 };
    
        printf( "Enter a non-negative number (no greater than %d digits): ", N );
    
        fgets( number, sizeof( number ), stdin );
        
        int valid = strchr( number, '\n' ) != NULL;
        
        char *p = number;
    
        if ( valid )
        {
            number[ strcspn( number, "\n" ) ] = '\0';
            while ( isblank( ( unsigned char )*p ) ) ++p;
            valid = is_valid_number( p );
        }
        
        if ( !valid )
        {
            puts( "Invalid number." );
        }
        else
        {
            unsigned int sum = 0;
    
            for ( char *digit = p; isdigit( ( unsigned char )*digit ); ++digit )
            {
                sum += *digit - '0';
            }
    
            printf( "The sum of digits = %u\n", sum );
        }
    }
    

    它的输出可能看起来像

    Enter a non-negative number (no greater than 300 digits): 1234567890123456789012345678901234567890
    The sum of digits = 180
    

    【讨论】:

    • @chqrlie 我已经更改了 for 循环中的条件。
    【解决方案3】:

    最直接的解决方案似乎是重复读取 1 位整数并在可行时对其进行总结。
    一位数字可以很容易地读入 int(不再需要),即使 300 位数字的总和也不会超过 int。

    #include <stdio.h>
    
    int main()
    {
        int digit=0;
        int sum=0;
        while(1==scanf("%1d",&digit))sum+=digit;
        printf("sum:%d\n", sum);
    
        return 0;
    }
    

    诚然(感谢 chqrlie 指出)期待行尾,因为它带有例如在线编译器或评委的测试输入。在交互式提示中

    ...单行数字是不够的,需要用 ^D 显式结束文件。

    【讨论】:

    • 有一个小问题:您的程序将继续从标准输入读取,直到文件结束或输入非数字。 %1d 格式将忽略换行符和其他空格。输入单行数字是不够的,需要使用 ^D 显式结束文件。
    • @chqrlie 为什么你认为在 EOF 之前阅读是不行的?我不反驳这个问题。但我明白你的意思,没有涵盖一些明显的用例。让我们看看我是否能想到一些东西......
    • 在没有从其他答案之一中得到解决方案的情况下无法想到任何事情。所以我明确指出了这个解决方案的特殊性。@chqrlie
    【解决方案4】:

    您可以使用 char 扫描每个数字。也这样你就不需要字符串了。enter image description here

    【讨论】:

    • 欢迎来到 Stack Overflow。请阅读How to Answerplease don't post screenshots of text。它们无法被屏幕阅读器等自适应技术的用户搜索或复制,甚至无法使用。相反,将代码作为文本直接粘贴到您的问题中。如果选择它并单击{} 按钮或 Ctrl+K 代码块将缩进四个空格,这将导致其呈现为代码。
    • 代码与解释的比例可能会阻止您发布带有少量解释的代码。但这只是意味着你必须添加更多的散文解释。
    【解决方案5】:
    #include <stdio.h>
    
    int main() 
    {
        char digit;
        int sum = 0;
        while ( scanf("%c", &digit) != EOF) 
        {
             sum += digit - '0';
        }
        printf("sum: %d\n", sum);
        return 0;
    }
    

    【讨论】:

    • 结果将不正确,因为所有输入字节都将被处理,包括非数字,尤其是换行符。
    • 根据问题,输入将仅为数字。所以,这个解决方案有效。
    • 关于如何从用户那里检索输入的问题尚不清楚,但要确保只能通过scanf() 从用户那里读取数字是非常复杂的。即使用户只输入数字,为触发输入而键入的回车键也会由scanf() 作为'\n' 字节返回,这将破坏总和。
    • 虽然这可能在技术上通过对规范的非常严格的解释来工作,但大多数通过 stdin 输入文本的方法都会导致尾随换行符,除非你特别想省略它,所以我会至少认为这非常脆弱。 (编辑:虽然 TBH 我从不直接使用 scanf,所以我实际上不记得 %c 是否扫描换行符。)
    • @Arkku: scanf("%c", &amp;digit) 确实会在行尾返回 1 并将 digit 设置为 '\n',因此 sum 将被错误地更新。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2015-01-27
    • 2014-01-26
    • 1970-01-01
    • 2017-03-30
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多