Search code examples
cstringdoubleatof

Converting Strings from a .csv file to doubles


Having trouble with the converting of strings to doubles. I've tried using strtod, but that does the same thing. It seems like this should work just find but perhaps using strtok has something to do with it. data[i].calories is a double of course.

data[i].calories = atof(strtok(NULL, ","));

It seems to assign either a positive or negative really big number to calories (a double, which means it must be reading the value wrong.

Data Expected:

12cx7,23:55:00,->0.968900025,(this could also be a double),0,74,0,2,

What it instead actually gets:

12cx7,23:55:00,->-537691972,0,0,74,0,2,

EDIT:

IM AN IDIOT I WAS DISPLAYING IT AS AN INT PFFFFFFFFFFFFFFFF.


Solution

  • Assuming we have an input like this,

    12cx7,23:55:00,0.968900025,,0,74,0,2,

    And we would like to,

    "Having trouble with the converting of strings to doubles."

    That is we would like to separate the alphanumeric data . And then the remaining ints and floats, we would like to print in the correct format, I would do something like the following:

    #include <cstring>
    #include <stdio.h>
    #include <stdlib.h>
    #include <ctype.h>
    
    int isNumeric (const char * s)
    {
        if (s == NULL || *s == '\0' || isspace(*s)) {
          return 0;
        }
        char * p;
        strtod (s, &p);
        return *p == '\0';
    }
    
    bool isInteger(double val)
    {
        int truncated = (int)val;
        return (val == truncated);
    }
    
    int main() {
        // If this is your input:
        char input[100] = "12cx7,23:55:00,0.968900025,0,74,0,2,";
        // Then step 1 -> we split the values
        char *token = std::strtok(input, ",");
        while (token != NULL) {
            // Step 2 -> we check if the values in the string are numeric or otherwise
            if (isNumeric(token)) {
                // printf("%s\n", token);
                char* endptr;
                double v = strtod(token, &endptr);
                // Step 3 -> we convert the strings containing no fractional parts to ints
                if (isInteger(v)) {
                    int i = strtol(token, &endptr, 10);
                    printf("%d\n", i);
                } else {
                    // Step 4 -> we print the remaining numeric-strings as floats
                    printf("%f\n", v);
                }
            }
            else {
                // What is not numeric, print as it is, like a string
                printf("%s,",token);
            }
            token = std::strtok(NULL, ",");
        }
    }
    

    For the isInteger() function, I took the idea/code from this accepted answer. The rest is quite original and probably could be refined/improved.

    This produces then this output:

    12cx7,23:55:00,0.968900,0,74,0,2,

    which is basically the output that we want, except with the very important difference that the input was a whole single string and the output is doubles/floats, ints and strings correctly identified and printed with the correct formatting.

    EDIT:

    I am not any doing error-handling here. This code is just to give the OP a proof-of-concept. Check and control for any errors returned from the used strtoX functions.