array value not updating - c

I have a strtok implementation (sort of), but it doesn't print the token!
char *tokenizer(char s[], const char *delimiter) {
char *p; //return value of function
int i = 0;
while(s[i] != *delimiter) //to get the size of array just right
i++;
char arr[i+1];
p = arr; //can't return an array, so assigned to a
//pointer
int j = 0;
i = 0;
while(s[i]!=*delimiter) {
arr[j] = s[i];
i++;
j++;
}
arr[j] = '\0';
printf("%s\n",p); //this statement works, but if excluded
//main prints nothing.
return p;
}
This function is being called as following, from the main:
char s[] = "tab-tab";
const char del[2] = "-";
char *p;
p = tokenizer(s, del);
printf("%s\n", p); //prints nothing without the printf in
//tokenizer
I tried debugging with gdb, and inspected the values of local variable after each line. p is updated with arr[j] inside tokenizer but goes to zero as soon as tokenizer finishes and frame shifts back to main.
The value ofp in main doesn't become NULL, it becomes an empty string, and prints that!
However, p in main prints the token if printf in tokenizer is included.
This already includes work-around. I know this can't possibly be the way strtok is implemented. I started with a more sophisticated, "expertish" version which had pointers, but couldn't get it to work, so settled for this "beginner" version.

It's because your pointer is pointing to a memory address in the stack, once your function is returned the memory address being pointed to no longer exists, you need to create dynamically allocated memory to access the variable outside of the function. The beauty of C
char *tokenizer(char s[], const char *delimiter) {
char *arr;
int i = 0;
while(s[i] != *delimiter)
i++;
// Initialize variable in the heap
if (!(arr = malloc(sizeof(char *) * (i+1))))
return NULL;
// Clear the array
bzero(arr, (i+1));
int j = 0;
i = 0;
while(s[i]!=*delimiter) {
arr[j] = s[i];
i++;
j++;
}
arr[j] = '\0';
// return pointer
return arr;
}
You should make sure to free the memory in the main to prevent memory leaks.

Related

String returned from function contains garbage [duplicate]

This question already has answers here:
Returning an array using C
(8 answers)
Closed 3 years ago.
I want the function lch() to return a string that can be used outside the function.
This is the code I have written, but it does not seem to work:
char *lch(char *ch,int n){
char c[n];
for(int i=0;i<n;i++){
c[i] = *ch;
}
puts(c); // check output string inside function
return c;
}
char str[100],*p;
main(){
p = lch("a",20);
puts(p); // check output outside function
}
I am confused with strings and how they should be passed to functions.
I want the output string to become the same on both calls to puts().
What should I do?
That is the result of the code above:
aaaaaaaaaaaaaaaaaaaa // inside the function
        ¢ÞêÊ· // outside the function
First of all, returning locally allocated storage will not work. You have to return dynamically allocated storage, and with a proper size to accommodate the null-terminator:
char *c = malloc(n+1);
/* ... */
/* end of program: */
free(p);
Second, you want to pass a character to your function, not a string:
char *lch(char ch,int n){
/* ... */
c[i] = ch;
/* ... */
p = lch('a', 20);
Third, you have to null-terminate your string:
int i;
for(i=0;i<n;i++){
c[i] = ch;
}
ch[i] = '\0';
puts(c); //check output string inside function
Here's the dynamically-allocated storage approach:
#include <stdlib.h>
#include <stdio.h>
char *lch(char ch,int n){
char *c = malloc(n+1);
int i;
for(i=0;i<n;i++){
c[i] = ch;
}
c[i] = '\0';
puts(c); //check output string inside function
return c;
}
char *p;
int main(void){
p = lch('a',20);
puts(p); //check output outside function
free(p);
return 0;
}
This also fixes the declaration and return type of main (main is supposed to be int main(void) or int main(int argc, char **argv)), removes the unneeded variable str, and adds needed #includes.
The reason your code does not do what you expect it to do is because the string in the function is allocated on the stack, which means that its memory is cleaned as soon as you exit the function.
That means the pointer p points to garbage value after the call to lch().
Also, you can not declare an array of size that is not a constant value, so the line:
char c[n];
would simply not work.
To solve this, you will need to dynamically allocate the string using malloc(3) :
char* lch(char ch, int n)
{
char * c;
/* Allocate n bytes of memory for the string */
c = malloc(n + 1);
if (NULL == c)
{
/* Failed to allocate memory, exit the function */
return c;
}
for(int i = 0; i < n; i++)
{
c[i] = ch;
}
/* Add a terminating null byte (to make it a string) */
c[i] = '\0';
puts(c);
return c;
}
int main(void)
{
char * p;
p = lch('a', 20);
puts(p);
/* Free the string from the memory */
free(p);
return 0;
}
I added a few fixes to the code but the main thing you need to look at is the use of malloc(3).
I dynamically allocated n+1 bytes of memory for the string, then wrote the data into the string (plus a '\0'), and when the function exits the memory will still be available and wont be corrupted.
The call to free is needed to free the memory we have allocated.
You can read more about malloc(3) here: https://linux.die.net/man/3/malloc

Pointers and local arrays in C

Why doesn't my function printTable print the content of my array? For example, from the whole word 'oui' stored in my array mysteryword it prints only 'o'?
#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>
#include <time.h>
#define libraryDimension 12
char* getFirstElementPointerOfMysteryWord(void);
char getCarac(void);
void printTable(char*ptr,int dimension);
/* Main program*/
int main() {
//getCarac();
char *pointerForFirstElement = getFirstElementPointerOfMysteryWord();
int tableDimension = 3;
printTable(pointerForFirstElement, tableDimension);
return 0;
}
This function is intended to provide a choice of words it has no parameters and it returns the address of the first element of my word's array.
char *getFirstElementPointerOfMysteryWord(void) {
int randomNumbers[3] = {0};
char mysteryWord[4];
char wordLibrary[libraryDimension];
wordLibrary[0] = '#';
wordLibrary[1] = 'n';
wordLibrary[2] = 'o';
wordLibrary[3] = 'n';
wordLibrary[4] = '#';
wordLibrary[5] = 'o';
wordLibrary[6] = 'u';
wordLibrary[7] = 'i';
wordLibrary[8] = '#';
wordLibrary[9] = 'q';
wordLibrary[10] = 'u';
wordLibrary[11] = 'i';
wordLibrary[12] = '\0';
int j=0;
for (int i = 0; i<libraryDimension; i++) {
if(wordLibrary[i] == '#') {
randomNumbers[j] = i;
j++;
}
}
srand(time(NULL));
int index = rand() % 3;
int randomNumber = randomNumbers[index];
int k=0;
for (int i = randomNumber ; i< libraryDimension-1 ; i++) {
if(wordLibrary[randomNumber+k+1] == '#'){
break;
}
else{
mysteryWord[k] = wordLibrary[randomNumber+1+k];
k++;
}
}
return mysteryWord;
}
This is the part where my code doesn't work properly.
void printTable(char *ptr,int dimension) {
for (int i = 0; i <dimension ; i++) {
printf("%c",*(ptr+i));
}
}
char getCarac(void){
char carac;
carac = getchar();
return carac;
}
When you declare a variable in a function, it is allocated on the stack. When the variable goes out of scope i.e. the function ends, the variable disappears (stack is local for the function) so by returning the address of the array you are returning an address that no longer exists.
Instead either allocate storage on the heap using malloc
char *mysteryWord = malloc(4);
or better, have it declared outside the function and then pass it to the function to fill.
void getFirstElementPointerOfMysteryWord(char* mysterword, size_t maxLen)
The problem is right here
char *getFirstElementPointerOfMysteryWord(void)
{
char mysteryWord[4];
/* other stuff */
return mysteryWord;
}
mysteryWord ceases to exist when the function returns. Any dereferencing of it by the caller (e.g. examining its content) or passing it to another function that dereferences (which your code does) gives undefined behaviour.
You need to ensure whatever pointer the caller receives, it continues to point at something that will exist for the caller. That can be done in various ways, each with different trade-offs. Probably the easiest is for the caller to PASS an array with 4 elements as an argument to this function (if the caller owns it, it will not cease to exist until the current scope within the caller ends)

Returning char* to print in C

So I am trying to print out a char* array after being returned from a function but I keep getting a segfault.
char* return(node *n){
node* p = list->head;
int count = 0;
int size = 0;
while(p != NULL){
size += strlen(p->name);
count++;
p = p->nxt;
}
size = size + 1; // for the '\0'
char * arr[count][size];
p = list->head;
count = 0;
while(p != NULL){
strcpy(arr[count], p->name);
count++;
p = p->next;
}
return arr;
}
I then go to try and print it out in my main method on a certain node. and I get a segmentation fault.
char* test = return(node1);
for(i = 0; i < 5; i++){
printf("%s", test[i]);
}
Your arr is local to the (unfortunately named) function. When the function exits, the space is deallocated. If you use that pointer afterwards, you are indexing into unknown, and most likely somewhere you're not supposed to (which results in a segfault).
When you want to allocate space in a function and return a pointer, you should use malloc (or equivalent), and remember to free the space afterwards. An alternate way is to have the pointer be a parameter to the function, and leave the reponsibility for allocation (and deallocation) to the caller (like fgets does).
Approach 1 (allocation inside the function):
char *foo() {
char *arr = malloc(100);
return arr;
}
/* somewhere else */
char *arr = foo();
/* use arr */
free(arr);
Approach 2 (allocation outside the function):
void foo(char *arr, size_t size) {
/* do stuff to arr */
}
/* somewhere else */
char *arr = char[100];
foo(arr, 100);
EDIT: Was wrong. Ignore what was here.

Issue working with double pointers

I'm new to C and having trouble wrapping my head around double pointers and keep getting segmentation fault errors. I've debugged the program a bit and located where things go wrong, but can't for the life of me figure out why. I'll post my code first:
int main() {
printf("Enter string to be split: \n");
a = readline();
String *st = newString(a);
String **split;
int num;
num = string_split(st, ',', split);
for (i=0; i<num; i++) { print_string(*(split+i)); }
}
readline() produces a pointer to an array of chars (entered by the user) and appends '\0' to it. newString and print_string definitely work. Here's the struct for string:
typedef struct {
char *chars;
int length;
int maxSize;
} String;
And here is the code for string_split which is causing me all this trouble.
int string_split(String *s, char delim, String **arrayOfStructs) {
char *c = getCharacters(s);
int len = length(s);
int begin = 0;
int end;
int arraycount = 0;
String **temp = (String**)malloc(sizeof(String*));
for (end=0; end<len+1; end++) {
if ((*(c+end) == delim || *(c+end) == '\0') && begin != end) {
String *st = substring(s,begin,end-1);
*(temp + arraycount) = st;
begin = end + 1;
arraycount++;
temp = (String**)realloc(temp, 1+arraycount*sizeof(String*));
}
}
arrayOfStructs = temp;
return arraycount;
}
In main, when I get back split, all the String*'s that it points too are gone. When print_string gets an individual String* and tries to grab one of its members, a segmentation fault occurs. I don't understand why, because I feel like I allocate memory every time it is necessary, but I feel like I'm missing something. Also, when debugging, if I step through string_split, temp is produced exactly like I expect, so I think I'm just not malloc'ing somewhere where I'm supposed to and it's not a problem with the logic of the function. Here is the code in substring, although I'm pretty sure it works since I've been able to return String* from substring and pass them to print_string just fine.
String *substring(String *s1, int begin, int end) {
String *s = (String*)malloc(sizeof(String));
int length = 0;
s->maxSize = 20;
char *temp = (char*)malloc(20*sizeof(char));
char *arr = s1->chars;
int i;
for (i=begin; i <= end; i++) {
*(temp+length) = *(arr+i);
length++;
if (length == s1->maxSize-1) {
s1->maxSize = s1->maxSize+20;
temp = (char*)realloc(temp, s1->maxSize*sizeof(char));
}
}
*(temp+length) = '\0';
s->length = length;
s->chars = temp;
return s;
}
Any help is greatly appreciated!
You need to pass the argument arrayOfStructs by reference and not by value. As C doesn't actually have proper references, you have to pass a pointer to the variable:
int string_split(String *s, char delim, String ***arrayOfStructs) {
...
*arrayOfStructs = temp;
return arraycount;
}
Call it using the address-of operator &:
num = string_split(st, ',', &split);
As it is now, you pass the argument by value, which means that the variable arrayOfStructs is just a local copy inside the function. Any changes to it is only made to the copy, and are lost once the variable goes out of scope when the function returns.
String **temp = (String**)malloc(sizeof(String*));
*(temp + arraycount) = st;
temp+arraycount is going to give you a random address in memory. temp contains the pointer you just malloced, which should point to another pointer.(which you have not initialised), but you are incrementing the pointer so you loose the location you just malloced.
temp is not pointing to consecutive memory, it specifically points to another pointer(which is 8bytes on a 64bit machine)

printf overwriting seeminlgy unrelated data?

EDIT: I should add how I have this all set up. The struct definition and prototypes are in mystring.h. The function definitions are in mystring.c. The main is in mystringtest.c. For mystring.c and mystringtest.c, I have #include "mystring.h" at the top. I'm compiling like gcc -o test.exe mystring.c mystringtest.c. Not sure if any of that matters, but I'm new with C so I'm just trying to include everything.
I have a good deal of experience with Java but am pretty new to C. I imagine this is related to pointers and memory but I'm totally at a loss here for what's going on. Here's my code:
typedef struct {
char *chars;
int length;
int maxSize;
} String;
int main() {
char *a;
a = readline();
String *s = newString(a);
int b = length(s);
printf("length is %d \n", b);
}
I run the program and enter "hello" (as prompted by readline()). I've stepped through the program and after length(s), s->chars is still a pointer to the array of chars 'hello'. After the print statement, s->chars becomes a pointer to the array of chars 'Length is %d \n'. I'm totally at a loss for what I'm doing wrong. I'm working on a virtual machine if that matters at all. Any help is greatly appreciated. I'll give the code for newString and length too.
int length(String *s) {
char *temp = s->chars;
char b = *temp;
int count;
if (b == '\0') { count = 0; }
else { count = 1; }
while (b != '\0') {
b = *(temp+count);
count++;
}
return count;
}
String *newString(char *s) {
String st;
st.length = 20;
st.maxSize = MAXCHAR;
char *temp = malloc(20 * sizeof(char));
char b = *s;
int count = 0;
while (b != '\0') {
*(temp + count) = b;
count++;
b = *(s+count);
if (count == st.maxSize) { break; }
if (count == st.length) {
st.length = st.length + 20;
temp = realloc(temp, st.length * sizeof(char));
}
}
st.chars = temp;
return &st;
}
String *newString(char *s) {
String st;
...
return &st;
}
You are returning a pointer to a local variable. After newString returns, the local variable no longer exists, so you have a dangling pointer.
Either allocate st with malloc, or return it by value.
you must null terminate the string after the while loop, you have not left space for the null terminator. Also I don't see why you need to realloc
//using strlen will eliminate the need for realloc, +1 is for the null terminator
int len = strlen(s)
char *temp = malloc((len * sizeof(char)) +1);
//null terminate
*(temp+count) = '\0';
st.chars = temp;

Resources