0

So you have to do:

11 = 1+1 = 2

3578 = 3+5+7+8 = 23 = 2+3 = 5

But the problem is that the number can be very large(consist of 10,000 digits)

But even with the easiest entrances it doesn't work:

Input : 11

Output: 2798 (and it always changes, but remains a 4-digit number)

Can someone explain why is this happening? And how can I summarize each digit of a very large number?

redflag
  • 27
  • 5
  • You have `while( buffer[idx] != '\n' )` but `scanf` does not read a newline - use `fgets()`. Or better, `while(isdigit(buffer[idx]))` – Weather Vane Mar 30 '22 at 13:16
  • 1
    Two things: The buffer will never contain a newline. That means your loop condition is flawed; And there's no encoding where the character `'1'` equals the number `1` (with the most common ASCII encoding, `'1'` is actually equal to the number `49`). That means your calculation is incorrect. – Some programmer dude Mar 30 '22 at 13:17
  • You want to offset your *characters* by the ASCII value of `'0'`, such as `result = (int)buffer[idx] + result - '0';` – Eugene Sh. Mar 30 '22 at 13:18
  • On another couple of notes (but unrelated to your problem), the `idx` variable doesn't need to be an `unsigned long long`, plain `unsigned` is enough. And instead of your `while` loop I suggest a `for` loop, like `for (unsigned idx = 0; buffer[idx] != '\0'; ++idx)`. Also, you should *really* check what `scanf` [*returns*](https://en.cppreference.com/w/cpp/io/c/fscanf#Return_value) before attempting to use the contents of the buffer. There's also no need to cast the characters, all characters will be promoted to `int` anyway. – Some programmer dude Mar 30 '22 at 13:20
  • 2
    The examples suggest that you want to *repeat* the digit summation until you end up with a one-digit result. The code presented does not do that. – John Bollinger Mar 30 '22 at 13:28
  • That the input number can be larger than is representable by any built-in type just means that you have to read it as text, which you are doing. No decimal digit sum can exceed nine times the number of digits, and for a 10000-digit input, that tops out at a first-round sum of 90000. That is well within the range of type `long`, and probably within the range of type `int` (though implementations may vary here). Conclusion: you don't need any fancy math or custom internal representation. – John Bollinger Mar 30 '22 at 13:53

3 Answers3

0

You got that huge number becuase your program is adding the ASCII value of various characters.

Some improvements:

  • Don't use "%s", use "%<WIDTH>s", to avoid buffer-overflow
  • Use size_t to iterate through an array, instead of unsigned long long int
  • Instead of using bare return 0;, use return EXIT_SUCCESS;, which is defined in the header file stdlib.h.
  • always check whether scanf() input was successful or not
  • Don't check for '\n', because string from scanf() ends at both SPACES and NEWLINE.
  • adding +1 to array size for NULL terminating character
  • Use "%zu" instead of "%lld" for size_t

Final Code:

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

int main(void) {
    char buffer[10001] = {0};

    if(scanf("%10000s", buffer) != 1)
    {
        perror("bad input");
        return EXIT_FAILURE;
    }

    size_t result = 0;
    for(size_t i = 0; buffer[i]; i++) {
        if(isdigit(buffer[i])){
            result += buffer[i] - '0';
        }
        else {
            perror("only digits are valid");
            return EXIT_FAILURE;
        }
    }

    printf("%zu\n", result);
    return EXIT_SUCCESS;
}

Output:

1112
5

TRY IT ONLINE

Darth-CodeX
  • 2,166
  • 1
  • 6
  • 23
0

You can do it without occupying memory

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

int main(void) {
    int sum = 0;
    for (;;) {
        int ch = getchar();
        if (!isdigit((unsigned char)ch)) break; // leave loop with ENTER, EOF, 'a', ...
        sum += ch - '0';
    }
    printf("sum of digits is %d.\n", sum);
    return 0;
}

Edit: see code running at ideone

pmg
  • 106,608
  • 13
  • 126
  • 198
  • That `(unsigned char)` cast is not needed – Darth-CodeX Mar 30 '22 at 13:42
  • 1
    @Darth-CodeX: I interpret [C11 7.4p1](https://port70.net/~nsz/c/c11/n1570.html#7.4p1) as saying otherwise. – pmg Mar 30 '22 at 13:45
  • `int isdigit(int c);`, needs `int` and your `ch` is also `int`. Why you need to type-cast? – Darth-CodeX Mar 30 '22 at 13:47
  • Because I don't know if all the values `getchar()` may get are valid (unless I convert to `unsigned char`). Maybe the user types `"6ñ..."` – pmg Mar 30 '22 at 13:48
  • But `isdigit()` checks for a range between `48...57` – Darth-CodeX Mar 30 '22 at 13:50
  • @Darth-CodeX The linked standard states "In all cases the argument is an int, the value of which shall be representable as an unsigned char or shall equal the value of the macro EOF. **If the argument has any other value, the behavior is undefined**. " – Andrew Henle Mar 30 '22 at 13:52
  • 1
    The value sent to `isdigit()` **must be** representable as an unsigned char. Maybe `ñ`, when interpreted as an `int` has value `-153`. – pmg Mar 30 '22 at 13:53
0

Wiki Digital Root provides a shortcut for getting the final single digit.

  • Validate your input string has only numeric digits
  • Find the sum of all digits in ASCII form
  • Make use of congruence formula to get the result.
#include <stdio.h>
#include <string.h>
#include <ctype.h>

#define MAX_NUM_LEN 10000

int digitRoot (int n) {
    if (0 == n) return 0;
    return (0 == (n % 9)) ? 9 : (n % 9);
}

int main () {
    char str_num [MAX_NUM_LEN];

    printf ("Finding Digital Root\nEnter a number : ");
    if (NULL == fgets (str_num, sizeof (str_num), stdin)) {
        perror ("Reading input string");
        return 2;
    }

    int slen = strlen (str_num);
    // remove new line if found
    if ('\n' == str_num[slen - 1]) str_num[--slen] = '\0';
    // validate input
    int digitSum = 0;
    for (int ni = 0; ni < slen; ++ni) {
        if (!isdigit ((unsigned char) str_num[ni])) {
            printf ("\nERROR: Invalid digit [%c]\n", str_num[ni]);
            return 1;
        }
        digitSum += str_num[ni] - '0';
    }
    printf ("\nDigital Root is [%d]\n", digitRoot (digitSum));
    return 0;
}
जलजनक
  • 3,072
  • 2
  • 24
  • 30