gpt4 book ai didi

c - 将内存分配给在 C 中声明为结构成员的二维数组?

转载 作者:太空宇宙 更新时间:2023-11-04 08:17:50 25 4
gpt4 key购买 nike

我想做什么?

我正在尝试将内存分配给声明为结构成员的 char 类型二维数组。

问题是什么?

我不知道该怎么做。

我的代码:

  # include <stdio.h>
# include <stdlib.h>
# include <conio.h>

typedef struct information {
int id ;
char **name ;
} info ;

void main () {
info s1 ;
int i , size ;
printf ("\n Enter max size of students name : ") ;
scanf ("%d",&size) ;
s1.name = ( char** ) malloc ( size * sizeof ( char* ) ) ;
for ( i = 0 ; i < size ; i++ )
s1.name [ i ] = ( char** ) malloc ( size * sizeof ( char* ) ) ;
printf ("\n Enter Id : ") ;
scanf ("%d",&s1.id) ;
printf ("\n Enter Name : ") ;
scanf ("%s",s1.name) ;
getche () ;
}

这样对吗?我是否正确分配了它?

我也想知道为什么我们在获取字符串形式的输入时不使用&。例如,我在倒数第三行的代码中,为什么不能这样写: scanf ("%s",&s1.name); ?

最佳答案

正如评论中所解释的,如果指针不是结构的成员,您将分配/释放完全相同。虽然看起来您不需要 char **name (pointer-to-pointer-to-char) 除非一个 id 与许多名字。只需声明一个指向名称的指针(例如 char *name;)就足以提供与 id一对一关系。

将这些部分放在一起,并调整scanf格式说明符 以在读取size 后读取/丢弃尾随换行符,你可以这样做:

# include <stdio.h>
# include <stdlib.h>
// # include <conio.h>

typedef struct information {
int id ;
char *name ;
} info ;

int main (void) {

info s1;
int size;

printf ("\n Enter max size of students name : ");
scanf ("%d",&size);

s1.name = malloc (size * sizeof *s1.name);

printf ("\n Enter Id : ");
scanf ("%d%*c", &s1.id);

printf ("\n Enter Name : ");
scanf ("%[^\n]%*c", s1.name);

printf ("\n You entered, id: %d, name: %s\n\n", s1.id, s1.name);

free (s1.name);

// getche () ;
return 0;
}

示例使用/输出

$ ./bin/struct_stdnm

Enter max size of students name : 29

Enter Id : 231

Enter Name : Alfred Q. Myres

You entered, id: 231, name: Alfred Q. Myres

如果您还有其他问题或需要,请告诉我。

注意:如果你需要一个idname数组,那么你需要一个struct information数组code>,而不是指向 name双指针——如果我解释什么对你所做的正确是有意义的。


防止超出分配的输入

如以下评论所述,scanf 不是读取 s1.name 的最佳选择,因为它不允许变量的最大字段宽度。为了正确防止超出分配末尾的写入,您应该使用 fgets 并将读取限制为 size:

printf ("\n Enter Name : ");
fgets (s1.name, size, stdin);

示例

$ ./bin/struct_stdnm

Enter max size of students name : 5

Enter Id : 123

Enter Name : Johnny Jones

You entered, id: 123, name: John

所有分配和输入都需要验证

无论您是坚持使用 scanf 进行输入还是使用 fgets,您都必须验证所有分配和输入以确保您实际分配你打算使用的内存,你实际上读了你认为你读过的东西。认为这只是代码完整性的另一层。虽然学习在没有完全验证的情况下使用示例可能很方便,但在对所有分配和输入进行充分检查之前,您永远不应认为您的代码是完整的。这是一个更新,显示对您的代码进行最少的验证检查:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
// # include <conio.h>

typedef struct information {
int id ;
char *name ;
} info ;

int main (void) {

info s1;
int size;
size_t len;

printf ("\n Enter max size of students name : ");
if (scanf ("%d",&size) != 1) { /* validate converison */
fprintf (stderr, "error: conversion of size failed.\n");
return 1;
}
if (size < 1) { /* validate size */
fprintf (stderr, "error: invalid size entered.\n");
return 1;
}

/* always validate allocations */
if (!(s1.name = malloc (size * sizeof *s1.name))) {
fprintf (stderr, "error: virtual memory exhausted.\n");
return 1;
}

printf ("\n Enter Id : ");
if (scanf ("%d%*c", &s1.id) != 1) { /* validate converison */
fprintf (stderr, "error: conversion of size failed.\n");
return 1;
}

printf ("\n Enter Name : ");
if (fgets (s1.name, size, stdin)) {
len = strlen (s1.name);

/* validate all characters fit within 'size' allocation */
if (len + 1 == (size_t)size && (s1.name)[len-1] != '\n')
printf (" warning: name exceeded allocation.\n");

/* remove trailing newline from name */
if (len && (s1.name)[len-1] == '\n')
(s1.name)[--len] = 0;
}
else {
fprintf (stderr, "error: name entry failed.\n");
return 1;
}

printf ("\n You entered, id: %d, name: %s\n\n", s1.id, s1.name);

free (s1.name);

// getche () ;
return 0;
}

当您没有分配足够的空间来容纳输入的整个名称时,这也会标记:

短分配示例

$ ./bin/struct_stdnm

Enter max size of students name : 5

Enter Id : 123

Enter Name : Johnny Jones
warning: name exceeded allocation.

You entered, id: 123, name: John

如果您还有其他问题,请告诉我。

关于c - 将内存分配给在 C 中声明为结构成员的二维数组?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/34846697/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com