在函数中使用字符串数组

Posted

技术标签:

【中文标题】在函数中使用字符串数组【英文标题】:Using Arrays of strings in function 【发布时间】:2022-01-14 10:35:51 【问题描述】:

我正在练习字符串数组,但似乎我不明白它是如何工作的,有人可以向我解释一下什么是制定这段代码的正确方法吗?

代码目的:将 2 个字符串分配给一个字符串数组并使用函数打印它们。

错误: 编译器没有发现任何错误,但我根本没有在终端中得到任何输出。

#include <stdio.h>

#define MAX 100

void function(char **);

int main()
    
    char *a[MAX]; /*array of max 100 strings*/
    a[0] = "test0";
    function(&a[MAX]);    
    return 0;


void function(char *a[MAX])
    
    a[1] = "test1";
    printf("%s",*a[1]);
    printf("%s",*a[0]);

【问题讨论】:

您的意思是在第一次打印时使用"%d"?怎么了? 不,这是一个小错误,但不是主要问题,我更新了问题 您的具体问题是什么? -- 在指针数组的最后一个元素之后将指针传递给函数。我确定这不是您想要的。 您正在向函数传递a最后一个 元素的地址,这也是错误的类型。你应该在这里收到一堆警告。 对不起,如果问题不够清楚,我的目的是打印 a[1] 和 a[0] 中的值,但我只是遇到了一些错误,我要走了编辑添加这些的问题。 【参考方案1】:

编译器没有发现任何错误,但我根本没有在终端中得到任何输出。

那是因为你传递的地址不是你的函数所期望的。

function(&a[MAX]);

您正在传递数组a 中索引MAX 处的项目地址,但您的函数将其解释为整个数组的地址。你应该写:

function(a)

您似乎混淆了参数的声明方式和函数调用中的使用方式。当你声明一个函数时,你必须指定参数的类型,所以你说例如char *s[] 表示指向字符的指针数组。但是当你调用一个函数时,编译器已经知道函数期望的类型,所以你只需要传递一个与声明类型匹配的变量。此上下文中的方括号,如a[MAX],被解释为选择数组的一个元素的下标。

旁白:就风格而言,function 是一个糟糕的函数名称。我知道这只是一个很小的测试程序,所以没什么大不了的,但要养成给事物起描述性名称的习惯。

还有:

printf("%s",*a[1]);
printf("%s",*a[0]);

在这里,您正在访问索引 1 处的项目,但您还没有在那里存储任何内容。这不是一个好计划。要么删除第一行,要么更改代码以将某些内容存储在索引 1 中。

此外,您不需要取消引用元素。数组中的每个元素都是一个字符数组,printf() 将期望char * 类型的值,这就是每个a[n] 的值。所以只需使用:

printf("%s", a[1]);
printf("%s", a[0]);

【讨论】:

是否将数组称为 function(a) ,将整个数组数组赋予函数? p.s.我确实分配了 a[1],但我尝试在函数内部执行它以测试它是如何工作的。 抱歉,错过了a[1]。无论如何,是的,将数组称为 a 提供了数组的值,它实际上只是第一个元素的地址(索引 0 处的那个)。出于同样的原因,您的 printf() 语句应将字符串引用为例如a[0],不是*a[0]*a[0] 是数组中第一个字符串的第一个字符。请注意我刚才的编辑添加了这一点。 谢谢,这似乎有效!如果我想在函数中访问字符串 a[0] 的第三个字母怎么办? 有更短的方法,但最好在学习时保持简单:char *s = a[0]; char c = s[2];【参考方案2】:

你需要传递数组的指针,即

function(a)

【讨论】:

【参考方案3】:

您似乎对正在使用的指针及其正确类型有些困惑。希望下面的程序可以解决一些问题。 cmets中有解释:

#include <stdio.h>

#define MAX 100

void function(char* (*aPtr)[MAX])

    // Since aPtr is a pointer, we need to derefecence it with * before assigning
    // string literals
    (*aPtr)[1] = "test1";
    printf("In function\n");
    printf("%s\n",(*aPtr)[0]);
    printf("%s\n\n",(*aPtr)[1]);


void function2(char** a)

    // Remember, * and [] can both be used to dereference in C
    // This is equivalent to *(a+2) = "test2";
    a[2] = "test2";
    printf("In function2\n");
    printf("%s\n",a[0]);
    printf("%s\n",a[1]);
    printf("%s\n\n",a[2]);


int main(void)

    // This is an array of MAX char pointers. Just on declaration, each pointer in the array
    // points to nothing. You can point them to a string literal (as you have done), or use
    // something like malloc to allocate space for each one
    char *a[MAX];
    // This is a pointer to an array of MAX char pointers. This is the type you're trying to
    // pass to `function`, which is not used correctly
    char* (*aPtr)[MAX] = &a;
    // I've included these prints so you can see the difference between `a` and `aPtr` via pointer
    // arithmetic. In this printf, `a` "decays" to a pointer to the first element in the array.
    // The first element of the array is a `char*`, so a pointer to that is a `char**`, so
    // that's what `a` is in this context, pointing to a[0]. What the actual address is here isn't
    // important, just think of this as offset 0
    printf("pointer to first element      = %p\n", (void*)a);
    // This is the explicit address of the first element in the array. Notice how it is
    // identical to the address of the array above.
    printf("address of first element      = %p\n", ((void*)&(a[0])));
    // This illustrates the "decay" concept again. `a` decays to a `char**`, and +1 on that
    // shows pointer arithmetic. On this architecture, pointers are 8 bytes, so a+1
    // advances the pointer by 8 bytes, which points to the 2nd element in the array.
    // This output will be the offset +8
    printf("pointer to second element     = %p\n", (void*)(a+1));
    // This shows the address of aPtr. Remember, this is a pointer to an array of char
    // pointers 100 large. This base address is also the address of where the array starts,
    // so it will be identical to offset
    printf("address of array              = %p\n", (void*)aPtr);
    // This is where the different pointer types are illustrated. Since char pointers are 8
    // bytes on this architecture, an array of 100 of them is 8*100 = 800 bytes. So aPtr+1
    // here performs pointer arithmetic on that type, meaning it advances the pointer 800
    // bytes. The print out here will be offset +800.
    printf("pointer to next array element = %p\n\n", (void*)(aPtr+1));

    // assign a[0] to point to the string literal "test0"
    a[0] = "test0";

    // This is what you're trying to do (but doing incorrectly) with your function call.
    // This passes the address of `a`, a pointer to an array of char pointers 100 large.
    // This is identical to passing `&a`, the address of `a`.
    function(aPtr);
    // `a` in this context "decays" to a pointer to its first element. Its first element is
    // `char*`, so here `a` is `char**`. And this is the signature you'll find in function2
    function2(a);

    // print out in main to show all the assignments were made
    printf("in main\n");
    printf("%s\n",a[0]);
    printf("%s\n",a[1]);
    printf("%s\n",a[2]);

    return 0;

Demo

【讨论】:

哇!多么详细的答案,谢谢!我仍然有疑问,如果在函数 2 中我想要 a[0] 的第三个字母怎么办? @Pinguiz 我总是需要考虑指向数组的指针,我和你一样清楚地说明了这一点。第一个字符串的第三个字母是a[0][2]。在function2 中,achar**,所以a[0] 是第一个char*a[0][2] 是第三个char 与第一个char* 的偏移量。您可以转到演示链接并在该沙盒中玩,不要忘记"%c" 是打印char 的格式说明符。

以上是关于在函数中使用字符串数组的主要内容,如果未能解决你的问题,请参考以下文章

在 Typescript 中,如何声明一个返回字符串类型数组的函数?

如何打印不带括号的字符串数组,以便可以在函数参数中使用

mysql中怎么存储数组?在线等!急!

如何使用交换函数和指针反转字符串数组? (C++)

C ++:从函数、返回类型或引用中使用和返回字符数组?

C++ 数组与字符串⁽²³⁾|函数与数组