I need help with sscanf.
I have a data file. I read it line by line.
One line is look like this: 23,13,45;
I want to read the integers.
I try this code:
unsigned char a,b,c;
sscanf(line,"%d,%d,%d;",&a,&b,&c);
But this is not working, only the first number read, the others is 0.
This is because %d expects a pointer to a 4-byte integer, and you are passing a pointer to a 1-byte char. Because variables a, b and c are stored in the order of decreasing memory addresses, sscanf first fills a with 23, at the same time filling 3 other bytes of stack memory with zeros (this is a memory violation, BTW). Then it fills b with 13, also filling a and two other bytes with zeros. In the end it fills c with 45, also filling a and b and one other byte with zeros. This way you end up with zeros in both b and a, and an expected value only in c.
Of course this is only one possible scenario of what can happen, as it depends on the architecture and compiler.
A proper way to read 4 integers would be to use int instead of unsigned char, or change the format specifier.
Correct format specifier for unsigned char is %hhu.
Other than that I don't see any problem as long as line does contain the string in the format you expect.
Related
in pure and portable c.
So I am having trouble casting what has to be a variable, from a variable. char *nib to int hex. The idea being I had a char *nib ="ab"; or "0xab" or anything that directly represents two characters as a char *. then casting it as a integer. and writing it to a file to get a one to one write. so I start with char *nib="0xab"; then I write it as a int presumably, and to a hexdump or edit and the result is just ab.
I've been able to do this as a constant directly declaring... but the nib is always static.
this has to be a one to one starting with a two char string or nib. Not converting anything, purly casting.
So can you write it directly to a file without converting it? three look up tables seems like a bit much for a value what has the name length
There is no way to cast 2 characters (2 bytes) into one byte because cast does not change binary representation of the value.
The closest you can get to casting string that looks like hex to some value that will show something similar is use 0-15 characters via escape sequence like char* nib = "\x0A\x0B" and cast ( *((short*)nib)) that to 2-byte value (0x0A0B in this case) and store that to a file (I'm not sure if there is portable integer type of 2 bytes - short often is 2 bytes wide but does not have to be 2 bytes). Unfortunately I don't think there is a portable way to store 2 byte integer value to a file as different architectures may have different byte order.
Writing string value character by character is likely safest approach. Or convert string to int a usual way and use your own read/write code for integers to ensure portability.
please tell me if I am wrong, if a number is stored as a character it will contain 1 byte per character of the number(not 4 bytes)?
for example if I make an int variable of the number 8 and a char variable of '8' the int variable will have consumed more memory?
and if I create an int variable as the number 12345 and a character array of "12345" the character array will have consumed more memory?
and in text files if numbers are stored are they considered as integers or characters?
thank you.
Yes, all of your answers are correct.
int will always take up sizeof(int) bytes, 8(int) assuming 32-bit int it will take 4 bytes, whereas 8(char) will take up one byte.
The way to think about your last question IMO is that data is stored as bytes. char and int are way of interpreting bytes, so in text files you write bytes, but if you want to write human-readable "8" into a text file, you must write this in some encoding, such as ASCII where bytes correspond to human-readable characters. So, to write "8" you would need to write the byte 0x38 (ASCII value of 8).
So, in files you have data, not int or chars.
When we consider the memory location for an int or for a char we think as a whole. Integers are commonly stored using a word of memory, which is 4 bytes or 32 bits, so integers from 0 up to 4,294,967,295 (232 - 1) can be stored in an int variable. As we need total 32 bits (32/8 = 4) hence we need 4 bytes for an int variable.
But to store a ascii character we need 7 bits. The ASCII table has 128 characters, with values from 0 through 127. Thus, 7 bits are sufficient to represent a character in ASCII; (However, most computers typically reserve 1 bits more, (i.e. 8 bits), for an ASCII character
And about your question:-
and if I create an int variable as the number 12345 and a character array of "12345" the character array will have consumed more memory?
Yes from the above definition it is true. In the first case(int value) it just need 4 bytes and for the second case it need total 5 bytes. The reason is in the first case 12345 is a single integer value and in the second case "12345" are total 5 ascii characters. Even in the second case, you actually need one more byte to hold the '\0' character as a part of a string (marks end of string).
When int is defined the memory would be allocated based on compiler option ( it can be 4 to 8 bytes). The number assigned to int is stored as is.
e.g int a = 86;
The number 86 would be stored at memory allocated for a.
When char is defined , there are numbers assigned to each character. When these character needs to be printed the same would print but when its stored in memory it would stored as number. These are called ASCII character, there are some more.
The allocation to store is 1Byte because with 1Byte you can represent 2^8 symbols.
if a number is stored as a character it will contain 1 byte per character of the number(not 4 bytes)? for example if I make an int variable of the number 8 and a char variable of '8' the int variable will have consumed more memory?
Yes, since it is guaranteed that (assuming 8-bit bytes):
sizeof(char) == 1
sizeof(int) >= 2
if I create an int variable as the number 12345 and a character array of "12345" the character array will have consumed more memory?
Correct. See the different between:
strlen("12345") == 5
sizeof(12345) >= 2
Of course, for small numbers like 7, it is not true:
strlen("7") == 1
sizeof(7) >= 2
in text files if numbers are stored are they considered as integers or characters?
To read any data (be it in a file or in a clay tablet!) you need to know its encoding.
If it is a text file, then typically the numbers will be encoded using characters, possibly in their decimal representation.
If it is a binary file, then you may find them written as they are stored in memory for a particular computer.
In short, it depends.
I have a uint64 value that I want to convert into a string because it has to be inserted as the payload of an HTTP POST request.
I've already tried many solutions (ltoa, this solution ) but my problem still remains.
My function is the following:
void check2(char* fingerprint, guint64 s_id) {
//stuff
char poststr[400] = "action=CheckFingerprint&sessionid=";
//convert s_id to, for example, char* myChar
strcat(poststr, myChar);
}
I want to convert s_id to char*. I've tried:
1) char ses[8]; ltoa(s_id,ses,10) but I have a segmentation fault;
2) char *buf; sprintf(buf, "%" PRIu64, s_id);
I'm working on a APIs, so I have seen that when this guint64 variable is printed, it has the following form:
JANUS_LOG(LOG_INFO, "Creating new session: %"SCNu64"\n", session_id);
sprintf is the right way to go with an unsigned 64 bit format specifier.
You'll need to allocate enough space for 16 hex digits and the null byte. Here I've allocated 20 bytes to accommodate a leading 0x as well and then I rounded it up to 20 for no good reason other than it feels better than 19.
char foo[20];
sprintf(foo, "0x%016" PRIx64, (uint64_t)numberToConvert);
will print the number in hex with leading 0x and leading zeros padded up to 16. You do not need the cast if numberToConvert is already a uint64_t
i have a uint64 value that i want to convert into char* because of it have to be inserted as payload of an HTTP POST request.
What you have is a fundamental misunderstanding.
To insert a text representation of your value into a document, you need to convert it to a sequence of characters, which is quite a different thing from a pointer to a character (char *). One of your options, which seems to be what you're really after, is to convert the value to a sequence of characters in the form of a C string -- that is, a null-terminated array of characters. You would then have or be able to obtain a pointer to the first character in the sequence.
That explains what's wrong with this attempted solution:
char *buf;
sprintf(buf, "%" PRIu64, s_id);
You are trying to write the string representation of your number into the array pointed-to by buf, but it doesn't point to one. Not having been initialized or assigned, its value is indeterminate.
Even if you your buf pointed to an array, it is essential that the array be long enough to accommodate all the digits of the value's decimal representation, plus a terminator. That's probably what's wrong with your other attempt:
char ses[8]; ltoa(s_id,ses,10)
An unsigned, 64-bit binary number may require up to 20 decimal digits, plus you need space for a terminator. The array you're providing is not nearly large enough, unless you can be confident that the actual values you're going to write will not exceed 9,999,999 (which is well within the range of a 32-bit integer).
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);
I'm reading in two 32 bit registers and trying to put it inside a string buffer using the following:
sprintf (buffer, "%s-%s", ((char*)(in32(REGISTER1))) , (char*)(in32(REGISTER2)));
Can the hex value read in from the registers not be typecast as a pointer to a char and be printed into the buffer as above?
As craig65535 implies in a comment above, the problem is most likely with this phrase:
the hex value read in from the registers
I doubt that you're reading in a hex value; rather, you're reading in an integer. If you want to store a hex representation of that integer in a string, you'd use the %X format specifier:
sprintf (buffer, "%08X-%08X", in32(REGISTER1), in32(REGISTER2));
(The 8 means "use a width of eight characters"; the 0 means "left-pad with zeroes if the value is such that the width is less than eight".)
The only way you could validly cast to char * is if the integer value in the register is actually a pointer to some memory location where you've stored a string; but that is clearly not the case here.
sprintf(buffer, "%08x-%08x", REGISTER1, REGISTER2);
-- that's assuming you want the register addresses in your buffer. If your intention is to read the contents of the registers, adjust accordingly. The point though is you cannot simply call a number a char* and get the number out of it, but sprintf() (and all printf-like functions) can convert value bases for you.
As the others answers suggest, you can convert your integer to a string hex representation with sprintf using %X.
But as you didn't said what compiler you use or what the length of integer or long is, you could get unexpected results.
On a 16bit controller sprintf (buffer, "%08X-%08X", in32(REGISTER1),in32(REGISTER2)); would fail.
This should work on the most plattforms, as sprintf assume long values as arguments, and the arguments are always casted to longs.
sprintf (buffer, "%08lX-%08lX", (long)in32(REGISTER1), (long)in32(REGISTER2));