我在结构c中丢失了值

问题描述

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

#define stock_dir "/Users/myname/prices/"
#define file_list "/Users/myname/trade/trade/nasdaq100_stock_list.txt"
#define look_back_period 3
#define num_stocks 103
#define days_of_data 21

int main()
{
    FILE *stocks,*stk;
    char stock[11],fullpath[50] = "\0",header[25];
    char line_of_data[40];
    char *sclose,*svol;
    int n = 0,i = 0;
    typedef struct daily_data {
        char  *date;
        float close;
        int vol;
    }data;
    
    sclose = (char*) malloc(20*sizeof(char));
    svol =  (char*) malloc(20*sizeof(char));
    
    data** day_data = (data**) malloc(num_stocks*sizeof(data*)  );
   
    if (day_data == NULL)
        {
        printf("day_data not allocated\n");
        exit(0);
        }

    for(i = 0; i < num_stocks; i++)
        if ((day_data[i] = (data*)malloc(days_of_data*sizeof(data))) == NULL)
        {
        printf("data[%d] not allocated\n",i);
        exit(0);
        }

    for(i = 0; i < num_stocks; i++)
      for(n = 0; n < days_of_data; n++)
       
          if ((day_data[i][n].date = (char*)malloc(20)) == NULL)
          {  printf("data[%d][%d] not allocated\n",i,n);
             exit(0);
          }

    /* ... code omitted ... */

    if ( (stocks = fopen(file_list,"r") )== NULL)
        printf("didn't open file list\n");
    i = 0;
 
    while (fgets(stock,sizeof(stock),stocks) != NULL)
    {
       printf("%s",stock);
       strcpy(fullpath,stock_dir);
        strcat(fullpath,stock);
        fullpath[strcspn(fullpath,"\n")] = 0;
        if ( (stk = fopen(fullpath,"r") )== NULL)
               printf("didn't open quote list\n");
        fgets(header,sizeof(header),stk);
        n=0;
        while(fgets(line_of_data,sizeof(line_of_data),stk) !=NULL)
            {
                fgets(line_of_data,stk);
                day_data[i][n].date = strtok(line_of_data,",");
                sclose = strtok(NULL,");
                day_data[i][n].close = atof(sclose);
                svol = strtok(NULL,");
                day_data[i][n].vol = atoi(svol);;
                printf("%s %f %d\n",day_data[i][n].date,day_data[i][n].close,day_data[i][n].vol);
              n++;
            }
    
        fclose(stk);
        i++;
    }
             
   for (n = look_back_period - 1; n  < (days_of_data  - look_back_period); n++)
      printf("%d %s  %f %d\n",n,day_data[1][n].date,day_data[1][n].close,day_data[1][n].vol);
    
}

while(fgets(line_of_data,stk) !=NULL)循环中的print语句显示所有内容都放入正确的位置。但是当我在外面打印值时,它们大多是错误的。我应该添加更多详细信息,但我不知道该说些什么。退出循环后,我会丢失结构中的值。

解决方法

您一次又一次地覆盖相同的数据。

看看您的结构:

    typedef struct daily_data {
        char  *date;  ///< a pointer without own storage
        float close;
        int vol;
    }data;

在处理文件时,您将每一行读入line_of_data

while(fgets(line_of_data,sizeof(line_of_data),stk) !=NULL)

您标记line_data并将指针分配给data->date

day_data[i][n].date = strtok(line_of_data,",");

标记化(strtok reference)的作用是在输入字符串中插入终止符,并将指针返回到输入的新部分的开头。因此,此时没有分配新的内存。返回的指针指向您的输入字符串。

有效地将局部变量指针分配给数据存储结构。

此外,您还会丢失指向date指针的初始分配内存的指针。

我建议您删除date的先验分配,并在您真正知道所需长度的点上分配所需的内存,或者如果您确定知道最大长度,则可以date成员是一个数组。

因此,您要么必须分配新的内存并复制标记化的数据,要么如果您将date设置为固定大小的数组,则只需复制标记化的数据即可。

第一个变体看起来像这样

  char * tok = strtok(line_of_data,");
  day_data[i][n].date = malloc(strlen(tok)+1);
  strcpy(day_data[i][n].date,tok); 

(+删除date成员的预分配)

或第二个变体:

data更改为

    typedef struct daily_data {
        char  date[20];
        float close;
        int vol;
    }data;

,处理代码如下:

  char * tok = strtok(line_of_data,");
  strcpy(day_data[i][n].date,tok); 

(+(当然是删除date成员的预分配)

在任何情况下,如果标记字符串超过最大长度或行格式与预期不符(缺少定界符,错误/无效数字(格式),...),您还应添加错误处理。

相关问答

依赖报错 idea导入项目后依赖报错,解决方案:https://blog....
错误1:代码生成器依赖和mybatis依赖冲突 启动项目时报错如下...
错误1:gradle项目控制台输出为乱码 # 解决方案:https://bl...
错误还原:在查询的过程中,传入的workType为0时,该条件不起...
报错如下,gcc版本太低 ^ server.c:5346:31: 错误:‘struct...