我创建了该类型的结构和指针。我使用malloc为它分配了内存,但是当我尝试为它实际分配一些值时(特别是读取整数并从文件中浮点数),这给了我一个分段错误,说“在 somelocation的“ ungetwc()没有可用的源“”。
以下是有关指针和结构的代码部分:
typedef struct {
int *rain;
float *avgtemp;
float *avgwind;
} weather;
weather *year = (weather*) malloc(n*sizeof(weather));
if (year == NULL)
{
return 1;
}
for (i = 0; i!=12; i++)
{
fscanf(infile, "%i %f %f", (year+i)->rain, (year+i)->avgtemp, (year+i)->avgwind);
}
我以为可能是fscanf中缺少&的问题,但是当我添加它时,我的IDE会警告我应该提供int *,但是会提供int **。
答案 0 :(得分:1)
根据您的代码,这是必需的:
typedef struct {
int *rain;
float *avgtemp;
float *avgwind;
} weather;
weather *years = malloc(n * sizeof(weather));
if (year == NULL) {
return 1;
}
weather *year = years;
for (i = 0; i < n; ++i, ++year) {
year->rain = malloc(sizeof(int));
year->avgtemp = malloc(sizeof(float));
year->avgwind = malloc(sizeof(float));
fscanf(infile, "%i %f %f",
year->rain, year->avgtemp, year->avgwind);
}
但是,我真正想要的是不在struct
内使用指针:
typedef struct {
int rain;
float avgtemp;
float avgwind;
} weather;
weather *years = malloc(n * sizeof(weather));
if (year == NULL) {
return 1;
}
weather *year = years;
for (i = 0; i < n; ++i, ++year) {
fscanf(infile, "%i %f %f",
&year->rain, &year->avgtemp, &year->avgwind);
}
更新:
是的,我只是从结构中删除了指针,它确实解决了我遇到的所有问题。也许我误解了我教授的话。
也许。第一种方法(即您的版本) 对于某些更复杂的用例有效。例如,如果struct
的字符串为char *
,则字符串长度可以任意长。
第二个版本更惯用,更易于使用。
否则,在代码中的其他任何地方,访问元素时,我们都将使用int rain = *year->rain;
而不是[更简单的int rain = year->rain;
如果struct
成员之一需要作为值的数组(例如),则该结构用于每年报告,我们需要(例如)每月每月的降雨量(相对于一年中的累计降雨量),rain
再次达到int *rain;
可能是可以的。但是,鉴于此,由于一年中的月数是固定的,因此我们可以执行:int rain[12];
以保持简单性。
答案 1 :(得分:0)
在您的代码中,您仅为结构分配了内存,但是该结构的字段仍在“等待”地址分配。指针只是内存中地址的别名,而且由于操作该地址更易于阅读。
有一些方法可以解决您的问题。我创建了四个不同的函数,并使用了两种不同类型的结构。
代码:
#include <stdio.h>
#include <stdlib.h>
typedef struct {
int rain;
float avgtemp;
float avgwind;
} weather;
typedef struct {
int *rain;
float *avgtemp;
float *avgwind;
} weatherp;
/* Obtain amount of items in array (implemented in <sys/params.h> header). */
#define nitems(x) (sizeof((x)) / sizeof((x)[0]))
/* Ex. 1: Using array of defined size. */
void
first_option()
{
weather year[2];
int ii;
for (ii = 0; ii < nitems(year); ii++) {
fscanf(stdin, "%d %f %f", &year[ii].rain, &year[ii].avgtemp, &year[ii].avgwind);
}
for (ii = 0; ii < nitems(year); ii++) {
fprintf(stdout, "%d %f %f\n", year[ii].rain, year[ii].avgtemp, year[ii].avgwind);
}
}
/* Ex. 2: Using malloc(3). */
void
second_option()
{
const int n = 2;
weather *year = (weather *)malloc(n * sizeof(weather));
int ii;
for (ii = 0; ii < n; ii++) {
fscanf(stdin, "%d %f %f", &year[ii].rain, &year[ii].avgtemp, &year[ii].avgwind);
}
for (ii = 0; ii < n; ii++) {
fprintf(stdout, "%d %f %f\n", year[ii].rain, year[ii].avgtemp, year[ii].avgwind);
}
free(year);
}
/* Ex. 3: Values in struct are pointers. */
void
third_option()
{
const int n = 2;
weatherp *year = (weatherp *) malloc(n * sizeof(weatherp));
int ii;
for (ii = 0; ii < n; ii++) {
year[ii].rain = (int *)malloc(sizeof(int));
year[ii].avgtemp = (float *)malloc(sizeof(float));
year[ii].avgwind = (float *)malloc(sizeof(float));
fscanf(stdin, "%d %f %f", year[ii].rain, year[ii].avgtemp, year[ii].avgwind);
}
for (ii = 0; ii < n; ii++) {
fprintf(stdout, "%d %f %f\n", *year[ii].rain, *year[ii].avgtemp, *year[ii].avgwind);
}
for (ii = 0; ii < n; ii++) {
free(year[ii].rain);
free(year[ii].avgtemp);
free(year[ii].avgwind);
}
free(year);
}
/* Ex. 4: Using array of defined size but struct fields are pointers. */
void
fourth_option()
{
weatherp year[2];
int ii;
for (ii = 0; ii < nitems(year); ii++) {
year[ii].rain = (int *)malloc(sizeof(int));
year[ii].avgtemp = (float *)malloc(sizeof(float));
year[ii].avgwind = (float *)malloc(sizeof(float));
fscanf(stdin, "%d %f %f", year[ii].rain, year[ii].avgtemp, year[ii].avgwind);
}
for (ii = 0; ii < nitems(year); ii++) {
fprintf(stdout, "%d %f %f\n", *year[ii].rain, *year[ii].avgtemp, *year[ii].avgwind);
}
for (ii = 0; ii < nitems(year); ii++) {
free(year[ii].rain);
free(year[ii].avgtemp);
free(year[ii].avgwind);
}
}
int
main()
{
first_option();
second_option();
third_option();
fourth_option();
return (0);
}
在functon first_option()中,我定义了结构的两元素数组(定义为weather
类型)。数组和结构字段都已经分配了内存,因为我没有使用字段作为指针,而是使用int
/ float
类型的实例。
在functon second_option()中,我定义了包含天气结构实例的指针。结构字段已经分配了内存,因为在结构内部我没有使用字段作为指针。存在int
/ float
类型的实例。但是我必须为指针分配内存。与前面的示例相比,我没有结构数组,因此必须创建它。因此,我为n
结构的weather
实例分配内存。就像为几个数据框(包含一些重要信息的容器/结构)创建几个(n)个架子一样。
毕竟,应该通过free(3)
函数释放由malloc分配的内存。
在functon third_option()中,我既没有为数组字段又为结构字段定义内存。如您所见,现在我使用了新创建的weatherp
类型。在这种情况下,我必须为结构字段和数据框(数组)的“架子”分配内存。因此,我为n
结构的weatherp
实例分配内存,然后在使用fscanf(3)
之前,我分别为每个结构字段分配内存。毕竟,应该使用malloc(3)
(每个struct字段,最后是struct实例的容器)释放free(3)
分配的内存。
最后一个函数 fourth_option()定义了结构的两元素数组(定义为weather
类型),但是结构的字段尚未分配内存。因此,在使用fscanf(3)
之前,我分别为每个结构字段分配了内存。毕竟,应该使用malloc(3)
释放free(3)
分配的内存。
一些其他信息:
声明为int a;
,struct type name;
或char tab[10];
的变量的每个地址已经在栈上动态分配了内存,并且该函数在函数结束后自动“释放”。手动分配的空间(例如,使用malloc(3)
)会在堆上分配,直到调用free(3)
函数。如今,程序结束后的操作系统内核可以释放手动分配的内存,但是一种很好的做法是消除内存泄漏,这表明您知道自己在做什么。
PS。在测试期间,我将月份的数量从12替换为2,并从stdin
而非文件中读取数据。当然,我们应该检查类似函数执行成功的事情(例如,malloc(3)
调用之后的指针是否不是NULL
)。我只是不想使代码复杂化。