简体   繁体   中英

How to add comma separated values in string in C

How do I add all csv values in the string?

I made a skeleton but should I convert string to integer and use += to add all integers?

#include <stdio.h>
int main(void)
{
    int i;                  // index
    int num=0, sum=0;       // number
    char str[]="123,456,789";

    for(i=0; str[i]; i++) {
        if (str[i] == ',') { // begin a new number
            - ① - // multiple statements are allowed
        } else { // a digit
            num = ②;
        }
    }
    sum += num; 
    printf("Sum of all values in CSV[%s] : %d", str, sum);

    return 0;
}

There are many many ways to go about this. The preferred is simply to use strtol for its intended purpose and iterate over the string using the endptr parameter to update your position in the string to one after the last digit following a successful conversion.

However, there is good value in learning to iterate over a string with either array indexing (or preferably pointers ) to parse what you need from the string. There is nothing too complicated to parse with a pair of pointers inch-worming your way down the string picking out what you need.

Here it appears you want to loop over each character in the string, testing for commas or digits and taking the appropriate action to either add the digit to your number , or add your number to the sum if a comma is encountered. Don't forget you must convert the ASCII value for the character to its integer value before using it in your number.

A simple implementation of what you are attempting could look like the following:

#include <stdio.h>

int main(void)
{
    int i,
        num=0,
        sum=0;
    char str[] = "123,456,789";

    for (i = 0; str[i]; i++)    /* loop over each char */
        if (str[i] == ',') {    /* begin a new number */
            sum += num;         /* add number to sum */
            num = 0;            /* reset number to 0 */
        }
        else                    /* add digit to number */
            num = num * 10 + (str[i] - '0');

    sum += num;                 /* add final number to sum */

    printf ("Sum of all values in CSV[%s] : %d\n", str, sum);

    return 0;
}

Example Use/Output

$ ./bin/csvsum
Sum of all values in CSV[123,456,789] : 1368

A strtol Implementation

The reason strtol (or any of the strtoX family) are preferred is due to the error checking they provide for the conversion as well as the built in advancing of the pointer within the string being converted to the next character in the string following the digits converted. (in your case the endptr parameter will either point to a comma or the nul-terminating character in the string after each conversion.

This allows you to simply walk down the string with strtol and a pair of pointers ( p and ep -- pointer and end-pointer ), converting each set of digits to a number as you go with strtol (p, &ep, base) . After each successful conversion, just skip forward with ep until you find the next '+-' or '0-9' that will start the next valid conversion and set p = ep; and repeat. (if you reach the nul-terminating character while advancing ep - you know you are done with the conversions)

A simple implementation would be:

#include <stdio.h>
#include <stdlib.h>     /* for strtol */
#include <limits.h>     /* for INT_MAX */
#include <errno.h>      /* for errno */

#define BASE 10         /* added benefit - strtol will convert from many bases */

int main (void)
{
    int sum=0;
    long tmp = 0;                   /* tmp long for strtol conversion */
    char str[] = "123,456,789",
        *p = str, *ep = NULL;       /* pointer and end-pointer */

    for (;;) {                      /* perform conversion until end (or error) */
        errno = 0;                      /* reset errno */
        tmp = strtol (p, &ep, BASE);    /* perform conversion, update ep */
        if (errno) {                    /* check conversion was valid */
            fprintf (stderr, "error: invalid conversion.\n");
            return 1;
        }
        if (tmp < INT_MAX - sum)        /* make sure tmp will fit in sum */
            sum += (int)tmp;            /* add tmp to sum */
        else {
            fprintf (stderr, "error: sum overflowed.\n");
            return 1;
        }
        /* find the next '+-' or 'digit' or end of string */
        while (*ep && *ep != '+' && *ep != '-' && ( *ep < '0' || '9' < *ep))
            ep++;
        if (!*ep) break;    /* if *ep is nul-character, end reached, bail */
        p = ep;             /* update pointer to end-pointer, repeat */
    }

    printf ("Sum of all values in CSV[%s] : %d\n", str, sum);

    return 0;
}

Look things over and let me know if you have further questions.

First you can trim all white spaces and all.

Secondly as you mentioned there will only be integers separated by commas so you should understand the general way to get an integer.

So what is the idea?

You will continue to form the number unless you see a comma or end of string.

How to form the number?

|ABCD
      num
A|BCD  A   [Here also 10*0+A]
AB|CD  A*10+B
ABC|D  (A*10+B)*10+C
ABCD|  ((A*10+B)*10+C)*10+D = 1000*A+100*B+10*C+1*D

You repetitively multiply the existing number with 10 and then add it.

This way you form the number.

I have avoided giving the answer with functions. There are other options like using builtin functions like strtok etc. You can check them in reference.

You can perform want you want with strtok and strtol functions:

int main(void)
{
    /* delimiter: string will be cut on spaces and comma */
    char delim[] = " ,";
    char *tok;
    /* string to parse */
    char str[] = "123,465,798";

    int sum = 0, num;

    /* get first token, warning `str` is modified */
    tok = strtok(str, delim);
    while (tok)
    {
        /* convert token to int */
        num = strtol(tok, NULL, 0);

        /* add it to sum */
        sum += num;

        /* read next token */
        tok = strtok(NULL, delim);
    }
    printf("sum is %d\n", sum);
    return 0;
}
int main() {

    int i;  // index

    int iGroup=0;// groupNumber array

    int num=0, sum=0;       // number
    char str[]="123,456,789";
    char strNum[16];
    memset(&strNum[0], 0, sizeof(strNum));

    for(i=0; str[i]!='\0'; i++) {
        if (str[i] == ',' ) { // Get the group number array since the numbers 

            iGroup=0;                     //Reset the index of the groupNumber array
            num=atoi(strNum);                 //Convert the array to numbers
             memset(&strNum[0], 0, sizeof(strNum)); //Set the groupNumber array to null 
                   sum += num; 
        } else { // a digit
            strNum[iGroup]=str[i];             //Add the character to groupNumber array
            iGroup++;
        }
    }
       num=atoi(strNum); 
       sum += num;
    //sum += num; 
    printf("Sum of all values in CSV[%s] : %d", str, sum);

    return 0;
}

Here is a solution with strtol() and strspn() that does not modify the input string:

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

int sum_csv(const char *str) {
    int sum = 0;
    for (;;) {
        char *p;
        int n = strtol(str, &p, 10);  /* convert number */
        if (p == str)                 /* stop if no number left */
            break;
        sum += n;                     /* accumulate (ignore overflow) */
        str = p + strspn(p, ", ");    /* skip number and delimiters */
    }
    return sum;
}

int main(void) {
    printf("sum is %d\n", sum_csv("123,465,798");
    return 0;
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM