scanf到结构中字段的问题

问题描述 投票:0回答:2

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

我尝试了不同的方法 - scanf("%s",arr[i]->code);scanf("%s",(*(arr+i))->code); - 它仍然无效。

这是我的代码的开头:

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

#define N 5

typedef struct DEPARTMENT
{
    char code[11];
    int sales;
}
department;

int main()
{
    department *arr[N];
    int i;
    printf("Enter values for %d departments:", N);
    for (i = 0; i < N; i++)
    {
        printf("\nThe %d department-", (i + 1));
        printf("\nCode:");
        scanf("%s",(arr[i])->code);
        printf("\nNumber of sales:");
        scanf("%d", &((arr[i])->sales));
    }
}
c arrays pointers struct scanf
2个回答
2
投票

你确实声明了你的qazxsw poi数组,你没有分配每个qazxsw poi的记忆。

您可以在循环中执行此操作,在此处填充数组:

department

如评论中提到的更清洁的解决方案,一个分配就足够了:

department

别忘了释放分配的内存并检查for (i = 0; i < N; i++) { arr[i] = malloc(sizeof(department)); /* .. */ } s的返回值。


0
投票

您当前的问题是尝试将值分配给无效的内存位置。你的声明:

department *arr = malloc(sizeof(department) * N);

声明一个指向struct DEPARTMENT [N]的指针数组(例如指向struct的5个指针)。但是,每个指针都是未初始化的,并指向不确定的内存位置。请记住,指针只是一个普通变量,它将其他东西的地址保存为其值,就像普通变量一样,它保持一个不确定的值,直到分配一个。

就像声明的任何其他局部变量一样,在值不确定时访问该值的任何尝试都会导致未定义的行为。要使用指针数组,必须将每个指针的起始地址分配给有效的内存块作为其值。在这里,由于您的目的是为malloc结构提供存储,因此无需声明 department *arr[N]; 指针,然后独立地为N结构分配存储空间。您可以简单地声明一个指向struct的指针,然后在单个内存块中为N struct分配存储空间,例如:

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中的违规字符未读,只是等待你在下次调用stdin时再次咬你。此外,如果有任何跟随有效输入的无意字符,它们也会保持在未读的stdin中。

您的选择是在每次输入后清空scanf以确保没有任何违规字符,或者,更好的选择是每次使用stdin或POSIX stdin等面向行的输入函数读取完整的输入行,然后解析您需要的值从填充的缓冲区。这有很多好处。每个输入都会读取和丢弃任何无关的字符。您还可以独立验证(1)读取; (2)从缓冲区中解析所需信息。您可以使用fgets()来解析填充缓冲区中的信息,就像使用getline()sscanf读取一样。

完全放在那里,您可以重写您的代码,如下所示:

scanf

(注意:使用单独的索引计数器stdin,它提供了即使用户在输入后取消输入也填充的实际结构数的计数,例如3个部门而不是5个)

示例使用/输出

#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 */
}

输入后尝试输入附加文本(甚至还有一个额外的击键)并查看代码的响应方式。保持Ctrl + C准备就绪。

仔细看看,如果您有其他问题,请告诉我。

© www.soinside.com 2019 - 2024. All rights reserved.