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...
Related
I am trying to change a string within a loop to be able to save my images with a changing variable. Code snippet is as follows:
for (frames=1; frames<=10; frames++)
{
char* Filename = "NEWIMAGE";
int Save_Img = is_SaveImageMemEx (hCam, Filename, pMem, memID,
IS_IMG_PNG, 100);
printf("Status Save %d\n",Save_Img);
}
What I want to do is put a variable that changes with the loop counter inside Filename so my saved file changes name with every iteration.
Any help would be great.
Create a file name string with sprintf and use the %d format conversion specifier for an int:
char filename[32];
sprintf(filename, "NEWIMAGE-%d", frames);
sprintf works just like printf, but "prints" to a string instead of stdout.
If you declared frames as an unsigned int, use %u. If it is a size_t use %zu. For details see your friendly printf manual page, which will tell you how you can for example zero pad the number.
Be sure that the character array you write to is large enough to hold the longest output plus an extra '\0' character. In your particular case NEWIMAGE-10 + 1 means 11 + 1 = 12 characters is enough, but 32 is future-proof for some time.
If you want to program like a pro, look at the snprintf and asnprintf functions, which can limit or allocate the memory written to, respectively.
You can use sprintf to create a formatting string:
char Filename[50];
sprintf(Filename, "NEWIMAGE%d", frames);
I am modifying airodump-ng to build a custom application.
I need the output in this format
{AP Mac 1, Station Mac 1},{AP Mac 2, Station Mac 2},...............
To do this I traverse through struct ST_INFO and using multiple strcat calls I generate an array in the above format.
The problem arises when the MAC address contains preceding zeros and this results in data corruption
eg: 0A1B23443311 is saved as A1B23443311
eg: 001B3311ff22 is saved as 1B3311ff22 ( The 0s have been ignored)
What should I do so that data is saved properly when MAC address contains preceding zeros?
The final array is written to a file.
Update: Printing leading 0's in C?
When I tried to print the MAC address the results were the same as given in the above examples but when I used %02x (I learned about it from above link) the problem was solved when I want to print.
Since, I want to save the contents to an array, is there any trick like the %02x for printf.
The struct ST_INFO contains unsigned char st_mac[6] (MAC address is stored in hex format) and my final array is also unsigned char array.
There are multiple ways to do, but if you're using snprintf() or one of its relatives, the %02x (or maybe %02X, or %.2x or %.2X) formats will be useful. For example:
const unsigned char *st_mac = st_info_struct.st_mac;
unsigned char buffer[13];
for (int i = 0; i < 6; i++)
sprintf(&buffer[2*i], "%.2X", st_mac[i]);
(Usually, using snprintf() is a good idea; here, it is unnecessary overkill, though it would not be wrong.)
You should not be using multiple strcat() calls to build up the string. That leads to a quadratic algorithm. If the strings are long (say kilobytes or more), this begins to matter. You also shouldn't be using strcat() because you need to know how long everything is (the string you've created so far, and the string you're adding to it) so that you can ensure you don't overflow your storage space.
if there is a fixed length for all the addresses, just check the length before appending it. If the
length < fixed_length , append difference between the length's number of zeroes.
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.
I am currently working with parsing some MAC addresses. I am given an output that does not include leading zeros (like so).
char* host = "0:25:25:0:25:25";
and I would like to format it like so
char* host = "00:25:25:00:25:25";
What would be the easiest way to go about this?
For those wondering, I am using the libpcap library.
I may be missing something in the question. Assuming you know it is a valid MAC, and the input string is thus parsable, have you considered something as simple as:
char* host1 = "0:25:25:0:AB:25";
char *host2 = "0:1:02:3:0a:B";
char result[19];
int a,b,c,d,e,f;
// the question sample
if (sscanf(host1, "%x:%x:%x:%x:%x:%x", &a,&b,&c,&d,&e, &f) == 6)
sprintf(result, "%02X:%02X:%02X:%02X:%02X:%02X", a,b,c,d,e,f);
printf("host1: %s\n", result);
// a more daunting sample
if (sscanf(host2, "%x:%x:%x:%x:%x:%x", &a,&b,&c,&d,&e, &f) == 6)
sprintf(result, "%02X:%02X:%02X:%02X:%02X:%02X", a,b,c,d,e,f);
printf("host2: %s\n", result);
Output
host1: 00:25:25:00:AB:25
host2: 00:01:02:03:0A:0B
Obviously for the ultra-paranoid you would want to make sure a-f are all < 255, which is probably preferable. The fundamental reasons I prefer this where performance isn't a critical issue are the many things you may not be considering in your question. It handles all of
Lead values of "n:", where n is any hex digit; not just zero. Examples: "5:", "0:"
Mid values of ":n:", again under the same conditions as (1) above. Examples: ":A:", ":0:"
Tail values of ":n". once more, under the same conditions as (1) above. Examples: ":b", ":0"
Hex-digit agnostic when reading; it works with both upper and lower case digit chars.
Most important, does nothing (except upper-case the hex values) if your input string is already properly formatted.
Roughly like this:
Allocate an output string to hold the reformatted MAC address.
Iterate over the input string and use strtok with : delimiter. In each iteration convert the beginning of the string (2 bytes) into a numerical value (e.g., with atoi). If the result < 16 (i.e., < 0x10), set "0" into the output string at current position and the result in hex at the following position; otherwise copy the 2 bytes of input string. Append : to the output string. Continue till end of the input.
I am having trouble accepting input from a text file. My program is supposed to read in a string specified by the user and the length of that string is determined at runtime. It works fine when the user is running the program (manually inputting the values) but when I run my teacher's text file, it runs into an infinite loop.
For this example, it fails when I am taking in 4 characters and his input in his file is "ABCDy". "ABCD" is what I am supposed to be reading in and 'y' is supposed to be used later to know that I should restart the game. Instead when I used scanf to read in "ABCD", it also reads in the 'y'. Is there a way to get around this using scanf, assuming I won't know how long the string should be until runtime?
Normally, you'd use something like "%4c" or "%4s" to read a maximum of 4 characters (the difference is that "%4c" reads the next 4 characters, regardless, while "%4s" skips leading whitespace and stops at a whitespace if there is one).
To specify the length at run-time, however, you have to get a bit trickier since you can't use a string literal with "4" embedded in it. One alternative is to use sprintf to create the string you'll pass to scanf:
char buffer[128];
sprintf(buffer, "%%%dc", max_length);
scanf(buffer, your_string);
I should probably add: with printf you can specify the width or precision of a field dynamically by putting an asterisk (*) in the format string, and passing a variable in the appropriate position to specify the width/precision:
int width = 10;
int precision = 7;
double value = 12.345678910;
printf("%*.*f", width, precision, value);
Given that printf and scanf format strings are quite similar, one might think the same would work with scanf. Unfortunately, this is not the case--with scanf an asterisk in the conversion specification indicates a value that should be scanned, but not converted. That is to say, something that must be present in the input, but its value won't be placed in any variable.
Try
scanf("%4s", str)
You can also use fread, where you can set a read limit:
char string[5]={0};
if( fread(string,(sizeof string)-1,1,stdin) )
printf("\nfull readed: %s",string);
else
puts("error");
You might consider simply looping over calls to getc().