我编写了下面的代码来将文件读入结构中,但是当我运行这段代码时,输出可以在下面的文本中看到。我想把这个文件读入结构中,每一个字符块都有数字、名字、姓氏等。原始文件也如下所示。
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
/* run this program using the console pauser or add your own getch, system("pause") or input loop */
struct StudentInfo{
char studentNumber[20];
char studentName[20];
char studentSurname[20];
char department[20];
char eMail[20];
};
int main(int argc, char *argv[]) {
//Declarations
char firstFileName[20];
char secondFileName[20];
char operationType[2];
char data[100];
struct StudentInfo *studentInfo=(struct StudentInfo*) malloc(sizeof(struct StudentInfo));
FILE *firstFile;
FILE *secondFile;
printf("Enter the first file name: ");
scanf("%s",firstFileName);
printf("Enter the second file name: ");
scanf("%s",secondFileName);
printf("Enter the operation type (-i, -u):");
scanf("%s",operationType);
if(strcmp(operationType,"-i")==0){
firstFile = fopen(strcat(firstFileName,".txt"),"r");
while(!feof(firstFile)){
fread(studentInfo,sizeof(struct StudentInfo),1,firstFile);
printf("%s",studentInfo->studentNumber);
}
}
if(strcmp(operationType,"-u")==0){
printf("%s",secondFileName);
}
fclose(firstFile);
/*
while(!feof(firstFile)){
students[1]->studentNumber =
}
fclose(firstFile);*/
}文件的原始内容是:
Ogrenci No;Ogrenci;Program;Sinif;Email;Status
10000000000;EDA NUR YILMAZ;Computer Engineering;4;enur.yilmaz@tedu.edu.tr;
10000000010;FEYZA NUR DUMAN;Computer Engineering;2;fnur.duman@tedu.edu.tr;
20000000010;GOKHAN YAMAC;Computer Engineering;2;gokhan.yamac@tedu.edu.tr;
30000000030;CEREN AYDINLI;Computer Engineering;2;ceren.aydinli@tedu.edu.tr;
30000000010;DURU YAMAC;Computer Engineering;3;duru.yamac@tedu.edu.tr;
40000000010;SEVIL TERZI;Computer Engineering;2;sevil.terzi@tedu.edu.tr;
50000000010;EREN AYDIN;Computer Engineering;2;eren.aydin@tedu.edu.tr;
50000000020;YAMAC YILMAZ;Computer Engineering;2;yamac.yilmaz@tedu.edu.tr;
60000000020;EDANUR YILMAZ;Computer Engineering;2;edanur.yilmaz@tedu.edu.tr;
70000000010;GOKHAN YAMAC;Computer Engineering;2;gokhan.yamac18@tedu.edu.tr;我代码的输出是:
Ogrenci No;Ogrenci;Program;Sinif;Email;Status
10000000000;EDA NUR YILMAZ;Computer Engineering;4;enPI_K³Æ_aj©ur.yilmaz@tedu.edu.tr;
10000000010;FEYZA NUR DUMAN;Computer Engineering;2;fnur.duman@tedu.edu.tr;
PI_K³Æ_aj©20000000010;GOKHAN YAMAC;Computer Engineering;2;gokhan.yamac@tedu.edu.tr;
30000000030;CEREN AYDINLPI_K³Æ_aj©I;Computer Engineering;2;ceren.aydinli@tedu.edu.tr;
30000000010;DURU YAMAC;Computer Engineering;3;dPI_K³Æ_aj©uru.yamac@tedu.edu.tr;
40000000010;SEVIL TERZI;Computer Engineering;2;sevil.terzi@tedu.edu.tr;
50000PI_K³Æ_aj©000010;EREN AYDIN;Computer Engineering;2;eren.aydin@tedu.edu.tr;
50000000020;YAMAC YILMAZ;ComputPI_K³Æ_aj©er Engineering;2;yamac.yilmaz@tedu.edu.tr;
60000000020;EDANUR YILMAZ;Computer Engineering;2;edanuPI_K³Æ_aj©r.yilmaz@tedu.edu.tr;
70000000010;GOKHAN YAMAC;Computer Engineering;2;gokhan.yamac18@tedu.edu.tr;
nuPI_K³Æ_aj©发布于 2022-05-15 17:57:10
环路
while(!feof(firstFile)){
fread(studentInfo,sizeof(struct StudentInfo),1,firstFile);
printf("%s",studentInfo->studentNumber);
}是错误的,有几个原因:
循环条件是错误的。有关更多信息,请参见以下问题:Why is “while ( !feof (file) )” always wrong?
线
fread(studentInfo,sizeof(struct StudentInfo),1,firstFile);将尝试从文件中准确读取sizeof(struct StudentInfo)字节,即100个字节。换句话说,你的程序假设每一行都是100字节长,下一个条目也就是100字节长。您的程序还假设这100字节长的条目之间没有任何内容(也没有换行符)。此外,您的程序假设文件中的每个字符串中都有一个空终止字符(因为稍后您试图将它们打印为空终止字符串)。所有这三个假设都是错误的。
您实际拥有的是一个文件,其中每个条目由换行符分隔。条目的字段具有可变长度(而不是固定长度为20),这些字段由;字符分隔。因此,使用函数fgets一次读取一行比较合适,并使用strtok将该行划分为单独的字段:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
struct StudentInfo
{
char studentNumber[20];
char studentName[20];
char department[20];
char unknown[20];
char eMail[20];
};
int main( void )
{
FILE *fpInput;
char line[400];
struct StudentInfo si;
//open input file
fpInput = fopen( "input.txt", "r" );
if ( fpInput == NULL )
{
fprintf( stderr, "Error opening file!\n" );
exit( EXIT_FAILURE );
}
//ignore first line of input
fgets( line, sizeof line, fpInput );
//read one line of input per loop iteration
while ( fgets( line, sizeof line, fpInput ) != NULL )
{
char *p;
//attempt to find newline character
p = strchr( line, '\n' );
//make sure entire line was read, and remove newline
//character if necessary
if ( p == NULL )
{
//a missing newline character is ok on end-of-file
if ( !feof(fpInput) )
{
fprintf( stderr, "Line too long for input buffer!\n" );
exit( EXIT_FAILURE );
}
}
else
{
//remove newline character from input
*p = '\0';
}
//attempt to read student number
p = strtok( line, ";" );
if ( p == NULL )
{
fprintf( stderr, "Unable to find student number!\n" );
exit( EXIT_FAILURE );
}
//attempt to copy student number to struct
if ( snprintf( si.studentNumber, sizeof si.studentNumber, "%s", p ) >= (int)(sizeof si.studentNumber) )
{
fprintf( stderr, "Not enough space to copy student number.\n" );
exit( EXIT_FAILURE );
}
//attempt to read student name
p = strtok( NULL, ";" );
if ( p == NULL )
{
fprintf( stderr, "Unable to find student name!\n" );
exit( EXIT_FAILURE );
}
//attempt to copy student name to struct
if ( snprintf( si.studentName, sizeof si.studentName, "%s", p ) >= (int)(sizeof si.studentName) )
{
fprintf( stderr, "Not enough space to copy student name.\n" );
exit( EXIT_FAILURE );
}
//attempt to read department
p = strtok( NULL, ";" );
if ( p == NULL )
{
fprintf( stderr, "Unable to find department!\n" );
exit( EXIT_FAILURE );
}
//attempt to copy department to struct
if ( snprintf( si.department, sizeof si.department, "%s", p ) >= (int)(sizeof si.department) )
{
fprintf( stderr, "Not enough space to copy department.\n" );
exit( EXIT_FAILURE );
}
//attempt to read unknown field
p = strtok( NULL, ";" );
if ( p == NULL )
{
fprintf( stderr, "Unable to find unknown field!\n" );
exit( EXIT_FAILURE );
}
//attempt to copy unknown field to struct
if ( snprintf( si.unknown, sizeof si.unknown, "%s", p ) >= (int)(sizeof si.unknown) )
{
fprintf( stderr, "Not enough space to copy unknown field.\n" );
exit( EXIT_FAILURE );
}
//attempt to read email
p = strtok( NULL, ";" );
if ( p == NULL )
{
fprintf( stderr, "Unable to find email!\n" );
exit( EXIT_FAILURE );
}
//attempt to copy email to struct
if ( snprintf( si.eMail, sizeof si.eMail, "%s", p ) >= (int)(sizeof si.eMail) )
{
fprintf( stderr, "Not enough space to copy eMail.\n" );
exit( EXIT_FAILURE );
}
//print data from struct
printf(
"Successfully read the following student entry:\n"
"Number : %s\n"
"Name : %s\n"
"Department: %s\n"
"Unknown : %s\n"
"E-Mail : %s\n"
"\n",
si.studentNumber, si.studentName, si.department,
si.unknown, si.eMail
);
}
}由于您还没有回应我要求澄清输入字段中第四个字段的含义的要求,我只是简单地在stuct StudentInfo中将其标记为“未知”。
但是,当我运行这个程序时,我会收到以下错误消息:
Not enough space to copy department.这是因为您对struct StudentInfo的定义包含以下行:
char department[20];这意味着它只能存储19字符加上终止空字符。但是,在输入文件中,您有Computer Engineering,它是20字符long (21包括终止空字符)。因此,必须将数组的大小至少增加到21。
你也有同样的问题
char eMail[20];此数组不足以存储字符串。
enur.yilmaz@tedu.edu.tr因为它需要24个字符(包括终止字符)
在将两个数组的大小从20增加到30之后,程序就可以工作了。它将有以下输出:
Successfully read the following student entry:
Number : 10000000000
Name : EDA NUR YILMAZ
Department: Computer Engineering
Unknown : 4
E-Mail : enur.yilmaz@tedu.edu.tr
Successfully read the following student entry:
Number : 10000000010
Name : FEYZA NUR DUMAN
Department: Computer Engineering
Unknown : 2
E-Mail : fnur.duman@tedu.edu.tr
Successfully read the following student entry:
Number : 20000000010
Name : GOKHAN YAMAC
Department: Computer Engineering
Unknown : 2
E-Mail : gokhan.yamac@tedu.edu.tr
Successfully read the following student entry:
Number : 30000000030
Name : CEREN AYDINLI
Department: Computer Engineering
Unknown : 2
E-Mail : ceren.aydinli@tedu.edu.tr
Successfully read the following student entry:
Number : 30000000010
Name : DURU YAMAC
Department: Computer Engineering
Unknown : 3
E-Mail : duru.yamac@tedu.edu.tr
Successfully read the following student entry:
Number : 40000000010
Name : SEVIL TERZI
Department: Computer Engineering
Unknown : 2
E-Mail : sevil.terzi@tedu.edu.tr
Successfully read the following student entry:
Number : 50000000010
Name : EREN AYDIN
Department: Computer Engineering
Unknown : 2
E-Mail : eren.aydin@tedu.edu.tr
Successfully read the following student entry:
Number : 50000000020
Name : YAMAC YILMAZ
Department: Computer Engineering
Unknown : 2
E-Mail : yamac.yilmaz@tedu.edu.tr
Successfully read the following student entry:
Number : 60000000020
Name : EDANUR YILMAZ
Department: Computer Engineering
Unknown : 2
E-Mail : edanur.yilmaz@tedu.edu.tr
Successfully read the following student entry:
Number : 70000000010
Name : GOKHAN YAMAC
Department: Computer Engineering
Unknown : 2
E-Mail : gokhan.yamac18@tedu.edu.tr但是,这个解决方案不太好的一点是,它包含大量的代码重复。处理所有5个字段的代码几乎是相同的,所以最好统一此代码:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
struct StudentInfo
{
char studentNumber[20];
char studentName[20];
char department[30];
char unknown[20];
char eMail[30];
};
int main( void )
{
FILE *fpInput;
char line[400];
struct StudentInfo si;
struct field
{
char *p_str;
size_t size;
};
//arrange fields in an array, so that it can be used in
//a loop
struct field fields[] = {
{ si.studentNumber, sizeof si.studentNumber },
{ si.studentName, sizeof si.studentName },
{ si.department, sizeof si.department },
{ si.unknown, sizeof si.unknown },
{ si.eMail, sizeof si.eMail }
};
//open input file
fpInput = fopen( "input.txt", "r" );
if ( fpInput == NULL )
{
fprintf( stderr, "Error opening file!\n" );
exit( EXIT_FAILURE );
}
//ignore first line of input
fgets( line, sizeof line, fpInput );
//read one line of input per loop iteration
while ( fgets( line, sizeof line, fpInput ) != NULL )
{
char *p;
//attempt to find newline character
p = strchr( line, '\n' );
//make sure entire line was read, and remove newline
//character if necessary
if ( p == NULL )
{
//a missing newline character is ok on end-of-file
if ( !feof(fpInput) )
{
fprintf( stderr, "Line too long for input buffer!\n" );
exit( EXIT_FAILURE );
}
}
else
{
//remove newline character from input
*p = '\0';
}
p = strtok( line, ";" );
for ( size_t i = 0; i < sizeof fields / sizeof *fields; i++ )
{
//verify that field exists
if ( p == NULL )
{
fprintf( stderr, "Unable to find student number!\n" );
exit( EXIT_FAILURE );
}
//attempt to copy field to struct
if ( snprintf( fields[i].p_str, fields[i].size, "%s", p ) >= (int)(fields[i].size) )
{
fprintf( stderr, "Not enough space to copy field.\n" );
exit( EXIT_FAILURE );
}
p = strtok( NULL, ";" );
}
//print data from struct
printf(
"Successfully read the following student entry:\n"
"Number : %s\n"
"Name : %s\n"
"Department: %s\n"
"Unknown : %s\n"
"E-Mail : %s\n"
"\n",
si.studentNumber, si.studentName, si.department,
si.unknown, si.eMail
);
}
}发布于 2022-05-15 22:34:15
您的代码出现了许多问题:
char operationType[2];只能容纳一个字符(另一个是因为\0);struct StudentInfo *studentInfo=(struct StudentInfo*) malloc(sizeof(struct StudentInfo));太不必要了,long;while(!feof(firstFile))是always wrong;scanf;fopen的返回值,fread;csv。在您的示例中,fread不是将您的文件读入struct StudentInfo的正确方法。appropriate.更多的是fgets
@Andreas Wenzel已经提供了a solution。下面是使用sscanf的另一个版本
首先,重新定义您的结构,这样就更有意义了:
struct StudentInfo {
char studentNumber[12];
char studentName[50];
char department[50];
int weired; // What is this?
char eMail[50];
};其次,定义一个从输入流读取一行的函数:
char *read_line(char *line, size_t size, FILE *stream)
{
if(!fgets(line, size, stream))
return NULL;
size_t npos = strcspn(line, "\n");
line[npos] = '\0';
return line;
}然后将其与sscanf结合使用
int main(int argc, const char *argv[])
{
const char *filename = "file.txt";
FILE *file = fopen(filename, "r");
if (!file) {
fprintf(stderr, "Could not open file %s\n", filename);
exit(EXIT_FAILURE);
}
char line[1024]; // 1KB should be large enough
struct StudentInfo students[100];
size_t nstudents = 0;
// Read and discard the first line
read_line(line, sizeof line, file);
// Read the rest of the file
for (size_t lineno = 0; read_line(line, sizeof line, file); ++lineno) {
char studentNumber[12];
char studentName[50];
char department[50];
int weired;
char eMail[50];
int ret = sscanf(line, " %11[^;\n];%49[^;\n];%49[^;\n];%d;%49[^;\n];", studentNumber, studentName, department, &weired, eMail);
if (ret != 5) {
printf("> [ERROR] on line %ld: expected %d fields, but only parsed %d\n", lineno, 5, ret);
continue;
}
// Copy data to struct array only when parsing succeeded
struct StudentInfo *st = &students[nstudents++];
strncpy(st->studentNumber, studentNumber, sizeof(studentNumber));
strncpy(st->studentName, studentName, sizeof(studentName));
strncpy(st->department, department, sizeof(department));
st->weired = weired;
strncpy(st->eMail, eMail, sizeof(eMail));
//printf("%s\n%s\n%s\n%d\n%s\n\n", studentNumber, studentName, department, weired, eMail);
}
fclose(file);
for (size_t i = 0; i < nstudents; ++i) {
struct StudentInfo *st = &students[i];
printf("Student #%ld\n", i+1);
printf("%s\n%s\n%s\n%d\n%s\n\n", st->studentNumber, st->studentName, st->department, st->weired, st->eMail);
}
}在这里,%11[^;\n];部分的意思是“读取所有内容,直到找到换行符或分号,或者达到11个字符的最大限制,然后读取分号。”
输出:
Student #1
10000000000
EDA NUR YILMAZ
Computer Engineering
4
enur.yilmaz@tedu.edu.tr
Student #2
10000000010
FEYZA NUR DUMAN
Computer Engineering
2
fnur.duman@tedu.edu.tr
Student #3
20000000010
GOKHAN YAMAC
Computer Engineering
2
gokhan.yamac@tedu.edu.tr
Student #4
30000000030
CEREN AYDINLI
Computer Engineering
2
ceren.aydinli@tedu.edu.tr
Student #5
30000000010
DURU YAMAC
Computer Engineering
3
duru.yamac@tedu.edu.tr
Student #6
40000000010
SEVIL TERZI
Computer Engineering
2
sevil.terzi@tedu.edu.tr
Student #7
50000000010
EREN AYDIN
Computer Engineering
2
eren.aydin@tedu.edu.tr
Student #8
50000000020
YAMAC YILMAZ
Computer Engineering
2
yamac.yilmaz@tedu.edu.tr
Student #9
60000000020
EDANUR YILMAZ
Computer Engineering
2
edanur.yilmaz@tedu.edu.tr
Student #10
70000000010
GOKHAN YAMAC
Computer Engineering
2
gokhan.yamac18@tedu.edu.trhttps://stackoverflow.com/questions/72249036
复制相似问题