用scanf到结构中的字段的问题

时间:2019-04-25 21:36:51

标签: c arrays pointers struct scanf

我已经定义了一个指向结构的指针数组,当我尝试扫描到字段时,我收到一条错误消息,并且我不明白我做错了什么。

我尝试了不同的方法-Cannont run program "PATH": error=32, Broken pipescanf("%s",arr[i]->code);-仍然不起作用。

这是我的代码的开头:

scanf("%s",(*(arr+i))->code);

2 个答案:

答案 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

仔细检查一下,如果还有其他问题,请告诉我。