【问题标题】:Best way to initialize an array of strings to pass it to a function初始化字符串数组以将其传递给函数的最佳方法
【发布时间】:2021-11-13 07:31:18
【问题描述】:

我需要初始化一个固定大小的空字符串数组(例如 3 x 100),将其传递给函数以填充数据并对其执行 strcpy()、strcmp()、memset() 等操作.函数终止后,我需要能够从我的 main() 读取数据。

到目前为止我尝试了什么:

char arrayofstrings[3][100] = {0};
char (*pointer)[3][100] = &arrayofstrings;

function(pointer);

初始化一个(空?)字符串数组并初始化第一个元素上的指针。

int function (char (*pointer)[3][100])
{
strcpy((*pointer)[i], somepointertostring);
strcmp((*pointer)[i], somepointertostring)
memset((*pointer)[i], 0, strlen((*pointer)[i]));
}

这是一个好方法吗?有更简单的方法吗?指针周围的括号是怎么回事?

【问题讨论】:

    标签: arrays c string pointers


    【解决方案1】:

    C 字符串函数期望缓冲区以空值结尾。您的 arrayofstrings 分配发生在堆栈上。根据您的编译器,它可能被初始化为全零或可能包含垃圾。

    在您的情况下,确保字符串函数不会超出缓冲区的最简单方法是将每个函数的第一个字符设置为 0(空)

    arrayofstrings[0][0] = 0x00;
    arrayofstrings[1][0] = 0x00;
    arrayofstrings[2][0] = 0x00;
    

    这将为您提供 3 个 100 字符的缓冲区,其中包含一个有效的空“字符串”。请注意,您只能存储 99 个“字符”,因为最后一个字符必须是 0x00(空终止符)。


    char (*pointer)[3][100] = &arrayofstrings;
    

    这是不必要的。

    关于 C 中的数组需要牢记的一点是,[] 索引实际上只是为了让人类程序员更轻松。任何数组定义都只是一个指向内存的指针。 [][]...[] 索引中的值和类型被编译器用于在堆栈上分配正确的内存量,并进行一些简单的数学运算以得出所需元素的正确内存地址访问。

    char arrayofstrings[3][100];
    

    这将在堆栈上分配 sizeof(char)*3*100 字节,并为您提供一个名为 'arrayofstrings' 的 char*。 char* 本身并没有什么特别之处。如果您有char arrayofstrings[300]char arrayofstrings[3][10][10] 甚至long arrayofstrings[75](char 为 1 字节,long 为 4 字节),它将是同一个指针。

    因为你用[a][b]将它声明为一个多维数组,当你请求arrayofstrings[x][y]时,编译器会计算((x*b)+y)*sizeof(type)和将其添加到 arrayofstrings 指针以获取所需值的地址。但是因为它只是一个指针,所以你可以像对待任何其他指针一样对待它,并将它传递给其他类型的指针,或者用它进行指针数学运算。

    【讨论】:

      【解决方案2】:

      初始化一个(空?)字符串数组并初始化第一个元素上的指针。

      &arrayofstrings 的类型是char (*)[3][100],即指向一个对象的指针,该对象是char 类型的2D 数组,维度为3 x 100。所以,这个初始化

      char (*pointer)[3][100] = &arrayofstrings;
      

      不是用arrayofstrings数组的第一个元素初始化pointer,而是pointer将指向整个2D数组arrayofstrings。这就是为什么,当使用 pointer 访问元素时,需要用括号括起来 -

      `(*pointer)[0]` -> first string
      `(*pointer)[1]` -> second string and so on..
      

      这是一个好方法吗?有没有更简单的方法?

      如果你想要指向数组arrayofstrings 的第一个元素的指针,那么你可以这样做

      char (*p)[100] = &arrayofstrings[0];
      

      或者

      char (*p)[100] = arrayofstrings;
      

      &arrayofstrings[0]arrayofstrings 是等价的1)

      将其传递给函数并访问数组:

      function() 函数签名应该是 -

      int function (char (*pointer)[100])
      // if you want the function should be aware of number of rows, add a parameter for it -
      // int function (char (*pointer)[100], int rows)
      

      这相当于

      int function (char pointer[][100])
      

      并像这样从main()函数调用它-

      function (p);
      

      function() 函数中,您可以使用p[0], p[1] ... 访问数组:

      演示示例程序:

      #include <stdio.h>
      #include <string.h>
      
      #define ROW 3
      #define COL 100
      
      void function (char (*p)[COL]) {
          strcpy (p[0], "string one");
          strcpy (p[1], "string two");
          strcpy (p[2], "string three");
      }
      
      int main(void) {
          char arrayofstrings[ROW][COL] = {0};
          char (*pointer)[COL] = &arrayofstrings[0];
      
          function (pointer);
      
          for (size_t i = 0; i < ROW; ++i) {
              printf ("%s\n", arrayofstrings[i]);
          }
      
          return 0;
      }
      

      1. 当您访问一个数组时,它会被转换为指向第一个元素的指针(这条规则很少有exceptions)。

      【讨论】:

        【解决方案3】:

        初始化字符串数组的最佳方式 ...

        char arrayofstrings[3][100] = {0}; 可以初始化一个字符串数组。

        在 C 中,初始化仅在对象定义时完成,如上。

        strcpy() 这样的稍后代码,分配数据给数组。


        将它传递给函数的最佳方法

        • 当C编译器支持variable length arrays时,使用function(size_t n, size_t sz, char a[n][sz])

        • 添加错误检查。

        • 使用size_t 进行数组大小调整和索引。


        #define somepointertostring "Hello World"
        
        int function(size_t n, size_t sz, char arrayofstrings[n][sz]) {
          if (sz <= strlen(somepointertostring)) {
            return 1;
          }
          for (size_t i = 0; i < n; i++) {
            strcpy(arrayofstrings[i], somepointertostring);
            if (strcmp(arrayofstrings[i], somepointertostring)) {
              return 1;
            }
            // Drop this it see something interesting in `foo()`
            memset(arrayofstrings[i], 0, strlen(arrayofstrings[i]));
          }
          return 0;
        }
        
        void foo(void) {
          char arrayofstrings[3][100] = {0};
          size_t n = sizeof arrayofstrings / sizeof arrayofstrings[0];
          size_t sz = sizeof arrayofstrings[0];
          if (function(n, sz, arrayofstrings)) {
            puts("Fail");
          } else {
            puts("Success");
            puts(arrayofstrings[0]);
          }
        }
        

        【讨论】:

        • 我的初始化是初始化数组并用零填充它(从而使其为空)还是只是初始化它上面的指针?我问这个是因为在我的函数中我想检查 arrayofstrings[][] 是空的还是已经填充了数据。
        • @Psoke char arrayofstrings[3][100] = {0}; 用零填充 arrayofstrings。非empty 中的数组。元素用值 0 填充 - char 的数组没有 empty 状态。它不会“初始化上面的指针”,因为arrayofstrings 中没有指针,只有 300 个char
        【解决方案4】:

        您不需要额外的间接级别。

        当传递给函数时,数组被转换为指向其第一个成员的指针。所以如果你这样声明函数:

        int function(char (*pointer)[100])
        

        或等价:

        int function(char pointer[][100])
        

        或者:

        int function(char pointer[3][100])
        

        您可以将数组直接传递给函数:

        function(arrayofstrings);
        

        然后身体可能看起来像这样:

        strcpy(pointer[0], "some string");
        strcpy(pointer[1], "some other string");
        strcpy(pointer[2], "yet another string");
        

        【讨论】:

        • 但是问题是如何初始化,不是吗?或者只是不清楚。
        猜你喜欢
        • 1970-01-01
        • 2023-04-09
        • 2012-11-27
        • 2023-03-06
        • 1970-01-01
        • 1970-01-01
        • 2021-02-07
        • 1970-01-01
        • 2016-12-08
        相关资源
        最近更新 更多