I am writing a function which takes in the integer value and the pointer to a character.
the function converts the integer value into binary and stores it in the char pointer.
the char pointer is 16 bytes long.
Snippet of code:
void int2bin(u_int16_t addr_IP, char *Binary)
{
int count;
printf("IP1add = %d \n", Binary);
for (count = 0; count < 16; count++) {
if(addr_IP>0)
*(Binary + 15-count) = addr_IP & 0x1 ? '1':'0';
else
*(Binary + 15-count) = '0';
addr_IP>>=1;
}
}
int main(int argc, char *argv[])
{
u_int16_t senderIP_16[], u_int16_t receiverIP_16[];
char sender_IP_hi[16], sender_IP_low[16];
int2bin(senderIP_16[0], &sender_IP_hi);
int2bin(senderIP_16[1], &sender_IP_low);
}
In the first call to the function, it returns correct values. But in the second pass, the value of first pass is appended to the second pass, i.e length of sender_IP_low becomes 32.
How can I resolve this?
Thanks
It looks like you're printing sender_IP_low as a string, and since it is not null-terminated, the print routine continues to print the adjacent buffer, sender_IP_hi. And you're probably just lucky that the print routine finds a zero and stops before a segmentation fault.
One quick fix is:
void int2bin(u_int16_t addr_IP, char *Binary) {
...
Binary[16] = 0; // terminate the string before returning
}
...
char sender_IP_hi[17], sender_IP_low[17]; // +1 for null terminator
Although, there are a few other things that could be fixed in your implementation, I just wanted to focus on an answer to your original question.
If you are printing the arrays with printf():
void int2bin(u_int16_t addr_IP, char *Binary)
{
int count;
printf("IP1add = %d \n", Binary);
for (count = 0; count < 16; count++) {
if(addr_IP>0)
*(Binary + 15-count) = addr_IP & 0x1 ? '1':'0';
else
*(Binary + 15-count) = '0';
addr_IP>>=1;
}
// Put the NULL char in the last position
Binary[16] = '\0';
}
int main(int argc, char *argv[])
{
u_int16_t senderIP_16[], u_int16_t receiverIP_16[];
// One more char for storing the terminator character
char sender_IP_hi[17], sender_IP_low[17];
int2bin(senderIP_16[0], &sender_IP_hi);
int2bin(senderIP_16[1], &sender_IP_low);
}
Related
I typed these codes + I get a segmentation fault. I am trying to make my very own special version of strtol:
struct optional_int {int Value; char IsNull;};
struct optional_int StrToHex(char Str[]) {
const char Hex[0x10] = "0123456789ABCDEF";
unsigned int Chr = 0x00,i,j,Number = 0x00;
unsigned char IsNull, IsNegative;
if(Str[0x0] == '-') {
IsNegative = 0x1;
int N_C_Char = 0;
while( Str[N_C_Char] != '\0' ) {
Str[N_C_Char]=Str[N_C_Char+1];//right here
N_C_Char++;
}
}else{IsNegative=0;}
printf("%sfas", Str);
for(i = strlen(Str); i > 0; i--){
unsigned int Successes = 0x0;
for( j = 0; j < 0x10; j++ ) {
if( Str[Chr]==Hex[Chr]) {
Number+=((pow(0x10, i))*j);
Successes++;
}
}
if(Successes!=1) {
IsNull = 1;
}else{
IsNull = 0;
Number = 0;
}
Chr++;
}
if(IsNegative == 1) {
return (struct optional_int){ Number, IsNull};
}else{
return (struct optional_int){-Number, IsNull};
}
}
int main(int argc, const char *argv[]) {
printf("asdf %x\n", StrToHex("-535").Value);
}
Whenever I give it some negative numbers, it gave me a segmentation fault core dump but I have located the issue.
Ok, so I figured it out. The issue is indeed the string you pass to the function. When you write "-535" the string is allocated in the data section of the program and you are not allowed to write it. When the number is negative you try to modify that string by shifting the digits over the - sign. That's why it crashes on negative numbers only.
int main(int argc, const char *argv[]) {
char c[200];
strcpy(c, "-535");
printf("asdf %x\n", StrToHex(c).Value);
}
This snippet works for me in the main function. You will never be able to pass constant strings to the function or pointers that refer to this kind of strings:
char c[200] = "-535";
StrToHex(c);
will also crash.
You must provide a memory location where you have write permissions.
Another workaround to your issue would be to not change the string to delete the - but write your code to just ignore it :)
This is probably a really stupid question, but
I have an array of structs outside of int main
typedef struct{
char c;
int k;
}factor_t;
and I declared
factor_t *factors = malloc(INIT*sizeof(*factors));
where INIT is 10
After running my function, I have an array of structs each which holds a char, c, and integer, k - e.g., factors[5].c could hold "b" or "d" or "e" and factors[5].k could hold "3" or "33" or "333"
I need to somehow insert these into a string, but I can't seem to
strcat(destination,c or k);
they both give me pointer to integer errors, destination is a char*
How would I go about putting these into a string? I'm aiming to get a string that looks like
ck
ck
ck
that is, a pattern of "ck\n" per struct, where c = char and k = integer
I use strcat(destination, "\n"); for the \n and it works, but I can't do the same with c and k
Calculate the length of the string and output with that offset.
#include <stdio.h>
#include <string.h>
typedef struct{
char c;
int k;
}factor_t;
void struct_cat(char *str, factor_t f) {
sprintf(str + strlen(str), "%c%d", f.c, f.k);
}
int main(void) {
factor_t fac = {'b', 33};
char buf[100] = "hogehoge";
struct_cat(buf, fac);
puts(buf);
return 0;
}
strcat appends a copy of the source string to the destination string. It expects c to be a null terminated string not a single char
If you want to add a single char to an array that is larger than n and the null terminating char is at index n
destination[n] = c;
destination[n+1] = '\0;
you have to be certain that destination is large enough.
If you want to format print additional data to destination string, again make sure destination is large enough and do :
sprintf(destination + n, "%c%d\n", c, k);
Or if you know how that destination has m chars left :
snprintf(destination + n, m, "%c%d\n", c, k);
With this if you attempt to print more than m chars the extra ones will be discarded.
You can use sprintf to do so . -
size_t len=strlen(destination); // calculate before concatenation
sprintf(&destination[len], "%c%d\n", factors[5].c,factors[5].k); // string with newline
destination should be of type char *.
If you need separate this feature use function (like #MikeCAT). But use of snprintf() and strncat() does not allow to go beyond the array bounds:
void strncat_struct(char *buffer, size_t buffer_size, factor_t f)
{
char tmp_buf[32];
snprintf(tmp_buf, sizeof(tmp_buf), "%c, %d\n", f.c, f.k);
strncat(buffer, tmp_buf, buffer_size);
}
int32_t main(int32_t argc, char **argv)
{
//...
char buffer[256] = {0};
for(i = 0; i < INIT; i++) {
strncat_struct(buffer, sizeof(buffer), factors[i]);
}
//...
}
Without using additional function. It is theoretically faster, couse there is no need to calculate string length:
int32_t main(int32_t argc, char **argv)
{
//...
char buffer[256];
char *buf_ptr = buffer;
size_t buf_size = sizeof(buffer);
for(i = 0; i < INIT; i++) {
int32_t printed;
printed = snprintf(buf_ptr, buf_size, "%c, %d\n", factors[i].c, factors[i].k);
buf_ptr += printed;
buf_size -= printed;
}
//...
}
The code below tries to increment the last index in a string, eg: if label = "1_1_9", find_next_label (label ) will return "1_1_10".
This works. However, I also want to alter the original label, increment it as well. eg: if label = "1_1_9", find_next_label(label) will return "1_1_10" and during this procedure, label also becomes "1_1_10".
This code below is unable to do this. The result from main() function shows that label is still "1_1_9".
Could anyone help find where the problem is?
char * find_next_lable(char * label)
{
int length = strlen(label);
char * last_index = label + length - 1;
int num = atoi(last_index);
num = num + 1;
char * next_lable = malloc(sizeof(label));
strncpy(next_label, label, length-1);
*(next_label + length - 1) = '\0';
sprintf(next_label, "%s%d", next_label, num);
label = next_label;
return label;
}
int main()
{
char * s = malloc(6);
strcpy(s, "1_1_9");
char * n = find_next_label(s);
printf("%s\n", s);
printf("%s\n", n);
return 0;
}
The last_index() and atoi() code block assumes that the final number is only one digit long; clearly this is not very general. You could search for the last underscore instead, and convert a number from the character following that. Use strrchr() to look for the last underscore.
Also you must think a lot about buffer sizes and overruns, you should probably make the function accept the available buffer size as an additional argument especially if you want to modify the input. If you want that, there's of course no point in allocating additional space either, just return the input.
If you don't need to create a new string you can just do:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define MAX_LEN 20
int main()
{
char *s = malloc(MAX_LEN); /* You must have enough memory if the number of chars grows! */
char *n;
int i;
strcpy(s, "1_1_9");
printf("%s\n", s);
n = strrchr(s, '_'); /* find the last '_' */
n++; /* and move to the number */
i = atoi(n);
sprintf(n, "%d", i+1); /* write the new value instead of the old one */
printf("%s\n", s);
free(s);
return 0;
}
else you can have the function:
char * find_next_lable(char *label)
{
char *n, *next_lable = malloc(sizeof(MAX_LEN));
int i;
strcpy(next_lable, label);
n = strrchr(next_lable, '_');
n++;
i = atoi(n);
sprintf(n, "%d", i+1);
return next_lable;
}
The result from main() function shows that lable is still 1_1_9.
That's because you are not changing the dynamically allocated array pointed to by s in main. Instead, you allocate new memory in the function find_next_lable. Also,
sprintf(next_lable, "%s%d", next_lable, num);
won't work since %s conversion specifier means that sprintf will read from the buffer pointed to by next_lable till and including the terminating null byte.
You must allocate enough memory so as to contain the incremented integer part.
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
// make sure MAX is large enough to
// contain the modified string
#define MAX 20
void find_next_lable(char *label);
int main(void)
{
char *s = malloc(MAX);
strcpy(s, "1_1_90");
printf("%s\n", s);
find_next_lable(s);
printf("%s\n", s); // prints 1_1_91
free(s);
return 0;
}
void find_next_lable(char *label)
{
// strrchr returns a pointer to the last
// occurrence of the character _ in label
char *last_index = strrchr(label, '_');
if(last_index == NULL)
{
last_index = label;
}
else
{
last_index++;
}
int num = atoi(last_index);
num = num + 1;
sprintf(last_index, "%d", num);
}
I am trying to print out byte array as one byte at the time in hexadecimal format within for loop like this:
int my_function(void *data)
{
obuf = (str*)data;
int i;
for (i = 0; i < obuf->len; i++)
{
printf("%02X:", obuf->s[i]);
}
return 0;
}
str in this case is structure from Kamailio - review at http://www.asipto.com/pub/kamailio-devel-guide/#c05str
The expected output:
80:70:0F:80:00:00:96:00:1D:54:7D:7C:36:9D:1B:9A:20:BF:F9:68:E8:E8:E8:F8:68:98:E8:EE:E8:B4:7C:3C:34:74:74:64:74:69:2C:5A:3A:3A:3A:3A:3A:3A:32:24:43:AD:19:1D:1D:1D:1D:13:1D:1B:3B:60:AB:AB:AB:AB:AB:0A:BA:BA:BA:BA:B0:AB:AB:AB:AB:AB:0A:BA:BA:BA:BA:B9:3B:61:88:43:
What I am getting:
FFFFFF80:70:0F:FFFFFF80:00:00:FFFFFF96:00:1D:54:7D:7C:36:FFFFFF9D:1B:FFFFFF9A:20:FFFFFFBF:FFFFFFF9:68:FFFFFFE8:FFFFFFE8:FFFFFFE8:FFFFFFF8:68:FFFFFF98:FFFFFFE8:FFFFFFEE:FFFFFFE8:FFFFFFB4:7C:3C:34:74:74:64:74:69:2C:5A:3A:3A:3A:3A:3A:3A:32:24:43:FFFFFFAD:19:1D:1D:1D:1D:13:1D:1B:3B:60:FFFFFFAB:FFFFFFAB:FFFFFFAB:FFFFFFAB:FFFFFFAB:0A:FFFFFFBA:FFFFFFBA:FFFFFFBA:FFFFFFBA:FFFFFFB0:FFFFFFAB:FFFFFFAB:FFFFFFAB:FFFFFFAB:FFFFFFAB:0A:FFFFFFBA:FFFFFFBA:FFFFFFBA:FFFFFFBA:FFFFFFB9:3B:61:FFFFFF88:43:
Could someone please help me understand why there are some of bytes prefixed with FFFFFF and other aren't?
Thanks in advance
Looks like obuf->s[i] returns a signed value
You would need to cast it to a unsigned value to get rid of the FFF.. at start.
printf("%02X:", (unsigned char)(obuf->s[i]));
The problem appears with chars that have the most significant bit set (which are out of the proper pure ASCII set range 0-127). The key point is to consider chars as unsigned.
printf("%02X:", (unsigned char)(obuf->s[i]));
See this simple compilable repro C code:
#include <stdio.h>
#include <string.h>
struct _str {
char* s; /* pointer to the beginning of string (char array) */
int len; /* string length */
};
typedef struct _str str;
int my_function(void *data)
{
str* obuf;
int i;
obuf = (str*)data;
for (i = 0; i < obuf->len; i++) {
printf("%02X:", (unsigned char)(obuf->s[i]));
}
return 0;
}
int main(void)
{
char buf[2];
str s;
/* Test with ordinary ASCII string */
s.s = "Hello";
s.len = strlen(s.s);
my_function(&s);
printf("\n");
/* Test with char values with most significant bit set */
buf[0] = 0xF1;
buf[1] = 0x00;
s.s = buf;
s.len = 1;
my_function(&s);
return 0;
}
With MSVC, I get this output:
48:65:6C:6C:6F:
F1:
I'm relatively a beginner in programming in C and am getting super confused with arrays and pointers.
Basically what I'm trying to do is extend a string that contains binary to the designated length len; (i.e. len=8 for num[]=101 would produce "00000101").
Can someone help me understand what's wrong with this?
const char * extendBinary(char num[], int len) {
char *number = #
int length = len;
int difference;
if(strlen(*num)<len) {
difference = len-strlen(num);
while(difference>0)
{
&number = strcat("0", &number);
difference--;
}
}
return number;
}
Your problems start with your specification. If I understand you correctly, you want to have a function where you pass an array of characters and a length. The size of your array of input characters will be between 1 and len? However, your function has no way of knowing what the size of your array num is. If you wanted this to work, you would need to define your function as
const char * extendBinary(char *num, size_t num_len, int len);
so that your function doesn't overrun your buffer pointed to by num. Note that I replaced char num[] with char *num as this is the common mechanism for passing a pointer. You cant pass pointers to arrays and then dereference that pointer and get back the original type (that includes its size) -- that's just one thing that C doesn't let you do, so just use a normal pointer and a separate size variable.
Finally, you'll have to deal with memory allocation unless you want a memory leak. Thus, you could simply say that whom ever calls extendBinary should free it's return value when done with it.
const char * extendBinary(char *num, size_t num_len, int len) {
char *ret = malloc(len + 1);
int i;
memset(ret, '0', len);
ret[len] = 0;
strncpy(&ret[len - num_len], num, num_len);
return ret;
}
int main(void) {
char arr[] = {'1', '0', '1'};
const char *formatted = extendBinary(arr, sizeof(arr), 8);
printf("%s\n", formatted);
free(formatted);
return 0;
}
this is wrong.
strcat("0", &number);
A weird way to fix you code would be this:
char temp[32] = {};
...
...
while(difference>0)
{
strncat(temp, "0", 31 - strlen(temp));
difference--;
}
strncat(temp, num, 31 - strlen(temp));
strncpy(num, temp, len);
Note, I am writing this code just to help you understand how strcat() works, there is much better ways to do what you are trying to do.
You cannot concatenate something to a const string, you must have entire control of what is happening into you code, and where your code is writing. Do you know where is the pointer to "0" in your source?
How do you set up num? If it's really an array of characters rather than a string, there's no requirement that it be null terminated, unless it's a global/static. If you set it up like so in a function:
char str[10];
str[0] = '1';
str[1] = '0';
str[2] = '1';
than your strlen will get whatever, depending upon whatever junk happens to be in num.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
//case 1: for num[9]="101";
char *extendBinary1(char num[], int len) {
int num_len = strlen(num);
memmove(num + (len - num_len), num, num_len);
memset(num, '0', (len - num_len));
return num;
}
//case 2: for "101";//pointer to const char
char *extendBinary2(const char num[], int len) {
int num_len = strlen(num);
char *number = calloc(len + 1, sizeof(char));
memset(number, '0', (len - num_len));
return strcat(number, num);
}
int main(void){
char num[9] = "101";
char *number = extendBinary2("101", 8);//dynamic allocate
printf("%s\n", extendBinary1(num, 8));
printf("%s\n", number);//free(number);
return 0;
}