将数组中的值分配给结构数组

时间:2016-03-06 18:39:40

标签: c arrays struct

我试图将包含所有字符串的数组中的值赋给结构数组,其中一些结构成员是整数。但是,我尝试它的方式会导致一些未定义的行为。像下面的代码生成以下内容:

0 surname ▒▒
1 forename &
2 id 0

应该说什么

0 surname Boatswain
1 forename Michael Jr
2 id 109993267

我不确定我分配这些值的方式有什么不妥。

代码:

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

//There are 7 values for each student
#define VALUES 7

struct Students{
  int term;
  int id; // NEED TO GENERATE ERROR IF WRONG NUM OF CHARACTERS
  char surname[15];
  char forename[15];
  char subject[3];
  int catnum;
  char section[3];
};

int main(int argc, char *argv[]){

//Get contents of input file
  unsigned char filename;
  printf("Enter the input file name: \n");
  scanf("%s", &filename);
  FILE *file = fopen(&filename, "r");
  int filesize=0;
  fseek(file, 0L, SEEK_END);
  filesize = ftell(file);
  fseek(file, 0L, SEEK_SET);
  char *contents = malloc(filesize+1);
  size_t size=fread(contents,1,filesize,file);
  contents[size]=0;  // what does all this do exactly?

//Get number of lines in input file
  int total_line = 0;
  const char *str;
  for(str = contents; *str; ++str)
  total_line += *str == '\n';

//Tokenize string
  int n=0,nn;
  char *b[VALUES*total_line];
  char *ds=strdup(contents);
  b[n]=strtok(ds, ",=\"\r\n\"");
  while(b[n] && n<((VALUES*total_line)-1)) b[++n]=strtok(NULL, ",=\"\r\n\"");
  //for(nn=0; nn<=n; ++nn) printf("%s %d   ", b[nn], nn);
  //putchar('\n');
  free(ds);

  struct Students record[total_line];

  int i, j;
  for(i=0;i++;i<total_line){
    for(j=0;j++;j<VALUES){
      int n=(7*i)+j;
      record[i].term=atoi(b[n]);
      record[i].id=atoi(b[n]);
      strcpy(record[i].surname, b[n]);
      strcpy(record[i].forename, b[n]);
      strcpy(record[i].subject, b[n]);
      record[i].catnum=atoi(b[n]);
      strcpy(record[i].section, b[n]);
    }
  }

// try printing some values here
  printf("0 surname %s\n",record[0].surname); 
  printf("1 forename %s\n",record[1].forename);
  printf("2 id %d\n", record[2].id);

  free(contents);
  return 0;
}

输入文件:

1301,107515018,"Boatswain","Michael R.",CSE, 230,="R01"
1301,109993269,"Castille","Michael Jr",CSE, 230,="R03"
1301,109993267,"Castille","Janice",CSE, 230,="R03"

提前感谢您的帮助!

编辑:更改for循环有什么问题?

for(i=0;i<total_line;i++) { 
  record[i].term=atoi(b[(7*i)]);
  record[i].id=atoi(b[(7*i)+1]);
  strcpy(record[i].surname, b[(7*i)+2]);
  strcpy(record[i].forename, b[(7*i)+3]);
  strcpy(record[i].subject, b[(7*i)+4]);
  record[i].catnum=atoi(b[(7*i)+5]);
  strcpy(record[i].section, b[(7*i)+6]);
}

编辑:我得到了它的工作。只需要将for循环更改为while循环。 编辑2:哦,我有i ++和我的total_line切换。 DERP。现在修好了。嗯,我想这解决了这个谜。

2 个答案:

答案 0 :(得分:2)

b[n]循环中,您要多次转换b[n++]次{。}}。您很可能不需要此循环,而是转换import { browserHistory } from 'react-router' browserHistory.push({});

答案 1 :(得分:2)

作为初步,这一行(显然你已经发现可疑)......

  contents[size]=0;  // what does all this do exactly?

...在从文件读取的字节之后添加一个字符串终止符,因此可以安全地将整个事物解释为一个大的C字符串。

@DavetheSax对您的令牌的索引进行了有效的观察。该问题不会导致未定义的行为,但结果行为肯定不是您想要的。

但是,确实在程序中确实存在未定义的行为。您可以通过将b复制到contents来填充数组ds,然后使用dsstrtok()进行标记。这本身就没问题,但只有在您需要保留最初阅读的contents时才需要,但您可能不会这样做。但是,在标记化之后,您可以免费ds。同样,这本身不是问题,但它会使您刚刚计算的所有令牌指针无效,因为它们指向先前为ds分配的内存(从中对它们进行了标记化)。在完成对令牌的分析之前,您需要保留它。在释放它们指向的空间后取消引用这些令牌指针会产生UB。

原则上,人们不能预测UB(否则它不会是UB)。尽管如此,您报告的特定结果似乎不太可能表现出来,所以也许还有更多的进展。