How does conversion specifier work? - c

Can I check my understanding of scanf?
int a;
scanf("%d",&a);
If I input 13, does conversion specifier convert 13 to binary and stored it in a?
If input is 13.3, then does it convert decimal fraction 13.3 to binary and store it in a?

I don't know about your knowledge in C, but how data stores in C is really is very important and interesting topic.
whenever data stores in variable it is always in binary format, it is not possible to see that binary data in simple C language but you can see the binary in embedded C. Where we pass data in any port or any program providing data internally and then sending the output to any port which is connected to the led.
Suppose the if you passed -1 in a port and the port is sending output to led connected with it then you can see all leds connected with it will glow.
In C you can observe like that
char c=-1;
printf("%u",c);
output=255
%u is used for unsigned integer it is not an error you can check it.
int and char always store in same fashion means if you try store char A then I think so it's ASCII value 65 will stored in binary way.
char ch='A';
printf("%d",ch);
output 65
same
int i=65;
printf("%c",i);
output A;
But float is stored completely different from int it has three different parts one is sign bit, second is mantissa and then exponent.
suppose
float f=5.55;
if(f==5.55)
pf("true");
else
pf("false");
output : false
now again
float f=5.25;
if(f==5.25)
pf("true");
else
pf("false");
output : true
so it's all about data stores in memory very important topic generally teacher not discuss in their classes.
Hope use full for you.

OP: If I input 13, does conversion specifier convert 13 to binary and stored it in a?
A: Yes. When user enters 1, 3, Enter, scanf("%d", ...) receives optional leading white-space (which there is none) then the chars '1', '3', and '\n'. Seeing '\n' is not a digit, it is put back into stdin for the next IO operation. The '1', '3' are converted to an int with the value of 13 **. The 13 is stored at &a. scanf() then returns a value of 1 which the code unfortunately does not use.
OP: If input is 13.3, then does it convert decimal fraction 13.3 to binary and store it in a?
A: No. scanf("%d", ...) reads the text as described above but instead of stopping at '\n', it stops at '.' and puts that back for subsequent IO. The '1', '3' is converted to 13 and stored in &a. The next IO operation will start with '.'. and likely cause trouble.
Suggest instead:
char buf[40];
fgets(buf, sizeof buf, stdin);
if (sscanf(buf, "%d", &a) != 1) Handle_IntNotEntered(buf);
Other approaches exist , like using strtol(), but the important issue is that users enter all sorts of unexpected text and the input needs validation and error handling.
** The 13 is typically stored in binary - I know of no machine that that does otherwise. But the details of how the 13 is stored should not make a difference. a will have the value of 13, if it is stored in binary, BCD or with 13 chipmunks running on 13 wheels.

In short, yes. There are different encoding by which computer can store data. Some machine are little endian some are big endian.
For, floating point number you can refer,
IEEE floating point

In short no. But you can change the code to almost work.
float a;
scanf("%f",&a);
However .3 can never be stored exactly in a float.
There is also a decimal type, a decimal based float (as opposed to the binary based one). It can store 0.3 exactly (and all other numbers you can type, up to its precision). But you can still not store 1/3 (you would need a fraction store to store that precisely). Or π ( you need a symbol store to store that). However you don't always need to be precise.

Related

How to check whether a hexadecimal number(%x) starts with a certain number or not in C?

I'm working on an operating system related project now and there is one step which requires to check whether a hexadecimal number starts with 3 or not, using C.
Currently my idea is to convert that hexadecimal number into a string and check the initial character but just cannot find out any documentation for doing that. Anybody has any idea? Maybe just a hint.
There are lots of methods to convert a number to a hex string (sprintf comes to mind; How can I convert an integer to a hexadecimal string in C? list a few more) – but, why should you?
A full hex number is formed by converting each nibble (4 bits) to a hexadecimal 'digit'. To get just the first, you can divide your value by 16 until you have reached the final (= 'first', in the left-to-right notation common for both decimal and hexadecimal values) digit. If that's a 3 you are done.
Assuming value is an unsigned number:
while (value > 15)
value >>= 4;
and then check if value == 3.
Your idea is not bad, you can use sprintf, it functions like printf/fprintf but instead of printing
on screen (or to be more precise: writing into a FILE* buffer), it stores the contents in a char buffer.
char value[16]; // more than enough space for 4 byte values
int reg = 0x3eef;
sprintf(value, "%x", reg);
if(value[0] == '3')
printf("The hexadecimal number 0x%s starts with a 3.\n", value);

Why cant I enter a number with decimal point in scanf? in C

I'm writing a simple C program to classfiy distances into certain ranges such as short long or medium
I understand that C will cancel out numbers after the decimal point to store as an int.
So that confuses me that why can't I type in a number such as 7.5 during scanf? as that will leads me to error.
Why can't it just read in as 7 into my scanf?
Is it because a keystroke of "." simply couldnt be accepted in declaring an int variable?
Why is it exactly?
I guess you mean 7.5 rather than 7+.+5.
This is just the way the scanf function works. When you specify %d, it means "Read digits of an integer". When you specify %f,it means "Read floating point value". The documentation for scanf gives the full detail about what is read and what stops.
If you want to read values with decimals and ignore the decimal, you have many options:
Read a double and convert to int afterwards
Read an int and check for a following . ; read another int if you find one
don't use scanf; read a string and do your own parsing
etc.
Personally I'd prefer not to use scanf, it has unavoidable UB when reading integral or floating point values.

Interpreting a hex number as decimal

I have an embedded system running C-code which works pretty straightforwardly; it reads characters via a serial connection, interprets the received chars as hexadecimal numbers and depending on what was received, proceeds to do something else. However, there is one very special case where the chars received are decimal instead of hex. Since this case is very rare (kind of an error case of an error case), I don't wish to modify the actual character reception to decide whether to interpret the received value as dec or hex, but rather to add a quick algorithm into the case handling where I change the number into decimal.
What would you say is the fastest (as in most efficient processor-wise) way of doing this? Since the software is running on a small MCU, any C library functions are not an option since I don't wish to add any more unnecessary #include's, so a purely mathematical algorithm is what I'm searching for.
Just to be clear, I'm not asking the quickest way to do a basic hex-to-dec- conversion as in 0x45 -> dec 69, but what I want to do is to transform eg. 0x120 into decimal 120.
Thanks in advance!
EDIT: Sorry, I'll try to explain in more detail. The actual code is way too long, and I think pasting it here is unnecessary. So here's what happens:
First I read a received number from the serial line, let's say "25". Then I turn it into hex number, so I have a variable with the read value, let's say X = 0x25. This works already fine, and I don't want to do modifications to this. What I would like to do now in this very special case is just to change the interpretation of the variable so that instead of X == 0x25, X==25. Hexadecimal 0x25 turns into decimal 25. There has to be some kind of mathematical formula for such a change, without the need of any processor-specific instructions or library functions?
If I'm understanding correctly, you've already converted a stream of ASCII characters into a char/int variable, assuming them to be a stream of hex-digits. In some cases, they were actually a stream of decimal digits (e.g. you received 45 and, treating this as hex, got a variable with value 69 when -- in one special case -- you actuially want its value to be 45.
Assuming two-characters, (00-ff in general, but for "was meant to be decimal" we're talking 00-99) then:
int hexVal = GetHexStringFromSerialPort() ;
int decVal = 10*(hexVal >> 4) + (hexVal & 0x0f) ;
should do the trick. If you've got longer strings, you'll need to extend the concept further.
Just do a simple while loop like this, supposing onum and dnum are unsigned integers
dnum = 0;
while (onum) {
digit = onum & 0xF;
dnum = dnum*10 + digit;
onum >>= 4;
}
this supposes that onum is really of the form that you describe (no hexdigits that are >9). It just succs the least significant hexdigit out of your number and adds it to your decimal.
Checking if your string starts with 0x characters and removing them should do the trick.

String to double saving time conversion in c

I'm working on a benchmarking task for an operation (in C language under Linux) and in this operation we use a conversion from string to double a lot (using atof or sscanf functions) but the problem here is that they gave a relatively large time (145, 270 ns respectively) which is not suitable for the operation. So, Do you know any other conversion mechanism that save time?
I tried to use casting but it gave zero
double d;
char ch[] = "123.154";
d = *((double *) ch);
printf ("%lf\n", d); // result 0 (compiled using gcc)
Regards
atof() and sscanf() are generic methods that accept a huge variety of formats. If you know that the floating point values follow a certain pattern, you can try to optimize the conversion for the expected format. ie. no need to support (+-), no need to support Inf, Nan, or sci-notation (1.3e43) etc.
One can make a look up table that converts 3 characters at once from strings:
table[a*256+b*16+c] = a*100+b*10+c; where one simply concatenates the 4 LSB bits of e.g. string "432"; the hex value of the index would be then 0x432 and the content would be 432.
Casting means changing the interpretation of some binary data. Doubles or floats and integers are not binary compatible (except for the value of (+) 0). However the following cast works to check, if three first characters in a strings are numbers:
char num[]="123.123";
if ((*((int*)num) & 0x00f0f0f0) == 0x00303030) // can use faster conversion
// this means interpreting the pointer to string as a pointer to integer
// and then referencing the contents of the memory _as_ integer (+ some bitmasking)
Further, if the set of floating points is relatively small, or some particular value is very frequent, one might trade space for speed and opt for a hash table. If hash table has a match, one can compare the strings 4 or 8 bytes in parallel to verify (or skip that part, if the input is known to be valid). One can also combine these techniques by hashing the first 4 characters for an initial guess and continue from that next 4 characters at a time.
double d;
char ch[] = "123.154";
d = atof(ch);
printf ("%f\n", d);
Or:
printf ("%s\n", ch);

C Compatibility Between Integers and Characters

How does C handle converting between integers and characters? Say you've declared an integer variable and ask the user for a number but they input a string instead. What would happen?
The user input is treated as a string that needs to be converted to an int using atoi or another conversion function. Atoi will return 0 if the string cannot be interptreted as a number because it contains letters or other non-numeric characters.
You can read a bit more at the atoi documentation on MSDN - http://msdn.microsoft.com/en-us/library/yd5xkb5c(VS.80).aspx
Uh?
You always input a string. Then you parse convert this string to number, with various ways (asking again, taking a default value, etc.) of handling various errors (overflow, incorrect chars, etc.).
Another thing to note is that in C, characters and integers are "compatible" to some degree. Any character can be assigned to an int. The reverse also works, but you'll lose information if the integer value doesn't fit into a char.
char foo = 'a'; // The ascii value representation for lower-case 'a' is 97
int bar = foo; // bar now contains the value 97
bar = 255; // 255 is 0x000000ff in hexadecimal
foo = bar; // foo now contains -1 (0xff)
unsigned char foo2 = foo; // foo now contains 255 (0xff)
As other people have noted, the data is normally entered as a string -- the only question is which function is used for doing the reading. If you're using a GUI, the function may already deal with conversion to integer and reporting errors and so in an appropriate manner. If you're working with Standard C, it is generally easier to read the value into a string (perhaps with fgets() and then convert. Although atoi() can be used, it is seldom the best choice; the trouble is determining whether the conversion succeeded (and produced zero because the user entered a legitimate representation of zero) or not.
Generally, use strtol() or one of its relatives (strtoul(), strtoll(), strtoull()); for converting floating point numbers, use strtod() or a similar function. The advantage of the integer conversion routines include:
optional base selection (for example, base 10, or base 10 - hex, or base 8 - octal, or any of the above using standard C conventions (007 for octal, 0x07 for hex, 7 for decimal).
optional error detection (by knowing where the conversion stopped).
The place I go for many of these function specifications (when I don't look at my copy of the actual C standard) is the POSIX web site (which includes C99 functions). It is Unix-centric rather than Windows-centric.
The program would crash, you need to call atoi function.

Resources