I am trying to print the integer value of each character in a given string using a function. When I pass a string to this function, it converts each character in the given string to an integer and then saves it to a result array. I have also created an array of pointers which will hold the address of each character's corresponding integer. But when I return this array of pointers, I am not able to print all integer values correctly.
#include <stdio.h>
int *c2i(char *str);
int main(){ char s[20]; int *p, i; printf("Enter your string:\n"); scanf("%s", s); p=c2i(s); for(i=0; i<4; i++){ printf("\n%d\t%d\n", *p, p); p++; } return 0;
}
int *c2i(char *str){ int i=0, result[20], *ptr[20]; while(*(str+i)!='\0'){ result[i]=*(str+i) & 0xff; ptr[i]=&result[i]; i++; } printf("%d %d %d %d %d %d %d %d", *ptr[0], *ptr[1], *ptr[2], *ptr[3], ptr[0], ptr[1], ptr[2], ptr[3]); return *ptr;
}I have included many printf statements just for debugging purposes. The output of the program when I try to run the code above is:
Enter your string:
abcd
97 98 99 100 6356588 6356592 6356596 6356600
97 6356588
1999382056 6356592
20 6356596
1 6356600
I am only getting the first value correctly when I print it in the main() function. When I increment the pointer and try to print the next values, I am getting garbage results. I can see that the address is the same but the values have been corrupted. What am I doing wrong here?
3 Answers
You can't return the stack-allocated array since once the function call finishes, it is no longer marked in use. Instead, you should malloc the array, for example int *ptr = malloc(sizeof(int)*20);. Also remember to free the array when done with it (it's good practice). See these posts for details
returning a local variable from function in C
#include <stdio.h>
int** c2i(char *str) { int i=0, *result, **ptr; result = (int *)malloc(20*sizeof(int)) ; ptr = (int **)malloc(10*sizeof(int *)) ; while(*(str+i)!='\0'){ result[i]=*(str+i) & 0xff; ptr[i]=&result[i]; i++; } printf("%d %d %d %d %p %p %p %p", *ptr[0], *ptr[1], *ptr[2], *ptr[3], ptr[0], ptr[1], ptr[2], ptr[3]); return ptr;
}
int main(){ char s[20]; int **p, i; printf("Enter your string:\n"); scanf("%s", s); p=c2i(s); for(i=0; i<4; i++){ printf("\n%d\t%p\n", **p, *p); p++; } return 0;
}double-pointer might solve your issue, look at your modified code..this gives you the desired result.here i'm attaching the screen shot of execution..
How about this
#include <stdio.h>
#include <string.h>
#define MAXLEN 20
void c2i(char *str, int *out, int len);
int main(){ char s[MAXLEN]; int out[MAXLEN]; int *p, i; printf("Enter your string:\n"); /* fgets safer that scanf, protects buffer overrun */ fgets(s, sizeof(s), stdin); /* fgets gives you the newline char though, so remove it */ if(s[strlen(s)-1] == '\n') { s[strlen(s)-1] = '\0'; } c2i(s,out,strlen(s)); for(i=0; i<strlen(s); i++){ printf("%d\n", out[i]); } return 0;
}
void c2i(char *str, int *out, int len){ int i=0; for(i=0; i<len; i++) { out[i]=*(str+i) & 0xff; }
}Passing the out buffer to c2i means you don't need to malloc/free a buffer, but this is probably just a matter of taste.
Using fgets means rather than scanf means you're protected from buffer overruns and your strings can have spaces in them too.