Glicério
Glicério

Reputation: 75

how can I append a char to a string allocating memory dynamically in C?

I wrote this code, but inserts garbage in the start of string:

void append(char *s, char c) {
    int len = strlen(s);
    s[len] = c;
    s[len + 1] = '\0';
}

int main(void) {
    char c, *s;
    int i = 0;
    s = malloc(sizeof(char));
    while ((c = getchar()) != '\n') {
        i++;
        s = realloc(s, i * sizeof(char));
        append(s, c);
    }   
    printf("\n%s",s);   
}

How can I do it?

Upvotes: 4

Views: 3422

Answers (3)

ensc
ensc

Reputation: 6984

The inner realloc needs to allocate one element more (for the trailing \0) and you have to initialize s[0] = '\0' before starting the loop.

Btw, you can replace your append by strcat() or write it like

size_t i = 0;
s = malloc(1);
/* TODO: check for s != NULL */
while ((c = getchar()) != '\n') {
        s[i] = c;
        i++;
        s = realloc(s, i + 1);
        /* TODO: check for s != NULL */
}
s[i] = '\0';

Upvotes: 0

chqrlie
chqrlie

Reputation: 144780

There are multiple problems in your code:

  • you iterate until you read a newline ('\n') from the standard input stream. This will cause an endless loop if the end of file occurs before you read a newline, which would happen if you redirect standard input from an empty file.
  • c should be defined as int so you can test for EOF properly.
  • s should be null terminated at all times, you must set the first byte to '\0' after malloc() as this function does not initialize the memory it allocates.
  • i should be initialized to 1 so the first realloc() extends the array by 1 etc. As coded, your array is one byte too short to accommodate the extra character.
  • you should check for memory allocation failure.
  • for good style, you should free the allocated memory before exiting the program
  • main() should return an int, preferably 0 for success.

Here is a corrected version:

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

/* append a character to a string, assuming s points to an array with enough space */
void append(char *s, char c) {
    size_t len = strlen(s);
    s[len] = c;
    s[len + 1] = '\0';
}

int main(void) {
    int c;
    char *s;
    size_t i = 1;
    s = malloc(i * sizeof(char));
    if (s == NULL) {
        printf("memory allocation failure\n");
        return 1;
    }
    *s = '\0';
    while ((c = getchar()) != EOF && c != '\n') {
        i++;
        s = realloc(s, i * sizeof(char));
        if (s == NULL) {
            printf("memory allocation failure\n");
            return 1;
        }
        append(s, c);
    }
    printf("%s\n", s);
    free(s);
    return 0;
}

Upvotes: 3

Roy Avidan
Roy Avidan

Reputation: 768

when you call strlen it searches for a '\0' char to end the string. You don't have this char inside your string to the behavior of strlen is unpredictable. Your append function is acually good. Also, a minor thing, you need to add return 0; to your main function. And i should start from 1 instead if 0. Here is how it should look:

int main(void){
   char *s;
   size_t i = 1;
   s = malloc (i * sizeof(char));//Just for fun. The i is not needed.
   if(s == NULL) {
   fprintf(stderr, "Coul'd not allocate enough memory");
   return 1;
   }
   s[0] = '\0';
   for(char c = getchar(); c != '\n' && c != EOF; c = getchar()) {//it is not needed in this case to store the result as an int.
      i++;
      s = realloc (s,i * sizeof(char) );
      if(s == NULL) {
             fprintf(stderr, "Coul'd not allocate enough memory");
             return 1;
      }
      append (s,c);
    }   
printf("%s\n",s);   
return 0;
}

Thanks for the comments that helped me improve the code (and for my english). I am not perfect :)

Upvotes: 0

Related Questions