0

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.

  • 1
    How are you displaying the double value? You do not use `"%d"`, do you? – Serge Ballesta Jan 24 '19 at 06:22
  • How should we know what `data[i].calories` is or how you print the values? This is the reason why you should always add a [MCVE](https://stackoverflow.com/help/mcve). – Gerhardh Jan 24 '19 at 06:46
  • 1
    If you think, `strtok` might be involved in the problem, what did it show when you checked the results of `strtok`? – Gerhardh Jan 24 '19 at 06:47
  • Please (re)read about how to make an MCVE ([MCVE]). Note that this includes some sample input data (2 lines would be sufficient), the expected output and the actual output (if there is any; if the program crashes before generating output, say so). Without that, all we can do is guess — you're quite possibly getting a null pointer from `strtok()`, for example. Certainly, you should be capturing what `strtok()` returns and printing it (if it isn't null) to ensure that you're getting what you expect. – Jonathan Leffler Jan 24 '19 at 07:07

1 Answers1

0

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.

Duck Dodgers
  • 3,409
  • 8
  • 29
  • 43
  • You should really avoid the `atoX` functions. They provide zero ability to validate the conversion. Instead using the `strtoX` functions, you have fine-grained control over error checking and validation of the conversion. (and yes, I know that was asked for in the question, but it is always helpful to ensure they know the difference) – David C. Rankin Feb 01 '19 at 08:38
  • @DavidC.Rankin Edited as per your suggestion. Yes, it was known to me that `atoX` functions are unsafe, but to provide a proof-of-concept (and not robust production-level code), I had used them here. – Duck Dodgers Feb 01 '19 at 08:44
  • Well, that's better, but unless you are checking `if (token == endptr)` (to determine if digits were converted, and if so, `if (errno)` indicating over/underlfow occurred, you may as well use `atoX`. For the purpose of your question, I would just add a node under your code indicating that both should be checked for. (also you mixed your C++ with your C, e.g. `std::strtok` `:)` Also, why `strtod` instead of a `strchar (token, '.')`? Just seems a bit 'different' in the approach. – David C. Rankin Feb 01 '19 at 08:48