Reading from a buffer word by word in c - c

I have a Buffer received as a result of recvfrom(). lets say,
char buffer[12] = "Hello 1";
I want to separate Hello and 1 and store them in different buffers so that one buffer has "Hello" in it and other buffer or an int variable has "1" stored in it.
In other words I want to separate contents of a buffer on the basis of spaces. How can this be done?
I tried:
int number;
char buff[7];
sscanf (buffer,"%s %d",buff,number);
Will this approach work?

If there are only 2 words your idea will work. But there is a small error in your code.
Change the sscanf this way
sscanf (buffer,"%s %d",buff,&number);

This approach works but you need to change to change your sscanf to:
sscanf (buffer,"%s %d",buff,&number);
The %d expects an int* and you are sending an int.

Looks like you want strtok, it can do exactly that. But make sure your string is NULL-terminated, recv and other socket functions don't do that for you and the standard C string functions do expect NULL-termination.

Related

How to store CHAR array to string MAC ADDRESS

I have a function that returns a unsigned char chMAC[6]; which is the mac address and i print it out as
printf("Mac: %x",chMAC[0]);
printf("%x",chMAC[1]);
printf("%x",chMAC[2]);
printf("%x",chMAC[3]);
printf("%x",chMAC[4]);
printf("%x\n",chMAC[5]);
And i get an output as Mac: B827E82D398E which is the actual mac address, but now i need to get that value as a string to pass to a sql parameter and i don't know how, since i need to add : in between. such as Mac: B8:27:E8:2D:39:8E
i bet this is easy, but i am still learning C.
You probably want all the bytes to be displayed as two characters:
%2x
but with a leading 0 instead of space:
%02x
You can string this all together in one printf call
printf("Mac: %02X:%02X:%02X:%02X:%02X:%02X\n"
, chMAC[0], chMAC[1], chMAC[2], chMAC[3], chMAC[4], chMAC[5]);
If you want the text to go to a sting buffer instead of stdout do this:
char buffer[32];
snprintf(buffer, sizeof(buffer)
, "Mac: %02X:%02X:%02X:%02X:%02X:%02X\n"
, chMAC[0], chMAC[1], chMAC[2], chMAC[3], chMAC[4], chMAC[5]);
You have all the pieces there, you just need to string them into the right order. Instead of using 6 separate printf() statements, pull it into one statement with all the formatting:
printf("Mac: %02X:%02X:%02X:%02X:%02X:%02X\n",
chMAC[0], chMAC[1], chMAC[2], chMAC[3], chMAC[4], chMAC[5]);
The "02" in the "%02X" formatting statements will put a leading zero if the value is <15; the capital X will make the alphabetic Hex digits into capitals (which is the usual convention when passing MAC addresses).
To send the resulting string to a buffer instead of to stdout, call sprintf (or even better, snprintf) with the same formatting string.
char mac_str[24];
snprintf(mac_str, sizeof(mac_str), "Mac: %02X:%02X:%02X:%02X:%02X:%02X\n",
chMAC[0], chMAC[1], chMAC[2], chMAC[3], chMAC[4], chMAC[5]);
why all the separate calls?
newlength = sprintf(mac, '%x:%x:%x:%x:%x:%x\n', chMAC[1], etc....)
You can have multiple %whatever format characters in a single printf/sprintf call...

Printf a buffer of char with length in C

I have a buffer which I receive through a serial port. When I receive a certain character, I know a full line has arrived, and I want to print it with printf method. But each line has a different length value, and when I just go with:
printf("%s", buffer);
I'm printing the line plus additional chars belonging to the former line (if it was longer than the current one).
I read here that it is possible, at least in C++, to tell how much chars you want to read given a %s, but it has no examples and I don't know how to do it in C. Any help?
I think I have three solutions:
printing char by char with a for loop
using the termination character
or using .*
QUESTION IS: Which one is faster? Because I'm working on a microchip PIC and I want it to happen as fast as possible
You can either add a null character after your termination character, and your printf will work, or you can add a '.*' in your printf statement and provide the length
printf("%.*s",len,buf);
In C++ you would probably use the std::string and the std::cout instead, like this:
std::cout << std::string(buf,len);
If all you want is the fastest speed and no formatting -- then use
fwrite(buf,1,len,stdout);
The string you have is not null-terminated, so, printf (and any other C string function) cannot determine its length, thus it will continue to write the characters it finds there until it stumbles upon a null character that happens to be there.
To solve your problem you can either:
use fwrite over stdout:
fwrite(buffer, buffer_length, 1, stdout);
This works because fwrite is not thought for printing just strings, but any kind of data, so it doesn't look for a terminating null character, but accepts the length of the data to be written as a parameter;
null-terminate your buffer manually before printing:
buffer[buffer_length]=0;
printf("%s", buffer); /* or, slightly more efficient: fputs(buffer, stdout); */
This could be a better idea if you have to do any other string processing over buffer, that will now be null-terminated and so manageable by normal C string processing functions.
Once you've identified the end of the line, you must append a '\0' character to the end of the buffer before sending it to printf.
You can put a NUL (0x0) in the buffer after receiving the last character.
buffer[i] = 0;

String format works in fprintf but doesn't work in sprintf, gives segmentation fault

fprintf(fp,"IP: %d: %.*s\n",
ip,
strstr(strstr(p->data, "User-Agent:"),"\n") - strstr(p->data, "User-Agent:"),
strstr(p->data, "User-Agent: ") );
fclose(fp);
Hi All, as you can see, in the above statement, I am trying to write off just the User Agent header from a char pointer which contains the entire http packet data. The thing is, After fiddling with the string format, I came up with this %.*s format which lets me, dynamically select the number of characters to be printed to the file, and then prints them. What the code is basically doing is, first, it's printing an int, then the number of chars from the occurrence of "User-Agent:" to the very next occurrence new line character is passed, and that amount of chars are then passes starting at where the "User-Agent:" starts, from the entire packet data string. I know it's all pretty messy, but it's working fine. Except that it's not working in sprintf.
Please save all my hard word! Any help is appreciated!
char *stat;
sprintf(stat,"%.*s\0",
strstr(strstr(p->data, "User-Agent:"),"\n") - strstr(p->data, "User-Agent:"),
strstr(p->data, "User-Agent: ")) ;
You are not allocating memory for stat. Try
char *stat = malloc(MAXLEN);
snprintf(stat, MAXLEN, ...);
^ ^
When you use sprintf, you need an array of characters to write into. You're writing to an uninitialized pointer.
Try this instead:
char stat[200];
sprintf(stat, etc...
Well, you are trying to write the data into uninitialized unallocated random memory location. Now that can't possibly work.
Either do:
char stat[SUFFICIENTLY_LARGE_NUMBER];
snprintf(stat, SUFFICIENTLY_LARGE_NUMBER, ...);
or:
char *stat = malloc(SUFFICIENTLY_LARGE_NUMBER);
snprintf(stat, SUFFICIENTLY_LARGE_NUMBER, ...);
and make sure "SUFFICIENTLY_LARGE_NUMBER" is enough bytes that the string fits in and not unnecessarily huge.
PS: snprintf, because your format does not include length limits. If it does, sprintf is OK, but never ever use sprintf with unlimited %s. Your %.*s, while formally limited, is not enough, because the expression will happily return more than the size of the allocated buffer, so you need another check to avoid overruning it.

How to convert int to char/string and vice versa in linux(gcc)?

I want to know the method of converting an integer into char/string and vice-versa also.
I have already used sprintf(&charvar,"%d",&intvar) but it produces wrong output, possibly garbage.
i have also heard atoi() in gcc has bugs.Reference:GCC atoi bug
What is the other method to convert string/char back to int ?
Actually i want to send an integer from one machine to another using SOCK_STREAM .
//EDIT : I forgot to tell that sprintf() does conversion and returns positive value.
If you want to send an integer to another machine you can send it as binary data, just by sending the intvar directly to the stream, you don't have to convert it to a char first. That will only introduce problems with knowing the length of the data as different values generate different lengths of strings.
Please read the manual of 'sprintf' and 'sscanf', and maybe their safer versions are proper for you.
Remove the ampersand before intvar:
sprintf(&charvar,"%d",intvar)
Two notes:
Here, I assume that &charvar is of correct type, which it probably isn't.
Even though it might not make much difference here, it's a good to get into the habit of using snprintf in preference to sprintf.
Here's some example code:
int intvar = ...;
char str[16];
snprintf(str, sizeof(str), "%d", intvar);
You cannot sprintf to a variable. You need a buffer for it, because of possible several digits and the trailing zero. Moreover, the argument should be the int variable, not its address.
Example:
char buffer[256];
int i = 42;
sprintf(buffer, "%d", i);
(buffer will be filled with '4', '2' and trailing '\0').
your sprintf is wrong.You should write sprintf(string,"%d",integer);
If you want to send an integer over the network and thats why you want to convert it into string have a look at htons
with these functions you can convert an integer to network format and avoid different endianness problems!
If you just want to convert it to bytes you can do something like this:
char buf[4];
memcpy(buf,&integer,4);
If you want your string to have the value of the int then you should use sprintf.

Printing an array of u_chars

I have an array of u_chars and I want to print it using printf. I don't know the size of the array:
u_char *ip_p;
printf("%s", ip_p); // EXC_BAD_ACCESS D:<
I want to print this. How can I do this?
That can't be done. A pointer doesn't magically contain information about the size of the data pointed to.
If there's no convention (a terminator byte, or a length encoded somewhere), you can't know how much data is valid, and thus how much to print.
If you don't know the size, how do you expect printf to know? Fix your code to pass the size as an additional argument. Then you can use:
printf("%.*s", size, buf);
However it looks like your data might not be text but binary. If so, I question the value of printing it with printf...
If ip_p is NUL terminated, your code works. Looking the comment in your code fragment I would say it isn't terminated...
If you don't know the size of the data how can you hope to use it? The size must have been available somewhere otherwise how did it get put there!? You must either know the size or have a sentinel value such as a nul character.
If it is not nul terminated, then "%s" is an inappropriate format specifier. Also if the u_char values are not all printable characters, you should not use %s or even %c. You might use %c and substitute non-printing characters with another.

Resources