4

I have this code to convert an ASCII string to and int, float, or double. However, it prints "42" for all of them. Where did I go wrong? The syntax looks correct, no warnings.

#include <stdlib.h>
int main(void)
{
     char *buf1 = "42";
     char buf2[] = "69.00";
     int i;
     double d;
     long l;
     i = atoi(buf1);
     l = atol(buf1);
     d = atof(buf2);
     printf("%d\t%d\t%d\n", i, l, d);
     return 0;
}
10
  • Interesting question. I wrote some code to do this not to long ago. check it out here: github.com/rmccullagh/snippets/blob/master/c/ascii/main.c Commented Aug 1, 2014 at 17:16
  • 13
    You have 3 different types, yet you use the same format string for all of them in your printf. Use the right format string for each type. Commented Aug 1, 2014 at 17:16
  • 2
    Don't use ato*. There's no way to tell if a returned 0 is a valid result or an error. Commented Aug 1, 2014 at 17:16
  • 4
    try #include <stdio.h> and printf("%d\t%ld\t%f\n", i, l, d); Commented Aug 1, 2014 at 17:17
  • 3
    "no warnings": gcc emits a warning when it detects mismatching arguments to printf. Commented Aug 1, 2014 at 17:17

3 Answers 3

5

First, you should avoid use of the ato* functions (ie: atoi, atof, etc), because there are cases where the conversion failed, and it just returns zero, so you have no way to know if the input was really a string representing zero, or if it was due to a processing error. If you modify the example below, for example, and change buf2 to "z16", you will get a warning you can handle. atoi would not let you know about that error.

Second, your format specifiers are incorrect in your printf call. Your compiler should have generated warnings about this.

Please refer to the example below for a working version that includes conversion error handling. Not that the explicit casting of strtol to (int) in my example does allow for a potential integer overflow. Try making buf1 a large number, and see what happens.

Good luck!

Code Listing


#include <stdio.h>   /* printf */
#include <stdlib.h>  /* strtox */
#include <errno.h>   /* error numbers */

#define BASE         (10)  /* use decimal */

int main(void) {
   char* errCheck;
   char *buf1   = "42";
   char *buf2   = "16";
   char  buf3[] = "69.00";
   int i;
   double d;
   long l;

   /* Handle conversions and handle errors */
   i = (int)strtol(buf1, &errCheck, BASE);
   if(errCheck == buf1) {
      printf("Conversion error:%s\n",buf1);
      return EIO;
   }
   l = strtol(buf2, &errCheck, BASE);
   if(errCheck == buf2) {
      printf("Conversion error:%s\n",buf2);
      return EIO;
   }
   d = strtod(buf3, &errCheck);
   if(errCheck == buf3) {
      printf("Conversion error:%s\n",buf3);
      return EIO;
   }

   printf("%d\t%ld\t%lf\n", i, l, d);
   return 0;
}
Sign up to request clarification or add additional context in comments.

10 Comments

Although using strtox() is better than atox(), code here also fails to detect overflow and potential garbage at the end of bufn, much like atox().
Fair enough. He could test against LONG_MAX, etc. stackoverflow.com/questions/5493235/… Also, a quick isalpha loop would handle trailing garbage. The general point I was making was to avoid atox functions.
Parenthesizing a positive numeric literal like 10 is a sign of too much paranoia. Rule of thumb: parenthesize if there's an operator in the replacement text. Everything else is a sign of someone not grokking C :-)
@Jens It is not a sign of paranoia. It is there to appease static code analysis tools (MISRA chk, LINT) etc, so you can sign off on compliance with certain standards legally. Old habits die hard.
@Jens I think you just answered your own question. (-1) evaluates as a signed integer literal, just like (1) evaluates to a literal. Wind River Workbench. This also enforces consistency throughout the code. A decent example would be using a type of globally-accessible offset encoded as a signed integer. If it changes from say, (2) to (-1), it's silly that the definition should change based on range. Depending on your master rule override file, your static code analysis tools might also do this to, but the option could be disabled.
|
2

Change

printf("%d\t%d\t%d\n", i, l, d);

to

printf("%d\t%ld\t%f\n", i, l, d);

1 Comment

stdlib.h is needed for atoi, etc. Both headers are needed.
1

Please don't use ato* functions as ato* functions has been deprecated by strto* and should not be used in new code.

The problem with ato* is, if the converted value is out of range it causes undefined behavior.

For more information check here.

3 Comments

With "... ato* functions are obsolete". Do you have some reference that indicates obsolescence? The ato* functions are in the latest C spec. (C11).
Kindly check Implementation Notes section: codecogs.com/library/computing/c/stdlib.h/atoi.php
Suggest editing your answer to match your reference indicating that functions are deprecated.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.