【问题标题】:how do I assign individual string to an element in one array of pointer?如何将单个字符串分配给一个指针数组中的元素?
【发布时间】:2020-06-02 22:46:24
【问题描述】:

我是 C 新手,但仍在尝试找出指针。

所以这是我陷入的一项任务:我想将 10 个水果名称分配给数组指针并一个一个打印出来。以下是我的代码;

#include <stdio.h>
#include <string.h>

int main(){
    char *arr_of_ptrs[10];
    char buffer[20];
    int i;
    for (i=0;i<10;i++){
        printf("Please type in a fruit name:");
        fgets(buffer,20,stdin);
        arr_of_ptrs[i]= *buffer;
    }
    int j;
    for (j=0;j<10;j++){
        printf("%s",*(arr_of_ptrs+j));
    }

}

但是执行此操作后,它只显示所有 10 个响应的最后一个结果。我试图咨询其他人提出的类似问题,但没有运气。

我的理解是 1) 数组的指针已经用 [10] 分配了内存,所以不需要 malloc()。

2) 缓冲区存储指向每个单独答案的指针,因此我取消引用它并将其分配给 arr_of_ptrs[i] 我不确定 arr_of_ptrs[i] 是否给我一个指针或一个值。我认为它绝对是一个指针,但我用 * 代码尊重它并将它分配给 *buffer,程序会卡住。

如果有人能指出我的问题,那就太好了。

提前致谢

【问题讨论】:

  • arr_of_ptrs[i]= *buffer; 应该会发出一个巨大的警告。那就是将char 分配给char*,无论发布的问题如何,这都是错误的。
  • 试试:arr_of_ptrs[i]= strdup(buffer);。也就是说,复制每个数组条目要引用的字符串。当不再需要时,不要忘记free每个数组指针。

标签: c arrays pointers memory malloc


【解决方案1】:

三个错误,1.你必须为arr_of_ptrs的元素分配内存,现在你只在堆栈内存上为arr_of_ptrs的元素分配内存。 2. arr_of_ptrs[i]= *buffer; 表示所有 arr_of_ptrs 元素都指向同一个内存地址,即“缓冲区”指针。因此 arr_of_ptrs 的所有元素都将与最后一个 stdin 输入字符串相同。 3.后续fgets()调用有潜在问题,其中一种解释可能是here

可以快速解决,

#include <stdio.h>
#include <string.h>

int main(){

    const int ARR_SIZE = 10, BUFFER_SIZE = 20;
    char arr_of_ptrs[ARR_SIZE][BUFFER_SIZE];
    char *pos;
    int i, c;

    for (i = 0; i < ARR_SIZE; ++i) {
        printf ("Please type in a fruit name: ");
        if (fgets (arr_of_ptrs[i], BUFFER_SIZE, stdin) == NULL) return -1;
        if ((pos = strchr(arr_of_ptrs[i], '\n')))
            *pos = 0;
        else
            while ((c = getchar()) != '\n' && c != EOF) {}
    }
    for (i = 0; i < ARR_SIZE; ++i)
        printf("%s\n", arr_of_ptrs[i]);

    return 0;
}

【讨论】:

  • 如果你不想处理第三个问题,并且在你的环境中有足够的内存,只需让 BUFFER_SIZE 足够大以容纳域中的所有字符串。
  • 它有效,但我想知道,在从标准输入收集每个字符之后,变量 c 如何被放入 arr_of_ptrs[i] 中的每个元素中?该解决方案还建议在分配内存后使用 strcpy() 。有什么潜在的问题吗?干杯
  • @James 1. 变量 c 处理缓冲区溢出问题。假设代码是 fgets(str, 5, stdin),它读取 5 个字节,然后输入“abcdef”,str 将在“abcd”结尾加上一个 '\0',总共 5 个字节。此时调用 next fgets(str, 5, stdin),str 以“ef”开头,因为“ef”是上次调用的剩余字符。如果用户输入的时间长于指定的 fgets(),则变量 c 用于“吃掉”stdin 中的剩余字符。变量 c 与 arr_of_ptrs 没有关系。您可以运行您的旧程序,尝试输入一个超过 20 个字符的字符串,然后查看问题。
  • @James 2. 您始终可以在您的 linux 终端上输入“man strcpy”,请参阅 Linux 手册页的“BUGS”部分,它列出了所有潜在问题,包括它是否是线程安全的等。 Linux 手册页是了解 API 的官方资源之一。作为一个学习者,我建议你自己做一个 malloc() 和 strcpy() 的解决方案,因为在实际工作中,大多数时候大型数组需要进入堆而不是堆栈。在嵌入式软件中,堆栈的帧大小可能非常小。
【解决方案2】:

误解可能是“取消引用”一个字符数组,与取消引用指向原始数据类型的指针不同,它不会创建该数组的副本。无法使用赋值运算符=复制数组;有一个单独的函数用于复制数组(特别是对于以 0 结尾的 char 又名 c 字符串数组,以及分配复制所需的内存):

比较指向原始数据类型的指针,例如int

int x = 10;
int *ptr_x = &x;
int copy_of_x = *ptr_x;  // dereferences a pointer to x, yielding the integer value 10

但是:

char x[20] =  "some text";  // array of characters, not a single character!
char *ptr_x = &x[0];  // pointer to the first element of x
char copy_of_first_char_of_x = *ptr_x;  // copies the 's', not the entire string

用途:

char x[20] = "some text";
char *ptr_x = &x[0];
char *copy_of_x = malloc(strlen(ptr_x)+1);  // allocate memory large enough to store the copy    
strcpy(copy_of_x,ptr_x);  // copy the string.
printf("%s",copy_of_x);

输出:

some text

【讨论】:

  • 你好实际上我阅读的解决方案没有使用 strdup() 而是使用 strcpy() 。它有潜在的问题吗?谢谢!
  • 是的,对于strcpy,您必须确保已为目标分配了足够的内存,即您需要前面的malloc(请参阅编辑后的答案)。 strdup 同时执行 - 分配和复制 - 作为一个命令。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2019-12-17
  • 2016-04-06
  • 1970-01-01
  • 1970-01-01
  • 2020-05-15
  • 2023-03-04
  • 1970-01-01
相关资源
最近更新 更多