我正在尝试编写代码,将学生值分配给结构数组(我以前从未使用过)。我知道它部分地按预期方式工作,因为输出文件中的其中一行是正确的,但其他所有内容都偏离了目标。我对 C 编码相当陌生,所以我不完全理解。由于某种原因,某些值正在跨结构传递。
#include <stdlib.h>
#include <stdio.h>
typedef struct{
int Gnum;
int semester;
char course[10];
int credits;
float grade;
char name[50];
}studentInfo;
void setStudentInfo(struct studentInfo *s,int *pos,FILE* ptr){
char buffer[256];
fseek(ptr,*pos,SEEK_CUR);
fgets(buffer,256,ptr);
sscanf(buffer,"%d%[^,],%d%s%d%f",&s->Gnum,s->name,&s->semester,s->course,&s->credits,&s->grade);
*pos = ftell(ptr);
}
//takes info from input file and writes to output file
int main(int argc, char *argv[]){
static int pos = 0;
struct studentInfo s1,s2,s3,s4,s5,s6;
struct studentInfo arr[]={s1,s2,s3,s4,s5,s6};
FILE* ptr;
FILE* ptr2;
char buffer[50];
ptr = fopen(argv[1],"r");
ptr2 = fopen(argv[2],"w+");
int lines = 0;
if(ptr == NULL){
printf("Error occurred while trying to open the input file");
exit(1);
}
if(ptr2 == NULL){
printf("An error occurred with your output file");
exit(1);
}
fseek(ptr,pos,SEEK_CUR);
fgets(buffer,50,ptr);
//reads only the first line of the file to get the loop value
sscanf(buffer,"%d",&lines);
pos = ftell(ptr);
for(int i = 0;i<lines;i++){
setStudentInfo(&arr[i],&pos, ptr);
}
for(int i = 0;i<lines;i++){
fprintf(ptr2,"%-25s%-10d%-8.2f%-10s%-3d%-3d\n",arr[i].name,arr[i].Gnum,arr[i].grade,arr[i].course,arr[i].credits,arr[i].semester);
}
这是输入文件
6
1134970 Iron Man, 5 CS500 4 9.9689
1156731 Captain America, 2 CS262 3 8.7892
1070965 Black Widow, 3 CS310 3 8.3459
1133656 Clint Barton, 5 CS440 4 6.8921
1259273 Nick Fury, 1 CS101 2 4.6784
1284367 Wanda Maximoff, 3 CS367 4 7.9765
这应该是数组的输出内容
Iron Man 4970 9.97 CS500 4 5
92 76992937979330654969186091637145600.00 0 0
Nick Fury 9273 4.68 CS101 2 1
Nick Fury 9273 4.68 CS101 2 1
Nick Fury 9273 4.68 CS101 2 1
Nick Fury 9273 4.68 CS101 2 1
输入值和输出应匹配且除顺序外不发生更改。
argc == 3
和 argv[1]
之前请确保 argv[2]
。struct studentInfo
不仅仅定义了具有该名称的 typedef,因此请添加该 struct
名称,或者在使用该类型时删除 struct
关键字。s1
到 s6
,只使用数组 studentInfo arr[6]
(见下文)。malloc()
动态分配数组(请参阅下一步)。studentInfo s
变量即可。ptr
失败,
ptr2 = fopen(...)
会泄漏,在正常情况下,ptr
和 ptr2
都会泄漏。ptr
和 ptr2
引用同一个文件,那么你会遇到麻烦。 w+
将截断文件,如果您读取较小的记录,然后写入较大的记录,则可能会损坏您的输入。我建议你检查一下这两个文件是否不同。请参阅我可以检查两个 FILE* 或文件描述符编号是否引用同一个文件吗?main()
:fopen(..., "r")
将光标定位在开头,因此fseek(ptr,pos,SEEK_CUR);
不执行任何操作。ftell()
返回 long
(不是 int
)。: On the first call *pos is relative to the beginning of the file so
fseek(ptr,*pos,SEEK_CUR)works as expected. On the 2nd call you are on position 37 and advance another 37 positions. Use
SEEK_SET`。scanf()
系列函数读取字符串时,始终使用最大字段长度以避免缓冲区溢出。ftell()
和 fseek()
调用。不需要它们。#include <stdio.h>
#define COURSE_LEN 9
#define NAME_LEN 49
#define str(s) str2(s)
#define str2(s) #s
typedef struct{
int Gnum;
int semester;
char course[COURSE_LEN+1];
int credits;
float grade;
char name[NAME_LEN+1];
} studentInfo;
void setStudentInfo(studentInfo *s,long *pos,FILE* ptr){
if(fseek(ptr,*pos,SEEK_SET)) {
printf("fseek failed");
return;
}
char buffer[256];
if(!fgets(buffer,sizeof buffer,ptr)) {
printf("fgets failed");
return;
}
if(sscanf(buffer,"%d%" str(NAME_LEN) "[^,],%d%" str(COURSE_LEN) "s%d%f",&s->Gnum,s->name,&s->semester,s->course,&s->credits,&s->grade) != 6) {
printf("sscanf failed");
return;
}
*pos = ftell(ptr);
if(*pos == -1) {
printf("ftell failed");
return;
}
}
int main(int argc, char *argv[]){
if(argc != 3) {
printf("usage: program INPUT OUTPUT\n");
return 1;
}
FILE *ptr = fopen(argv[1],"r");
if(!ptr) {
printf("Error occurred while trying to open the input file");
return 1;
}
FILE *ptr2 = fopen(argv[2],"w+");
if(!ptr2){
printf("An error occurred with your output file");
fclose(ptr);
return 1;
}
long pos = 0;
if(fseek(ptr,pos,SEEK_CUR)) {
printf("fseek failed\n");
goto out;
}
char buffer[50];
if(!fgets(buffer, sizeof buffer, ptr)) {
printf("fgets failed\n");
goto out;
}
int lines;
if(sscanf(buffer,"%d",&lines) != 1) {
printf("failed to read number of records\n");
goto out;
}
pos = ftell(ptr);
if(pos == -1) {
printf("ftell failed\n");
goto out;
}
for(int i = 0;i<lines;i++) {
studentInfo s;
setStudentInfo(&s, &pos, ptr);
fprintf(ptr2,"%-25s%-10d%-8.2f%-10s%-3d%-3d\n",s.name,s.Gnum,s.grade,s.course,s.credits,s.semester);
}
out:
fclose(ptr);
fclose(ptr2);
}
运行示例:
./a.out input.txt output.txt && cat output.txt
Iron Man 1134970 9.97 CS500 4 5
Captain America 1156731 8.79 CS262 3 2
Black Widow 1070965 8.35 CS310 3 3
Clint Barton 1133656 6.89 CS440 4 5
Nick Fury 1259273 4.68 CS101 2 1
Wanda Maximoff 1284367 7.98 CS367 4 3