I'm trying to parse an argument value in C and convert the number to a double value. I have:
char *stringEnd;
double num = strtod("123.0", &stringEnd);
I used "123.0" just to test the function, but it always returns a value of 0.0. Does anybody know what I'm doing wrong?
Are you including the relevant header? ie: #include <stdlib.h>
First though (and you should be doing this all the time anyway), try compiling with all warnings on (-Wall on GCC).
If you get a warning about strtod being undefined, that shows where the problem is coming from.
This is a nasty one, because C will implicitly declare any function it doesn't have a prototype for as returning int!
You if have to use strtod in order to use:
double num = strtod("123.0", NULL);
you can also use sscanf
double num;
sscanf("123.0", "%lf", &num);
You can use sscanf.
double num;
sscanf("123.0", "%lf", &num);
You need to #include stdlib.h.
In which language is your operating system? I'm not sure how the C function strtod reacts, but I know that the equivalent delphi function takes the settings of the operating system into account. Some languages (french, german, ...) use a "," instead of a "." as decimal separator.
Related
I'm testing conversion specifiers both for printf() and scanf() function. I hadn't problem with %a format specifier for floating point hexadecimal number used in printf() function. It displayed what I expected. But I encountered problem when I wanted to input hexadecimal float using
scanf("%a", &var);
I'm using the following code:
#include <stdio.h>
int main()
{
float var;
printf("Enter variable:\n");
scanf("%a", &var);
printf("var = %f\n", var);
printf("var = %e\n", var);
printf("var = %a\n", var);
return 0;
}
When I enter a sample value, e.g. 0x1.205b0cp-11 that is 5.5e-4 it gives me that result:
Enter variable: 0x1.205bc0p-11
var = 0.000000 var = 0.000000e+000 var = 0x0.000000p+0
Whatever number I enter it always gives me 0. What's the reason or solution for that problem. I have no idea what I'm making wrong.
That code works on my system(a), producing the expected result:
pax> ./prog
Enter variable: 0x1.205bc0p-11
var = 0.000550
var = 5.500000e-04
var = 0x1.205bcp-11
Keep in mind that hexadecimal floating point constants (and the %a conversion specifier) were introduced in C99, so you should make sure you're using a compiler that handles that. Most modern ones will, but some people may be locked in to a certain level if the vendor isn't keen on keeping up to date(b).
Keep in mind that the scanf family, conversion specifiers a, e, g, and f (and their upper-case variants) are all the same - they each handle every format that strtod handles. The (likely) reason that they all exist is to mirror the printf conversion specifiers where it makes a difference to how the value is output.
It's possibly worth testing with a variety of inputs less advanced than hex floating point, and work your way up to there. For example, the sequence { 0, 3, 3.1, 3.14159. 9e2, 6e-2, ... }. That would at least let you know where the input is failing.
Also, it's a good idea to test the conversion to ensure it works (this is true of all calls where failure can adversely affect future program behaviour). In other words, something like this in place of your scanf statement:
if (scanf("%a", &var) != 1) {
fprintf(stderr, "Something went horribly wrong!\n");
return 1;
}
(a) My system, by the way, is gcc 9.4.0 (from gcc --version) running on Ubuntu 20.04.2 (from cat /etc/lsb_release). It's often a good idea to include that sort of information in questions, it can help us figure out issues more quickly.
(b) Possibly a good reason to consider changing vendors though, of course, subject to normal cost/benefit analysis.
Try computing somehow like with printf("var = %e\n", var/7.0 + var *var);. Sometimes simple code without doing any math does not link in the math library needed by printf().
While working on an embedded project, I noticed that sprintf() method for the following code:
char ln2[16];
sprintf(ln2, "%f Volt", Data[Position].Voltage1);
generates the question mark character as output.
The output generated from the code above is:
? Volt
while the input is declared as double Voltage1 = 0.0;
The same issue does not seem to apply while trying to format an integer.
The following works as expected:
char ln1[16];
sprintf(ln1, "POSITION %d", (Position + 1));
and outputs POSITION 3 where the Position is a global variable and declared as int.
The structure that actually holds the data is:
struct data
{
int Position;
double Voltage1;
double Voltage2;
};
All above while using the C/C++
and the Platform.io extensions both for VS Code.
What is going on wrong here?
Embedded versions of the printf usually do not implement float number handling. You need to let the linker to link the correct version of the function. For example for ARM gcc it will be -u _printf_float or/and -u _scanf_float
ln2 points to a string literal. String literals are read-only, so when you attempt to write to it you invoke undefined behavior.
You should instead define ln2 as a character array which is writable.
char ln2[16];
I was doing basics of macros. I define a macro as follows:
#define INTTOSTR(int) #int
to convert integer to string.
Does this macro perfectly converts the integer to string? I mean are there some situations where this macro can fail?
Can I use this macro to replace standard library functions like itoa()?
for example:
int main()
{
int a=56;
char ch[]=INTTOSTR(56);
char ch1[10];
itoa(56,ch1,10);
printf("%s %s",ch,ch1);
return 0;
}
The above program works as expected.
Interestingly this macro can even convert float value to string.
for example:
INTTOSTR(53.5);
works nicely.
Till now I was using itoa function for converting int to string in all my projects. Can I replace itoa confidently in all projects. Because I know there is less overhead in using macro than function call.
Macros execute during (before to be exact) compile time, so you can convert a literal number in your sourcecode to a string but not a number stored in a variable
In your example, INTTOSTR(56) uses the stringification operator of the preprocessor which eventually results in "56". If you called it on a variable, you'd get the variable name but not its content.
In C, you can use itoa or if you are desperate and would like to avoid it, use snprintf for instance:
snprintf(my_str, sizeof(int), "%i", my_int);
The problem with your macro is that you are thinking about constants, but of course, your macro will be broken when you need to use a variable holding an integer. Your macro would try to stringify the macro name as opposed to the value it would be holding.
If you are fine with constants, your macro is "good", otherwise it is b0rked.
Your macro does not convert integers to strings, it converts a literal into a string literal, which is something very different.
Literals are any plain numbers or definitions of values in your code. when you do int x = 10; the numeral 10 in an integer literal, while x is a variable and int is the type. const char* ten = "10"; also defines a literal, in this case a string literal, with value "10" and a variable called ten which points to the address where this literal is defined. What your macro actually does is change the way the literal is represented before any actual compilation goes on, from an integer literal into a string literal.
So, the actual change is being done before any compilation, just at source code level. Macros are not functions and cannot inspect memory, and your convertion would not work with variables. If you try:
int x = 10;
const char* ten = INTTOSTR(x);
You would be very puzzled to find that your variable ten would actually hold the value "x". That's because x is treated as a literal, and not as a variable.
If you want to see what's going on, I recommend asking your compiler to stop at preprocessing, and see the output before your code is acutally compiled. You can do this in GCC if you pass the -E flag.
PS. Regarding the apparent "success" with conversion of float values, it just comes to show the danger of macros: they are not type-safe. It does not look at 53.5 as a float, but as a token represented by characters 5, 3, . and 5 in the source code.
Why do we pass the format specifiers to scanf( ) in C as its parameters?
I mean, can't we just do
scanf( &var ); // Here, var is any pre-declared variable.
the type of var can be fetched from its declaration. Why is this not allowed ?
I see the below code as a waste of memory.
scanf( "%d" , &var );
The type cannot be "fetched from it's declaration". There is nothing magical about scanf(), it's just a function. A function in C cannot access meta information about variables.
This is why, in general, function arguments are declared including their type. For variable-argument functions such as scanf(), the first argument is not optional and it is used to describe the number and type of the other arguments in some fashion chosen by the function itself.
You clearly need to read some book on C programming to get better understanding of the core concepts. Unlike some other languages, C doesn't have I/O mechanism baked into the language. scanf() is just a library function and as such, this function has no way to automagically know the type of the variable it is supposed to fill.
Because %d will simply specify what the type of var is, there is no memory wastage. scanf(&var) would not work because the function is not designed to accept arguments that way.
You know that variables in C can be of different types:
int: Integer
char: Character
float: Floating point number.
...
Unlike other languages, variable types cannot be implicitly inferred at compilation time in C. That is why you always declare the type of your variables ( Example: int a or char c).
Because scanf is just a function in C, and because functions in C should take parameters of a specific type, people who coded C decided to use the following format:
scanf("%d", &var) ; // for integers
scanf("%c", &var); //for chars
scanf("%f", &var); //for double and floats.
using %d or %c does not waste memory or whatsoever. you can think about it as a flag that specifies the type of the input variable.
Could the developers of C do it without %d, %c...etc? Yes they could, but then, they have to handle all possible exceptions that might arise from sending the wrong type.
Suppose the developers of C used just the following format
scanf(&var);
That is surly very concise, but then you will have to use the same syntax to send chars/int/double...etc, and then the function scanf has to figure out a way to decide about the type of the variable that was sent. Remember what I told you before? variable types CANNOT be implicitly inferred at compilation time, and thus, this task will be almost impossible.
They could however use a different scanf function for every type. For example:
scanfInt(&var); //for integers.
scanfFloat(&var); //for floats.
...
...
That would work perfectly, but it makes less sense to replicate the same code of scanf and use different functions just because the type is different.
So what is the solution? ==> Use the same function name ( scanf ), and then add a parameter (%d, %f, %c..) that will be used internally as a flag by C to know the parameter type.
I hope now you have a better understanding of the use of %d, %f....
There are two major points you are missing here.
First, we humans sitting at the keyboard will write something like:
char var = '0';
And we know that the "type" of this variable is char and we probably intend to store a character there. Once the compiler gets a hold of this it removes these "human" elements all that is left is at some memory location there is 1 byte reserved, further references to places in the code where we wrote "var" will interact with this memory location. That is all the compiler knows, there is no understanding of the intended variable "type".
Second, the format specificers do so much more than just indicate a simple type. Look at any page explaining scanf() and you'll see a long list, take special note of things like scan sets, negated scan sets, and expected input lengths.
Let's say I want the user to enter just a single digit, 0-9, well I don't have to just assume they will do as I ask, I can help ensure they will by using the format specifiers in scanf():
int var = 0;
print("enter 1 digit (0-9):\n");
scanf("%1d", &var);
Now, no matter how many digits they enter, I'll only have stored the first one.
What if you have a string that you want to read from the user, and you want to read everything up until you hit a new line character (read over spaces). We'll there are a number of options for this, but scanf can do it too. The "standard" to read a string is:
scanf("%s",some_string);
But that will stop at any whitespace character, so you wouldn't want scanf() to make an assumption in this case, you'd want to be able to use a specific negated scanset:
scanf("%[^\n]",some_string);
What's going on here:
printf("result = %d\n", 1);
printf("result = %f\n", 1);
outputs:
result = 1
result = 0.000000
If I ensure the type of these variables before trying to print them, it works fine of course. Why is the second print statement not getting implicitly converted to 1.00000?
In the second case you have a mismatch between your format string and the argument type - the result is therefore undefined behavio(u)r.
The reason the 1 is not converted to 1.0 is that printf is “just” a C function with a variable number of arguments, and only the first (required) argument has a specified type (const char *). Therefore the compiler “cannot” know that it should be converting the “extra” argument—it gets passed before printf actually reads the format string and determines that it should get a floating point number.
Now, admittedly your format string is a compile-time constant and therefore the compiler could make a special case out of printf and warn you about incorrect arguments (and, as others have mentioned, some compilers do this, at least if you ask them to). But in the general case it cannot know the specific formats used by arbitrary vararg functions, and it's also possible to construct the format string in complex ways (e.g. at runtime).
To conclude, if you wish to pass a specific type as a “variable” argument, you need to cast it.
An undefined behavior. An int is being treated as float
The short answer is that printf isn't really C++. Printf is a C function which takes a variable argument list, and applies the provided arguments to the format string basis the types specified in the format string.
If you want any sort of actual type checking, you should use streams and strings - the actual C++ alternatives to good old C-style printf.
Interesting, presumably it's fine if your put '1.0'
I suppose the printf only gets the address of the variable, it has no way of knowing what it was. But I would have thought the compiler would have the decency to warn you.