【问题标题】:Assigning char array of pointers with scanf使用 scanf 分配指针的 char 数组
【发布时间】:2015-06-12 01:06:51
【问题描述】:

我正在尝试使用 scanf 填充 char 指针数组以将输入存储为字符串。变量 T 用于动态构建大小为 T 的数组。然后输入并显示 T 数量的字符串,但是当我填写数组时,例如如果 T = 2 第一行可能是狗,第二行是猫,它会打印出“cdog”和“cat”。所以第一个字符串的第一个字母然后是第二个字符串的全部。我不确定我在使用 char* 时的错误在哪里。任何帮助,将不胜感激。

#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);
  }
}

【问题讨论】:

  • 您没有 char 指针数组。你有一个字符数组。
  • "然后输入了 T 个字符串..." 你已经为 一个 字符串分配了内存。
  • 标准警告:请do not castmalloc()C 中的家人的返回值。
  • 另外,freemalloced 内存在使用后不会导致内存泄漏

标签: c arrays string char scanf


【解决方案1】:
  1. 始终检查scanf() 的返回值。
  2. 您不是为指针分配空间,而是为字节分配空间,这是主要问题,您需要

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

    你还需要为每个字符串留出空间

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

    scanf() 之前,而不是scanf("%s", new_array + i) 这样做

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

如果您启用编译器警告,编译器应该警告您将不兼容的类型传递给printf()

最好使用scanf() 的长度修饰符来防止缓冲区溢出,并且在不再需要指针时不要忘记调用free()

【讨论】:

  • 在更改中检查scanf() 的返回值吗?输入字符串是什么? lengthOfTheString 的长度是多少?
  • new_array[i] = malloc(1000*sizeof(char)) 这也不起作用。数组中每个元素的最大大小不能超过 1000 个字符。
  • @DexterCooke sizeof(char) == 1 根据定义。
【解决方案2】:

在您的代码中,new_array 的类型为 char *,这不是您想要的。您必须将定义更改为

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

然后,您可以按照之前的代码使用scanf()

【讨论】:

    【解决方案3】:

    改为与身体的其他部分一起这样做:

    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));
    }
    

    第一个malloc是指定你想要多少个字符串,第二个malloc是指定一个字符串可以有多大。

    更多提示:

    1. 当您使用 C 语言编写时,不要强制转换由 mallocrealloc 生成的 void*
    2. 您应该以相反的方式取消分配使用的内存:

      for (i = 0; i < T; ++i)
      {
          free(new_array[i]);
      }
      free(new_array);
      
    3. 始终检查内存分配过程是否(不)成功:

      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. 检查用户是否通过scanf提供了有效值。

    【讨论】:

    • 如果用户在第一次输入请求时输入adsda怎么办?即scanf("%d" ... ) 何时执行?
    • 如果?我已经在我的答案中添加了它,但我认为这是一个一般性提示,而不是在这个答案中提及重要,因为在我看来它总是很重要,而不仅仅是现在。
    【解决方案4】:

    谢谢大家。 char* 数组中字符串的长度不能大于 1000 个字符,因此是硬编码的。这是最终的工作代码...

    #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]);
    }
    

    【讨论】:

    • 您应该考虑freeNULL checking 的建议。
    猜你喜欢
    • 2015-10-26
    • 2019-09-19
    • 2011-04-02
    • 2018-10-06
    • 2015-05-21
    • 1970-01-01
    • 2018-08-15
    • 1970-01-01
    • 2021-01-10
    相关资源
    最近更新 更多