Parsing string to long in C - c

I've written a server in python and the client in C.
The python server send i.e. "1 1000\n" to the C client.
The C function that recieves this string should parse it into two long int's.
void receive_job() {
char tmp_buffer[256];
long start, stop;
recv(sock, tmp_buffer, 255, 0);
/*
here I wonder how I can parse tmp_buffer to set start and stop values.
*/
}
I am not very proficient in C, so I would appreciate a comment on this.

Have a look at strtol() or strtoul(), depending on your concrete data type:
char end;
long x = strtol(tmp_buffer,&end,10);
long y = strtol(end+1,NULL,10);

Use strtol.
char data[] = "1 1000\n";
char *next, *err;
long a = strtol(data, &next, 10);
long b = strtol(next, &err, 10);

Look up sscanf manual page - but check the return value!

It is better to clear the tmp_buffer using memset before calling recv or at least to add a null byte in it. Otherwise it would contain garbage that you might parse if something got transmitted wrongly.

Related

breaking up a char array into a structure

In case someone gets this issue in the future I'll leave this up.
*Note This approach wasn't going to work when going from C client to C server. This would have only worked with the Java client to C server. So I had to abandoned this approach.
Ok, I've been fighting with C for too long now. I'm passing some info with UDP from a java client to a C server. I can get the info there, but I'm not sure how to break apart the message to store into a struct like so
struct __attribute__((__packed__)) clientMessage
{
short tml;
short rid;
char op;
char message[MAXBUFLEN-5];
};
I recieve the message like this
Where test is a char test[MAXBUFLEN-5];
if ((numbytes = recvfrom(sockfd, test, MAXBUFLEN-1, 0,
(struct sockaddr *)&their_addr, &addr_len)) == -1) {
perror("recvfrom");
exit(1);}
So, I need to take the message "7 2 1Yo" (two 2 byte shorts and a char followed by an unknown message length) and store it into it's appropriate parts in the struct. The message gets sent correctly, I just can't break it into the bits of info that I need. I'm currently attempting
memcpy(&cm.rid, &test, 2);
memcpy(&cm.tml, &test[1], 2);
memcpy(&cm.op, &test[4], 1);
memcpy(&cm.message, &test[5], MAXBUFLEN-5);
But my resutls end up being
Message: Yo
OP: 1Yo
RID: 7 1Yo
TML: 2 7 1Yo
it Should be
Message: Yo
OP: 1
RID: 2
TML: 7
I successfully get the message, but nothing else. I'm relatively new to C so forgive my ignorance. I'm guessing this is really easy but idk.
The first line should be memcpy(&cm.rid, &test[0], 2);, for the address is supposed to be the address of the first byte.
And the rest:
memcpy(&cm.tml, &test[2], 2); // you want to get the third and forth byte, begin with index 2.
memcpy(&cm.op, &test[4], 1); // the fifth byte, begin with index 4.
memcpy(&cm.message, &test[5], MAXBUFLEN-5); // the rest bytes.
If you are using a binary protocol, it would be better to use e.g. int16_t instead of short in the declaration of clientMessage because the size of short is not specified within the c standard.
To access the message stored in test you could do simply something like this:
struct clientMessage *cm = (struct clientMessage *) test;
You should also notice, that the endianness of network protocols is different from the endianness of a x86 and amd64 architecture, so instead of 42 you might recieve 10752.
To fix this you can use the ntohs() (Network TO Host Short) function to acces the tm and rid.
Use sscanf() for the first part and memcpy() for the text.
const char *message = "7 2 1Yo";
struct clientMessag cM;
int offset = 0;
int n;
n = sscanf(message, "%hd %hd %c%n", &cM.tml, &cM.rid, &cM.op, &offset);
size_t SuffixLength = strlen(&message[offset]);
if ((n != 3) || (SuffixLength >= sizeof(cM.message))) {
exit(1); // handle syntax error;
}
memcpy(cM.message, &message[offset], SuffixLength + 1);
// Additional field checks like IsOKOpCode(cM.op)
I avoided %s as it does not store whitespace into your message.
Error checking is always good to do. Recommend additional field checks.
BTW: its not clear if the cM.op field should be treat as text or a number. Does the OP want a 1 or '1' stored? The above assume text. Alternatively one could use "%hd%hd%hhd%n".
Since test contains the string "7 2 1Yo", you have to parse the string into the values you want. You can do this with sscanf():
char fmt[256];
snprintf(fmt, sizeof(fmt), "%%hd %%hd %%c%%%ds", MAXBUFLEN-5-1);
sscanf(test, fmt, &cm.rid, &cm.tml, &cm.op, cm.message);
In this code fragment above, we create a format string for the parsing. This is necessary to prevent sscanf() from scanning past the end of the message in the case that it is not \0 terminated. The result of the snprintf() call with a MAXBUFLEN of 128 is:
"%hd %hd %c%122s"
Which tells sscanf() to scan for two short decimal numbers, a char, and a string no longer than 122 characters.

Convert string to long long C?

How can I convert a string to a long long in C?
I've got
char* example = "123";
I'd like to convert example to a long long so I'd want something like
long long n = example;
How can I do this?
Use the function strtoll:
#include <stdlib.h>
#include <errno.h>
char const * example = "123";
char * e;
errno = 0;
long long int n = strtoll(example, &e, 0);
if (*e != 0 || errno != 0) { /* error, don't use n! */ }
In fact, e will point to the next character after the converted sequence, so you can do even more sophisticated parsing with this. As it stands, we just check that the entire sequence has been converted. You can also inspect errno to see if an overflow occurred. See the manual for details.
(For historical interest: long long int and strtoll were introduced in C99. They're not available in C89/90. Equivalent functions strtol / strtoul / strtod exist, though.)

C Programming: Convert Hex Int to Char*

My question is how I would go about converting something like:
int i = 0x11111111;
to a character pointer? I tried using the itoa() function but it gave me a floating-point exception.
itoa is non-standard. Stay away.
One possibility is to use sprintf and the proper format specifier for hexa i.e. x and do:
char str[ BIG_ENOUGH + 1 ];
sprintf(str,"%x",value);
However, the problem with this computing the size of the value array. You have to do with some guesses and FAQ 12.21 is a good starting point.
The number of characters required to represent a number in any base b can be approximated by the following formula:
⌈logb(n + 1)⌉
Add a couple more to hold the 0x, if need be, and then your BIG_ENOUGH is ready.
char buffer[20];
Then:
sprintf(buffer, "%x", i);
Or:
itoa(i, buffer, 16);
Character pointer to buffer can be buffer itself (but it is const) or other variable:
char *p = buffer;
Using the sprintf() function to convert an integer to hexadecimal should accomplish your task.
Here is an example:
int i = 0x11111111;
char szHexPrintBuf[10];
int ret_code = 0;
ret_code = sprintf(szHexPrintBuf, "%x", i);
if(0 > ret_code)
{
something-bad-happend();
}
Using the sprintf() function like this -- sprintf(charBuffer, "%x", i);
-- I think will work very well.

Parse a version number given as a string into 4 distinct integers using in c

I have a version number returned as a string which looks something like "6.4.12.9", four numbers, each separated by a "."
What I would like to do is to parse the string into 4 distinct integers. Giving me
int1 = 6
int2 = 4
int3 = 12
int4 = 9
I'd normally use a regex for this but that option isn't available to me using C.
You can use sscanf
int a,b,c,d;
const char *version = "1.6.3.1";
if(sscanf(version,"%d.%d.%d.%d",&a,&b,&c,&d) != 4) {
//error parsing
} else {
//ok, use the integers a,b,c,d
}
If you're on a POSIX system, and limiting yourself to POSIX is okay, you can use the POSIX standard regular expression library by doing:
#include <regex.h>
then read the relevant manual page for the API. I would not recommend a regexp-solution for this problem to begin with, but I wanted to point out for clarity that regular expressions are often available in C. Do note that this is not "standard C", so you can't use it everywhere, only on POSIX (i.e. "Unix-like") systems.
You could used strtok() for this (followed by strtol()), just make sure you're aware of the semantics of strtok(), they're slightly unusual.
You could also use sscanf().
One solution using strtoul.
int main (int argc, char const* argv[])
{
char ver[] = "6.4.12.9";
char *next = ver;
int v[4], i;
for(i = 0; i < 4; i++, next++)
v[i] = strtoul(next, &next, 10);
return 0;
}
You can use strtoul() to parse the string and get a pointer to the first non-numeric character. Another solution would be tokenizing the string using strtok() and then using strtoul() or atoi() to get an integer.
If none of them will exceed 255, inet_pton will parse it nicely for you. :-)

C - casting int to char and append char to char

I am making my first parallel application, but I am stuck with basics of C. I need to know, how to cast int to char and then how to append one char to another.
It you could help me please, i would be glad. Thank you.
You can use itoa function to convert the integer to a string.
You can use strcat function to append characters in a string at the end of another string.
If you want to convert a integer to a character, just do the following -
int a = 65;
char c = (char) a;
Note that since characters are smaller in size than integer, this casting may cause a loss of data. It's better to declare the character variable as unsigned in this case (though you may still lose data).
To do a light reading about type conversion, go here.
If you are still having trouble, comment on this answer.
Edit
Go here for a more suitable example of joining characters.
Also some more useful link is given below -
http://www.cplusplus.com/reference/clibrary/cstring/strncat/
http://www.cplusplus.com/reference/clibrary/cstring/strcat/
Second Edit
char msg[200];
int msgLength;
char rankString[200];
........... // Your message has arrived
msgLength = strlen(msg);
itoa(rank, rankString, 10); // I have assumed rank is the integer variable containing the rank id
strncat( msg, rankString, (200 - msgLength) ); // msg now contains previous msg + id
// You may loose some portion of id if message length + id string length is greater than 200
Third Edit
Go to this link. Here you will find an implementation of itoa. Use that instead.
Casting int to char is done simply by assigning with the type in parenthesis:
int i = 65535;
char c = (char)i;
Note: I thought that you might be losing data (as in the example), because the type sizes are different.
Appending characters to characters cannot be done (unless you mean arithmetics, then it's simple operators). You need to use strings, AKA arrays of characters, and <string.h> functions like strcat or sprintf.
Casting int to char involves losing data and the compiler will probably warn you.
Extracting a particular byte from an int sounds more reasonable and can be done like this:
number & 0x000000ff; /* first byte */
(number & 0x0000ff00) >> 8; /* second byte */
(number & 0x00ff0000) >> 16; /* third byte */
(number & 0xff000000) >> 24; /* fourth byte */
int myInt = 65;
char myChar = (char)myInt; // myChar should now be the letter A
char[20] myString = {0}; // make an empty string.
myString[0] = myChar;
myString[1] = myChar; // Now myString is "AA"
This should all be found in any intro to C book, or by some basic online searching.
int i = 100;
char c = (char)i;
There is no way to append one char to another. But you can create an array of chars and use it.

Resources