Assigning char array of pointers with scanf

2019-08-05 10:10发布

问题:

I'm trying to use scanf to fill an array of char pointers to store the input as a string. The variable T is used to build an array of size T dynamically. Then T amount of strings are entered and displayed however when I fill in the array for example if T = 2 the first line could dog and the second line cat, it prints out "cdog" and "cat". So the first letter of the first string then the all of the 2nd string. I'm not sure where my mistake is in using char*. Any help would be appreciated.

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

int main()
{
  int T;
  int i;
  scanf("%d",&T);


  char *new_array = (char*)malloc(T * sizeof(char));

  for (i = 0; i < T; ++i)
  {
    scanf("%s", new_array+i);

  }

  for (i = 0; i < T; i++)
  {
    printf("%s\n", new_array+i);
  }
}

回答1:

  1. Always check the return value of scanf().
  2. You are not allocating space for pointers, but for bytes, which is the main problem, you need

    char **new_array = malloc(T * sizeof(char *));
    /*    ^                                   ^             */
    /* allocate pointer to poitners         sizeof(pointer) */  
    if (new_array == NULL)
        handleThisErrorAndDoNotTryToWriteTo_new_array();
    

    you will also need space for each string so

    new_array[i] = malloc(1 + lengthOfTheString);
    if (new_array[i] == NULL)
        handleThisErrorAndDoNotTryToWriteTo_new_array_i();
    

    right before scanf(), and instead of scanf("%s", new_array + i) do this

    scanf("%s", new_array[i]);
    

If you enable compiler warnings, the compiler should warn you that you are passing incompatible types to printf().

It would also be good, to use a length modifier for scanf() to prevent buffer overflow, and don't forget to call free() when you no longer need the pointers.



回答2:

In your code, new_array is of type char *, which is not what you want. You have to change your definition to

char *new_array[T] = malloc(T * sizeof(char*));

Then, you can use the scanf() as per your previous code.



回答3:

Do this instead, together with the rest of the body:

int string_size;
//this begins just after reading T
scanf("%d", &string_size);
char **new_arrays = malloc(T * sizeof(char*));
for(i = 0; i < T; i++)
{
    new_arrays[i] = malloc(string_size * sizeof(char));
}

The first malloc is to specify how many strings you want, and the second malloc is to specify how big a string can be.

Further tips:

  1. When you're writing in C, do not cast void* produced by malloc and realloc.
  2. You should de-allocate the memory used in the reverse way:

    for (i = 0; i < T; ++i)
    {
        free(new_array[i]);
    }
    free(new_array);
    
  3. Always check if the memory allocation process is (un)succesful:

    char **new_arrays = malloc(T * sizeof(char*));
    if(new_arrays == NULL)
       exit(0) //e.g.
    for(i = 0; i < T; i++)
    {
        new_arrays[i] = malloc(string_size * sizeof(char));
        if(new_arrays[i] == NULL)
            exit(0) //e.g.
    }
    
  4. Check if the user provides valid values through scanf.



回答4:

Thanks everyone. The length of the strings in the char* array can not be greater than 1000 chars so thats hard coded. Here is the final working code...

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

int main()
{
  int T;
  int i;
  scanf("%d",&T);


  char **new_array = malloc(T * sizeof(char*));
  for (i = 0; i < T ; i++)
  {
    new_array[i] = malloc(1000 * sizeof(char));
    scanf("%s", new_array[i]);
  }

  for (i = 0; i < T; i++)
    printf("%s\n", new_array[i]);
}