【问题标题】:How do I assign a value to an array of strings in C?如何为C中的字符串数组赋值?
【发布时间】:2021-09-11 06:43:12
【问题描述】:

所以我使用malloc() 创建了一个指针数组。我最终想要一个字符串数组。我将如何将字符串值分配给这些 malloced 指针之一?

例如,如果我做了以下事情:

char ** elements= malloc(N* sizeof(char*));

并循环前一个数组以分配单个指针,如下所示:

elements[i] = malloc((50) * sizeof(char));

【问题讨论】:

  • 此代码将为每个字符串准确分配 50 个字节。你知道你所有的字符串都会比这短吗?
  • 对于此代码,您可能希望使用 strcpy(elements[i], somestring) -- 但是,您必须小心确保每个复制的字符串 somestring 的长度小于 50 个字符。
  • 我明白了,字符串实际上少于 50 个字符,非常感谢!
  • 有一个非标准但广泛可用的函数strdup,请查看。您也可以实现自己的版本。
  • C 没有字符串值。只有字符和指针。所以你必须弄清楚“为字符串数组赋值”在实际 C 语言(字符和指针)中的含义。

标签: arrays c pointers dynamic-memory-allocation


【解决方案1】:

使用#include <string.h> 包含字符串函数。 比使用 strncpy 函数为 char 数组赋值。要将字符串复制到elements[i],请使用:

strncpy(elements[i], "Hello, world!", 49)

您可以将另一个char 数组指针作为第二个参数。请注意,为避免擦除字符串末尾的空字节,请从实际字符串数组长度中减去 1 以保留 '\0' 的最后一个字节。此外,最好使用calloc(50, sizeof(char)) 来分配字符串,因为calloc 还会用空字节填充它们。或者,至少,在迭代时添加这一行(将最后一个字节设置为零以使字符串以空值结尾):

elements[i][49] = '\0';

【讨论】:

    【解决方案2】:

    使用当前标准 C,您可以:

    #include <stdlib.h>
    #include <string.h>
    
    size_t size = strlen(some_string) + 1; // +1 for null term
    elements[i] = malloc(size);
    memcpy(elements[i], some_string, size);
    
    ...
    
    free(elements[i]);
    

    随着即将推出的“C2x”标准(仍处于草案阶段),strdup 可能会被添加到该语言中。尽管它已经作为 POSIX 支持的非标准扩展广泛使用。示例:

    #include <string.h>
    
    elements[i] = strdup(some_strings[i]);
    
    ...
    
    free(elements[i]);
    

    【讨论】:

      【解决方案3】:

      我们可以使用strncpy() 和类似的函数将某些内容复制到字符串中,例如memcpy() 或使用我们自己的函数。

      我建议使用strncpy(),因为它可以防止溢出,因为它会复制一个直到指定的长度。

      #include <stdio.h>
      #include <stdlib.h>
      #include <string.h>
      
      typedef unsigned char BYTE;
      
      enum {
          NumStrings = 50,
          MaxStrLen = 50
      };
      
      int main(void) {
          char **StrList = malloc(NumStrings * sizeof(char *));
          if (StrList == NULL) {
              perror("malloc");
              exit(1);
          }
          for (BYTE i = 0; i < NumStrings; i++) {
              StrList[i] = malloc(MaxStrLen);
              if (StrList[i] == NULL) {
                  perror("malloc");
                  exit(1);
              }
              // Here we copy something into the string for example
              strncpy(StrList[i], "test", 50);
              StrList[i][49] = '\0';
              // Print string here to show it's copied
              printf("%s ", StrList[i]);
          }
          putchar('\n');
      
          for (BYTE i = 0; i < NumStrings; i++) 
              free(StrList[i]);
          free(StrList);
          exit(0);
      }
      

      【讨论】:

      • 不幸的是,strncpy 所解决的问题与它所解决的问题一样多,因为如果源字符串恰好是 N 个字符长,则复制的字符串将不会正确地以空值结尾。真正安全的选择是strlcpy,尽管它不是标准的。
      • “我推荐使用 strncpy(),因为它可以防止溢出” 这是完全错误的。请学习Is strcpy dangerous and what should be used instead?
      • @SteveSummit strcpy_s 已正式标准化,但实际上很少有编译器实现 C11 边界检查库。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2012-05-24
      • 2011-12-08
      • 2017-09-27
      • 2016-05-12
      • 2021-05-22
      • 2011-09-08
      • 1970-01-01
      相关资源
      最近更新 更多