2

I'm trying to add all the numbers in a string in the C language. For example, 12abc4 should yield 16 (12+4). Can you help me complete it?

My code as of now is:

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

void function(char a[])
{
    char sum=0;
    int count=0;
    for(int i=0;a[i]!='\0';i++)
    {
        if(a[i]>='a'&&a[i]<='z')
        {
            continue;

        }
        else
        {
            if(a[i+1]>='a'&&a[i+1]<='z')
            {
                sum=sum+a[i];
            }
            else
            {
                
            }
        }
    }
    printf("%c",sum);

}

int main()
{
    int t;
    scanf("%d",&t);
    while(t--)
    {
        char a[100001];
        scanf("%s",a);
        function(a);
        printf("\n");
    }
}
Adrian Mole
  • 49,934
  • 160
  • 51
  • 83
  • Note that `scanf("%s", a);` makes your program [vulnerable to buffer overflow](https://stackoverflow.com/q/1621394/6865932), though your buffer is quite large, to avoid this use a limit in the specifier: `scanf("%100000s", a);`. In the link there are also better methods to safely read `stdin`. – anastaciu Sep 20 '20 at 17:52

2 Answers2

2

There are a number of issues with your code. First, you are confusing the char type (a representation of a printable character, such as the digit '3') and the int type (representing the actual value of a number, and stored as a binary value). In your code, you are attempting to sum the former, where (assuming ASCII representation), the character 2 will have a value of 50. We can readily address this issue by simply subtracting the value of the '0' character (ASCII 48), as the C Standard guarantees that the digits will be represented by consecutive, increasing values.

Another problem is that your code will add each individual digit, so that the 12 in your string will be summed up as 1 + 2, rather than as 12. To get round this, we can keep a 'flag' to keep track of whether we are currently 'inside' a number and, if so, first multiply our current number by 10, before adding the new digit.

Also, rather than checking a specific range of non-digit characters, you should use the standard isdigit() function to check if a character is (not) a decimal number.

There are also a few other issues in your code, which I have addressed in the comments in the "working version" posted below:

#include <stdio.h> // This header for "printf" and "scanf"
#include <ctype.h> // This one for the "isdigit" function!

void function(char a[])
{
//  char sum = 0; // Let's use an int for the sum!
    int sum = 0, add = 0; // ... and another one for each extracted number to add
//  int count = 0; // This is never used
    int in_number = 0; // We need a flag to see if we're currently processing a number
    for (int i = 0; a[i] != '\0'; i++) {
    //  if (a[i] >= 'a' && a[i] <= 'z') {
        if (!isdigit(a[i])) { // This is better than testing individual character ranges!
            if (in_number) { // We have a number to add to our total...
                sum += add;
            }
            add = 0; // Reset the 'next' number to add
            in_number = 0; // and clear our 'in_number' flag
        //  continue; // We don't need this, because the "else" block won't run if we're in here!
        }
        else { // We've found a digit ...
            add *= 10; // First, multiply our current number by 10 (before we add the next digit)
            add += a[i] - '0'; // We need to convert the character to a number
            in_number = 1; // Don't forget to set our flag to show we're currently in a number!
        }
    }
    // When we've finished our loop, we need to check if we're still inside a number:
    if (in_number) {
        sum += add;
    }
    printf("%d", sum); // Use the "%d" format to print an integer!
}

int main()
{
    int t;
    scanf("%d", &t);
    while (t--) {
        char a[1000]; // DO you REALLY need a 10001 character buffer?
        scanf("%s", a);
        function(a);
        printf("\n");
    }
    return 0; // Always good practice to actually have this at the end of your "main"
}

Feel free to ask for any further clarification and/or explanation.

Adrian Mole
  • 49,934
  • 160
  • 51
  • 83
  • Though the buffer is large there is a risk of overflow with `scanf("%s", a);`, it's a `gets` like problem. – anastaciu Sep 20 '20 at 15:33
  • 1
    @anastaciu A fair comment, indeed! I was just trying to simplify and reduce the code to address the *obvious* issues in the code. But your comment is well-made, and I shall consider editing my post (after I have had much-needed sleep)! – Adrian Mole Sep 20 '20 at 21:24
  • Ah yes, the rest of the warrior :) I already left a comment in the answer so I think we can consider it solved. – anastaciu Sep 21 '20 at 10:51
1

You need to read digits and convert them as you go through the string, as shown here:

#include <ctype.h>

int sum_numbers(char *s)
{
        int accum = 0;
        int number = 0;
        int c;
        while ((c = *s++) != 0) {
                if (isdigit(c)) {
                        number *= 10;
                        number += c - '0';
                } else {
                        accum += number;
                        number = 0;
                }
        }
        accum += number;
        return accum;
}

A complete program, that runs the algorithm on each argument passed as parameter on the command line, is shown below:

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

int sum_numbers(char *s)
{
        int accum = 0;
        int number = 0;
        int c;
        while ((c = *s++) != 0) {
                if (isdigit(c)) {
                        number *= 10;
                        number += c - '0';
                } else {
                        accum += number;
                        number = 0;
                }
        }
        accum += number;
        return accum;
}


int main(int argc, char **argv)
{
        int i;

        for (i = 1; i < argc; i++) {
                printf("argv[%d] = \"%s\", sum=%d\n",
                        i, argv[i], sum_numbers(argv[i]));
        }
        return 0;
}

same program, but reading input from stdin:

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

int sum_numbers(char *s)
{
        int accum = 0;
        int number = 0;
        int c;
        while ((c = *s++) != 0) {
                if (isdigit(c)) {
                        number *= 10;
                        number += c - '0';
                } else {
                        accum += number;
                        number = 0;
                }
        }
        accum += number;
        return accum;
}


int main(int argc, char **argv)
{
        int i = 0;
        char buffer[1000];

        while(fgets(buffer, sizeof buffer, stdin)) {
                /* get out the final \n, if present. */
                char *s = strtok(buffer, "\n");
                printf("argv[%d] = \"%s\", sum=%d\n",
                        ++i, s, sum_numbers(s));
        }
        return 0;
}

As you see, only the main() routine changes, the calculations goes the same for each of the three programs.

Luis Colorado
  • 10,974
  • 1
  • 16
  • 31