我如何使用scanf读取文本文件中的下一行
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了我如何使用scanf读取文本文件中的下一行相关的知识,希望对你有一定的参考价值。
我有一个分配,我需要使用scanf从文本文件中读取输入,并将输入临时存储到结构中,最后使用printf进行打印。我们不允许使用结构数组。
这是文本文件:
1010 Jose Manalo 3.5
2003 Luisa Santos 2.5
1008 Andres Espinosa 4.0
这里是给定的结构(String20是20个字符的数组):
struct nameTag {
String20 first;
String20 last;
};
struct studentTag {
int ID;
struct nameTag name;
float grade;
};
我的初始代码如下(studentInfo是我的studentTag的结构变量):
scanf("%d %s %s %f", &studentInfo.ID, studentInfo.name.first, studentInfo.name.last, &studentInfo.grade);
printf("%d %s %s %.1f", studentInfo.ID, studentInfo.name.first, studentInfo.name.last, studentInfo.grade);
这当然只读取并打印第一行
编辑(已解决):将scanf放入一个循环中,直到达到EOF或NULL为止,效果很好。这是我所做的:
while(scanf("%d %s %s %f", &studentInfo.ID, studentInfo.name.first, studentInfo.name.last, &studentInfo.grade)!=NULL)
printf("%d %s %s %.1f
", studentInfo.ID, studentInfo.name.first, studentInfo.name.last, studentInfo.grade);
[scanf
用于从stdin读取输入流,也就是说,您可以使用的最接近的函数是fscanf,类似于scanf,但是您可以指定要读取的文件:
#include <stdio.h>
typedef char String20[20];
struct nameTag {
String20 first;
String20 last;
};
struct studentTag {
int ID;
struct nameTag name;
float grade;
};
int main()
{
FILE* f;
if(!(f = fopen("file.txt", "r"))) {
return 1;
}
struct studentTag studentInfo;
while(fscanf(f, "%d %19s %19s %f", &studentInfo.ID, studentInfo.name.first, studentInfo.name.last, &studentInfo.grade) == 4)
printf("%d %s %s %.1f
", studentInfo.ID, studentInfo.name.first, studentInfo.name.last, studentInfo.grade);
}
使用fscanf
的返回值来验证是否读取了正确的字段数并将其用作停止参数。
请注意,对于读取char数组,重要的是指定要读取的字符串的长度,例如,对于char[20]
字符数组容器,可以使用"%s19"
说明符,以避免堆栈粉碎。
一次读取一行时,请使用面向行输入功能,例如fgets()
或POSIX getline()
。这避免了试图仅使用scanf()
来从文件读取的新C程序员的许多陷阱。
[单独使用scanf()
的问题很多,但是归结为尝试读取后输入流中剩下的内容。例如,当使用scanf()
尝试读取整数值时,如果在数字之前遇到非数字,则会发生matching-failure,并且从输入流中停止字符提取,这将导致所有问题输入流中的字符未读-除非下次手动将字符从输入流中清空,否则请等待下一次尝试再次咬你。读取float
作为最后一个值后,'
'
保留在输入流中未读取,并且如果下次读取时,您的格式说明符不忽略前导空白,则将空白视为您的输入。 (这只是冰山一角...)
因此,请使用fgets()
一次将整行读取到适当大小的字符数组中。这样,您一次消耗了整条生产线。然后,您可以使用sscanf()
从数据行中解析所需的内容。无论解析成功与否,您都不会影响从文件中读取下一行数据。数据读取和值解析不再在单个操作中耦合。
将各个部分放在一起,您可以执行以下操作:
#include <stdio.h>
#include <string.h>
#define MAXC 1024
#define MAXNM 20
typedef char String20[MAXNM]; /* your typedef */
struct nameTag {
String20 first;
String20 last;
};
struct studentTag {
int ID;
struct nameTag name;
float grade;
};
int main (int argc, char **argv) {
char buf[MAXC]; /* buffer to hold each line */
size_t n = 0; /* counter for number of students */
struct studentTag std[MAXNM] = {{ .ID = 0 }};
/* use filename provided as 1st argument (stdin by default) */
FILE *fp = argc > 1 ? fopen (argv[1], "r") : stdin;
if (!fp) { /* validate file open for reading */
perror ("file open failed");
return 1;
}
/* read each line -- until array full of EOF reached */
while (n < MAXNM && fgets (buf, MAXC, fp)) {
struct studentTag tmp = { .ID = 0 }; /* temporary struct to fill */
if (sscanf (buf, "%d %19s %19s %f", /* parse value from line */
&tmp.ID, tmp.name.first, tmp.name.last, &tmp.grade) == 4)
std[n++] = tmp; /* assign temp struct to array on success */
else /* on error */
fprintf (stderr, "error: line format - %s", buf);
}
if (fp != stdin) /* close file if not stdin */
fclose (fp);
for (size_t i = 0; i < n; i++) /* output all stored student data */
printf ("
ID: %d
First: %s
Last: %s
Grade: %f
",
std[i].ID, std[i].name.first, std[i].name.last, std[i].grade);
return 0;
}
([note:您总是通过checking return来验证每个用户输入和值的解析,请参阅Henry Spencer's 10 Commandments for C Programmers - No. 6 “被警告...” )
示例使用/输出
将数据放在dat/studenttag.txt
中,您将提供文件名作为第一个参数并接收:
$ ./bin/readstudenttag dat/studenttag.txt
ID: 1010
First: Jose
Last: Manalo
Grade: 3.500000
ID: 2003
First: Luisa
Last: Santos
Grade: 2.500000
ID: 1008
First: Andres
Last: Espinosa
Grade: 4.000000
仔细检查,如果还有其他问题,请告诉我。
最佳方法是使用fgets
,然后按David在评论中建议的使用sscanf
。Scanf是一种安全的方法,因为它可能导致缓冲区溢出。虽然,我认为您正在寻找这样的东西:
#include <stdio.h>
struct nameTag
{
char first[20],last[20];
};
struct studentTag
{
int ID;
struct nameTag name;
float grade;
};
int main(void)
{
struct studentTag studentInfo;
FILE *filein;
filein=fopen("file.txt","r");
while (!feof(filein)) /* Reading each line until EOF */
{
if (fscanf(filein,"%d %s %s %f",&studentInfo.ID, studentInfo.name.first, studentInfo.name.last, &studentInfo.grade)==0)
;
printf("%d %s %s %.1f
", studentInfo.ID, studentInfo.name.first, studentInfo.name.last, studentInfo.grade);
}
return 0;
}
您可以使用fscanf
fptr = fopen("c2.txt", "r+");
if(fptr!=Null)
for (!feof(fptr))
{
fscanf(fptr,"%d %s %s %f
", &studentInfo.ID, studentInfo.name.first, studentInfo.name.last, &studentInfo.grade);
printf("%d %s %s %.1f
", studentInfo.ID, studentInfo.name.first, studentInfo.name.last, studentInfo.grade);
}
以上是关于我如何使用scanf读取文本文件中的下一行的主要内容,如果未能解决你的问题,请参考以下文章