我一直在尝试找出如何将来自用户的信息存储在struct的数组中,但到目前为止。。不工作。
我创建了一个结构体,在main函数中我创建了一个指向这个结构体的指针,然后动态地分配这个结构体。但我真的不知道我将如何从用户那里获得信息,我的意思是。我知道,但它并不像预期的那样工作。如果我只使用一个struct数组,它会像这样...
&p[i].id //正常
我试着用这个方法,但不工作,idk为什么...代码还没有完成…
//
// 7.c
// IFTM Exercises
//
// Created by Lelre Ferreira on 8/29/19.
// Copyright © 2019 Lelre Ferreira. All rights reserved.
//
#define size 5
#include <stdio.h>
#include <stdlib.h>
struct produtos {
int id;
int quant;
float vlrs;
char nm[50];
};
void cadastroProdutos (struct produtos *p, int tamanho);
void maiorValorProdutos (struct produtos *p, int tamanho);
void maiorEstoqueProdutos (struct produtos *p, int tamanho);
int main (int argc, const char * argv[]){
struct produtos *p;
int tamanho = 0;
printf("Insira quantidade de produtos/itens a serem cadastrados: ");
scanf("%d", &tamanho);
p = (struct produtos *) malloc(tamanho * sizeof(struct produtos));
cadastroProdutos(p, tamanho);
maiorValorProdutos(p, tamanho);
maiorEstoqueProdutos(p, tamanho);
return 0;
}
void cadastroProdutos(struct produtos *p, int tamanho){
int i = 0;
for (i = 0; i < tamanho; i++) {
printf("Insira o ID: ");
scanf("%d", &p[i] -> id);
printf("Insira o nome: ");
scanf("%s", p[i] -> nm);
printf("Insira o valor: ");
scanf("%f", &p[i] -> vlrs);
printf("Insira a quantidade: ");
scanf("%d", &p[i] -> quant);
}
}
void maiorValorProdutos(struct produtos *p, int tamanho){
}
void maiorEstoqueProdutos(struct produtos *p, int tamanho){
}
IDE出现此错误:无法获取类型为“int”的右值的地址...
3条答案
按热度按时间g9icjywg1#
您没有理解
[..]
运算符应用于您的指针p
(例如:p[0]
)作为解引用,使类型struct produtos
和'.'
运算符正确(而不是@MilesBudnek的回答中提到的struct produtos*
。除了
'.'
或'->'
操作符问题之外,您似乎还没有注意到动态分配的要点。虽然从#define size 5
分配的结构体开始很好,但动态分配内存的要点是能够无缝地处理第6个结构体,方法是根据需要重新分配额外的内存来处理所有输入(或者直到可用内存耗尽)。你现在写的函数
cadastroProdutos
,并不能真正实现一个干净的动态分配(除了它返回void
,并且没有验证其中的任何输入)。与在函数中循环size
次不同,您只想在每次调用cadastroProdutos
时获得相当于1个结构体的数据。这样,您可以根据需要多次调用它,直到输入所有数据。在你的函数中不需要循环,而且你对scanf
的使用是非常脆弱的,因为你没有办法处理由于 * 匹配失败 * 或只是意外输入的流浪字符而留在stdin
中的字符(例如:为id
键入的'a'
,或长于49
字符的名称等)要解决大多数问题,不要对User-Input使用
scanf
,而是将所有User-Input读取到一个合理大小的临时缓冲区(例如:1024
字符左右),然后使用sscanf
从缓冲区解析所需的信息。这样做有双重好处:允许对读取和解析进行单独验证;通过使用合理大小的缓冲区,每次消耗一整行输入,就可以消除无关字符问题(例如猫踩在键盘上)。你的
cadastroProdutos
接受输入,没有提供有意义的返回来指示输入的成功/失败,如果任何一个输入失败,你的函数容易受到 * 未定义行为 * 的影响。因此,通过检查所使用的函数的返回值来验证每个用户输入。对于任何输入失败,对于 failure 返回0
,对于 success 返回非零值,允许您在调用函数中处理任何输入失败。(**注意:**计数类型应该使用
size_t
,而不是int
)将这些更改放在
cadastroProdutos
中,您可以执行类似于以下操作:(注意:
tamanho
作为指针传递,这样它的数字可以在函数内更新,失败时返回0
,而成功时返回更新的tamanho
,允许您有意义地返回size_t
类型)避免在代码中使用 magic-numbers。你为
size
定义了一个常数,现在只需要定义你需要的常数,这样就不会再有像char nm[50];
这样的 * 魔法数字 * 了。要做到这一点,您可以使用更多的#define
,例如。现在,您需要在
main()
中声明一个临时缓冲区来保存该行,以及size_t
值,即当前分配的结构体总数(allocated
)和填充的数字(tomanho
),这导致在每个循环if (tomanho == allocated)
的开始处的简单检查,你知道你需要realloc
额外的结构体之前,试图填补任何更多。main()
函数基本上可以是:在这一点上,你所有的结构体都被填充并存储在
p
中,你需要做的就是你需要做的任何事情(简单地在下面输出),然后free()
你已经分配的内存,例如:在一个简短的例子中,你可以这样做:
(**注意:**增加了一个简单的
add another (y/n)?
提示,以确定用户是否需要添加更多数据)示例使用/输出
上面我们从2-allocated结构开始,然后进入6结构,强制重新分配。例如:
所有数据都正确存储,如果需要,您可以添加1000多个条目。您还应该通过内存错误检查程序(如Linux上的
valgrind
)运行任何使用动态内存的程序,该程序可以告诉您是否不正确地使用了您不拥有的内存块的指针。一个简短的测试,从一个文件中重定向输入,而不是重新输入,可以确认是否存在任何内存问题,使用内存检查器很简单,只要运行你的程序,例如。
8yoxcaq72#
p[i]
是struct produtos
,而不是struct productos*
。这意味着,要访问其成员,您需要使用.
操作符,而不是->
。即这与将
p
定义为main
中的数组没有什么不同。当你把一个数组传递给一个函数时,它会衰减为指向它的第一个元素的指针。例如:从
cadastroProdutos
函数的Angular 来看,这两个调用完全相同。在这两种情况下,它只接收指向数组第一个元素的指针和数组的大小。u2nhd7ah3#
运行这个。看看代码,你就会明白: