Miguel Garcia
Miguel Garcia

Reputation: 117

Allocate memory for a dynamic string of char

I am trying to make a function that will allocate memory dynamically while the user hit any key other than ENTER. The code compiles without errors or warnings (on gcc) but is not working properly...could someone tell me what is going wrong exactly?

I got the code to work if I modify the function to return a pointer to char i,e, something like

char * getString(char * string);

However I am still curious about the original code and why is not working, would very much appreciate any explanation. Thanks in advance to anyone who takes the time to read this.

#include <stdio.h>
#include <stdlib.h>

void getString(char * string);

int main(void){

    char * str = NULL;

    printf("Write something:\n");
    getString(str);
    printf("You wrote:\n");
    printf("%s\n", str);
    free(str);

    return 0;
}


void getString(char * string){
    char ch;
    int length = 0;

    do{
        scanf("%c", &ch);
        if(length == 0){
            string = (char *) malloc(sizeof(char));
        } else {
            string = (char *) realloc(string, (length + 1) * sizeof(char));
        }
        if(string == NULL){
            printf("ERROR: memory could not be allocated!!\n");
        }

        string[length] = ch;
        length++;
    } while(ch != '\n');

    string[length - 1] = '\0';
}

Upvotes: 0

Views: 335

Answers (2)

Remy Lebeau
Remy Lebeau

Reputation: 595827

The string parameter is being passed in to getString() by value, so it is a copy of the str variable, and as such any changes that getString() makes to string itself, like assigning a memory address to it, are not reflected in the original str variable.

To fix this, you need to pass the string parameter by pointer instead.

You also need to fix the memory leak and access violation that your code has if realloc() fails.

Try this:

#include <stdio.h>
#include <stdlib.h>

void getString(char ** string);

int main(void){

    char * str = NULL;

    printf("Write something:\n");
    getString(&str);
    printf("You wrote:\n");
    printf("%s\n", str);
    free(str);
    return 0;
}

void getString(char ** string){
    char ch, *newstr;
    int length = 0;

    if (string == NULL) {
        printf("ERROR: invalid parameter!!\n");
        return;
    }
    *string = NULL;

    do{
        if (scanf("%c", &ch) < 1) {
            ch = '\n';
        }

        newstr = (char *) realloc(*string, length + 1);
        if (newstr == NULL){
            printf("ERROR: memory could not be allocated!!\n");
            free(*string);
            *string = NULL;
            return;
        }
        *string = newstr;

        newstr[length] = ch;
        length++;
    }
    while (ch != '\n');

    (*string)[length - 1] = '\0';
}

Upvotes: 5

Sourabh Choure
Sourabh Choure

Reputation: 733

A better way to implement your solution.
You should use double pointer as the argument of getString which is going to store the input string from the user.

#include <stdio.h> 
#include <stdlib.h>

void getString(char**); // function prototype

/* Main function */
int main()
{
    /* Pointer to point to the memory location
     * where input string will be stored */
    char *s=NULL;
    /* Call by reference,the function will place 
     * string in memory location where the pointer
     *  is pointing */
    getString(&s); 
    printf("s=%s\n",s);
    
    free(s);
    return 0;
}

/* getString function will
 * store each input character in
 * the allocated memory area. */
void getString(char** p)
{
    if(*p==NULL){
        if((*p=malloc(1*sizeof(char)))==NULL)
            exit(0);
    }

    int c; //Variable to store each input character
    size_t i=0; //Counter to keep track of the size of the input string

    while((c=getchar())!='\n' && c!=EOF){
        char* newp = realloc(*p,i+1);
        if(newp==NULL){
            fprintf(stderr,"realloc failed\n");
            free(p);
            exit(0);
        }
        *p = newp;
        *(*p+i)=c;
        i++;
    }
    *(*p+i)='\0'; //Null character to end the string.
}

Upvotes: 0

Related Questions