我已经定义了一个指向结构的指针数组,当我尝试扫描到字段时,我收到一条错误消息,并且我不明白我做错了什么。
我尝试了不同的方法-Cannont run program "PATH": error=32, Broken pipe
或scanf("%s",arr[i]->code);
-仍然不起作用。
这是我的代码的开头:
scanf("%s",(*(arr+i))->code);
答案 0 :(得分:2)
尽管您确实声明了department
数组,但没有分配每个department
的内存。
您可以在要填充数组的循环内执行此操作:
for (i = 0; i < N; i++)
{
arr[i] = malloc(sizeof(department));
/* .. */
}
评论中提到的一种更清洁的解决方案,一次分配就足够了:
department *arr = malloc(sizeof(department) * N);
别忘了释放分配的内存并检查malloc
的返回值。
答案 1 :(得分:0)
您的当前问题是尝试将值分配给无效的内存位置。您的声明:
department *arr[N];
声明指向结构DEPARTMENT [N] 的指针的数组(例如,指向struct的5个指针)。但是,这些指针中的每一个都是未初始化的,并且指向不确定的内存位置。请记住,指针只是一个普通变量,其将其他内容的地址保存为作为其值,并且就像普通变量一样,它保留不确定的值,直到分配了一个为止。
就像声明的任何其他局部变量一样,在值不确定时访问该值的任何尝试都会导致未定义行为。要使用指针数组,必须将每个指针的起始地址分配给有效内存块作为其值。在这里,由于您的意图是为N
结构提供存储,所以无需声明N
指针,然后为N
结构单独分配存储。您只需声明一个指向结构的指针,然后在单个内存块中为N
结构分配存储空间,例如
#define N 5
...
typedef struct {
char code[MAXC];
int sales;
} department;
...
department *arr; /* declares a pointer to struct */
...
/* allocate/validate storage for N struct */
if ((arr = malloc (N * sizeof *arr)) == NULL) {
perror ("malloc-arr");
return 1;
}
(注意:每次分配总是 验证 )
在单个块中为N
结构分配存储的优点是提供单个free()
来释放分配的内存块。
就像您必须 验证 每个分配一样,您必须 验证 每个用户输入。这意味着您至少必须验证所有归还给scanf
的情况。但是,您使用scanf
有一个缺点。 scanf
的输入非常脆弱,因为输入的任何变化都将导致 matching 失败,从stdin
提取字符将在 matching 失败发生,将令人反感的字符留在stdin
中,未读,只是在您下次致电scanf
时再次咬你。此外,如果在有效输入之后有任何无意的字符,它们也将保留为stdin
未读。
您的选择是在每次输入后清空stdin
,以确保不留下任何令人反感的字符,或者更好的选择是每次使用面向行的输入函数,例如fgets()
或POSIX getline()
,然后从填充的缓冲区中解析所需的值。这有很多好处。每个输入都会读取并丢弃所有多余的字符。您还可以从独立验证(1)读取中受益; (2)从缓冲区解析所需信息。您可以使用sscanf
来解析已填充缓冲区中的信息,就像使用scanf
来读取stdin
一样。
将其放在一起,您可以像下面这样重写代码:
#include <stdio.h>
#include <stdlib.h>
#define N 5
#define CODESZ 12 /* if you need more than 1 constant, define them */
#define MAXC 1024 /* (don't skimp on buffer size) */
typedef struct {
char code[MAXC];
int sales;
} department;
int main()
{
department *arr; /* declares a pointer to struct */
char buf[MAXC]; /* buffer to hold each line */
int i, ndx = 0;
/* allocate/validate storage for N struct */
if ((arr = malloc (N * sizeof *arr)) == NULL) {
perror ("malloc-arr");
return 1;
}
printf("Enter values for %d departments:\n", N);
while (ndx < N) { /* loop until info for N departments received */
printf ("\nThe %d department-\n Code : ", ndx + 1);
if (fgets (buf, MAXC, stdin) == NULL ||
sscanf (buf, "%11s", arr[ndx].code) != 1)
break;
fputs (" Sales : ", stdout);
if (fgets (buf, MAXC, stdin) == NULL ||
sscanf (buf, "%d", &arr[ndx].sales) != 1)
break;
ndx++;
}
puts ("\nDepartment Sales Results:\n");
for (i = 0; i < ndx; i++) /* output results, free memory */
printf ("Dept Code: %-12s Sales: %d\n", arr[i].code, arr[i].sales);
free (arr); /* don't forget to free what you allocate */
}
(注意:)使用了一个单独的索引计数器ndx
,即使用户在输入后取消输入(例如3个部门,而不是3个部门),它也可以提供填充的实际结构数的计数5)
使用/输出示例
$ ./bin/allocstructloop
Enter values for 5 departments:
The 1 department-
Code : 001
Sales : 123
The 2 department-
Code : 002
Sales : 234
The 3 department-
Code : 003 -- this department met sales goals.
Sales : 345
The 4 department-
Code : 004
Sales : 456 -- this department exceeded sales goals.
The 5 department-
Code : 005 -- this department had most sales for period.
Sales : 567
Department Sales Results:
Dept Code: 001 Sales: 123
Dept Code: 002 Sales: 234
Dept Code: 003 Sales: 345
Dept Code: 004 Sales: 456
Dept Code: 005 Sales: 567
请在输入后尝试输入其他文本(甚至略微敲击键盘),并查看代码的响应方式。准备好 Ctrl + C 。
仔细检查一下,如果还有其他问题,请告诉我。