初始化字符串数组并将其传递给函数的最佳方法

2022-01-30 11:24:50 标签 arrayscstringpointers

我需要初始化一个固定大小的空字符串数组(例如3 × 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]));
}

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

###C字符串函数希望缓冲区以null结尾。你的arrayofstrings分配发生在堆栈上。根据编译器的不同,它可能被初始化为全0或者可能包含垃圾。

在您的情况下,确保字符串函数不会超出缓冲区的最简单的方法是将每个函数的第一个字符设置为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字节,并给你一个char*称为'arrayofstrings'。char*本身没有什么特别之处。如果你有char arrayofstrings[300]或char arrayofstrings[300]或[3][10][10]甚至long arrayofstrings[75] (char是1字节长,是4字节长),它将是相同的指针。

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

###你不需要额外的间接级别。

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

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

# # # < blockquote >

初始化字符串数组的最佳方法…

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

在C语言中,初始化只在上面这样的对象定义时完成。

后面的代码,如strcpy(),将数据赋给数组。

最好的方法是……将它传递给函数

当C编译器支持可变长度数组时,使用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]);
  }
}

# # # < blockquote >

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

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

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

不是初始化指针与arrayofstrings数组的第一个元素,但指针将指向整个2D数组的字符串。这就是为什么当使用指针访问元素时,你需要在它周围的括号-

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

这样做好吗?有没有更简单的方法?

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

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

char (*p)[100] = arrayofstrings;

&arrayofstring[0]和arrayofstring都是等价的1)。

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

函数()的函数签名应该是-

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

当你访问一个数组时,它被转换为指向第一个元素的指针(这个规则很少有例外)。

阅读全文

▼ 版权说明

相关文章也很精彩
推荐内容
更多标签
相关热门
全站排行
随便看看

错说 cuoshuo.com —— 程序员的报错记录

部分内容根据CC版权协议转载;网站内容仅供参考,生产环境使用务必查阅官方文档

辽ICP备19011660号-5

×

扫码关注公众号:职场神器
发送: 1
获取永久解锁本站全部文章的验证码