[英]Assigning values from an array to an array of structs
我正在尝试将包含所有字符串的数组中的值分配给结构体数组,其中某些结构体成员是整数。 不过,我尝试的方式会导致一些未定义的行为。 像下面的代码生成以下内容:
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循环。 Edit2:哦,我有i ++和我total_line切换了。 DERP。 现在修复。 好吧,我想这解决了这个谜。
在for(j=0;j++;j<VALUES)
循环中,您多次转换相同的b[n]
。 您很可能不需要此循环,而只需转换b[n++]
。
作为初步介绍,此行(显然您已经发现可疑)...
contents[size]=0; // what does all this do exactly?
...在从文件读取的字节之后添加一个字符串终止符,因此整个内容可以安全地解释为一个大的C字符串。
@DavetheSax对令牌的索引进行了有效观察。 该问题不会导致未定义的行为,但是产生的行为肯定不是您想要的。
但是,您的程序中确实确实存在未定义的行为。 通过将contents
复制到ds
,然后使用strtok()
ds
进行标记来填充数组b
。 这本身是可以的,但是仅当您需要保留最初读取的contents
时才需要,而您可能不需要。 但是,分词后,您可以释放ds
。 同样,这本身并不是问题,但是它会使您刚才计算的所有令牌指针失效,因为它们指向先前为ds
分配的内存(从中对其进行了令牌化)。 在分析完标记之前,您需要保留该标记。 在释放令牌指针所指向的空间后,取消引用这些令牌指针会产生UB。
原则上,无法预测UB(否则将不会是UB)。 不过,您报告的特定结果似乎不太可能体现出来,因此这里可能还有更多事情要做。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.