fscanf 用于 C 中的文本文件
fscanf for text files in C
我有一个文件
1 Toy Story 1995 01-Jan-1995 http://us.imdb.com/M/title-exact?Toy%20Story%20(1995) Animation|Children's|Comedy
2 GoldenEye 1995 01-Jan-1995 http://us.imdb.com/M/title-exact?GoldenEye%20(1995) Action|Adventure|Thriller
和列之间的space用制表符写了
这是我的代码,但是 ...
#include <stdio.h>
#include <stdlib.h>
#include <windows.h>
#include <unistd.h>
FILE *MovieF;
void addFileM();
struct Movies
{
char MID[50];
char MName[50];
char MYear[50];
char MDate[50];
char MIMDB[100];
char MGen[100];
}Movie[100];
int main()
{
addFileM();
return 0;
}
void addFileM()
{
MovieF = fopen("d:\movies.txt","r");
for(int i=0;i<60;i++)
{
fscanf(MovieF, "%s\t%s\t%s\t%s\t%s\t%s\n",Movie[i].MID,Movie[i].MName,Movie[i].MYear,Movie[i].MDate,Movie[i].MIMDB,Movie[i].MGen);
}
for(int i=0;i<60;i++)
{
printf("%s\n%s\n%s\n%s\n%s\n%s\n\n",
Movie[i].MID, Movie[i].MName, Movie[i].MYear,
Movie[i].MDate, Movie[i].MIMDB, Movie[i].MGen);
}
}
并输出:
1
Toy
Story
1995
01-Jan-1995
http://us.imdb.com/M/title-exact?Toy%20Story%20(1995)
Animation|Children's|Comedy
2
GoldenEye
1995
01-Jan-1995
http://us.imdb.com/M/title-exact?GoldenEye%20(1995)
Action|Adventure|Thriller
3
Four
Rooms
1995
01-Jan-1995
如你所见,“玩具总动员”存储在两个不同的字段中,第一部电影的类型数据与第二部电影一起打印。
你能告诉我有什么问题吗?
问题是 %s
格式说明符在 whitespece char(space、表格、换行符等)出现时停止扫描找到了。
这就是为什么 “玩具总动员” 和 “四个房间” 都存储在结构的两个不同字段中,使您的扫描从字面上看是“转移”位置(第一部电影的流派字段将成为第二部电影的第一个字段,依此类推)。
您可以使用 %[^\t]
.
而不是 %s
方括号 格式说明符扫描包含一组字符的字符串。但如果 ^
存在,则避免包含该字符。所以在这种情况下,它意味着 "存储字符串并在找到第一个选项卡时停止"。
更好的是:您可以选择使用格式 %N[^\t]
最多存储 N 个字符。给定目标数组的大小,只需将 N 指定为该大小减一(将 space 保留为字符串终止符)。
你的 fscanf
会变成这样:
fscanf(MovieF, "%49[^\t]%49[^\t]%49[^\t]%99[^\t]%99[^\t]\n",
Movie[i].MID, Movie[i].MName, Movie[i].MYear,
Movie[i].MDate, Movie[i].MIMDB, Movie[i].MGen);
我有一个文件
1 Toy Story 1995 01-Jan-1995 http://us.imdb.com/M/title-exact?Toy%20Story%20(1995) Animation|Children's|Comedy
2 GoldenEye 1995 01-Jan-1995 http://us.imdb.com/M/title-exact?GoldenEye%20(1995) Action|Adventure|Thriller
和列之间的space用制表符写了 这是我的代码,但是 ...
#include <stdio.h>
#include <stdlib.h>
#include <windows.h>
#include <unistd.h>
FILE *MovieF;
void addFileM();
struct Movies
{
char MID[50];
char MName[50];
char MYear[50];
char MDate[50];
char MIMDB[100];
char MGen[100];
}Movie[100];
int main()
{
addFileM();
return 0;
}
void addFileM()
{
MovieF = fopen("d:\movies.txt","r");
for(int i=0;i<60;i++)
{
fscanf(MovieF, "%s\t%s\t%s\t%s\t%s\t%s\n",Movie[i].MID,Movie[i].MName,Movie[i].MYear,Movie[i].MDate,Movie[i].MIMDB,Movie[i].MGen);
}
for(int i=0;i<60;i++)
{
printf("%s\n%s\n%s\n%s\n%s\n%s\n\n",
Movie[i].MID, Movie[i].MName, Movie[i].MYear,
Movie[i].MDate, Movie[i].MIMDB, Movie[i].MGen);
}
}
并输出:
1
Toy
Story
1995
01-Jan-1995
http://us.imdb.com/M/title-exact?Toy%20Story%20(1995)
Animation|Children's|Comedy
2
GoldenEye
1995
01-Jan-1995
http://us.imdb.com/M/title-exact?GoldenEye%20(1995)
Action|Adventure|Thriller
3
Four
Rooms
1995
01-Jan-1995
如你所见,“玩具总动员”存储在两个不同的字段中,第一部电影的类型数据与第二部电影一起打印。
你能告诉我有什么问题吗?
问题是 %s
格式说明符在 whitespece char(space、表格、换行符等)出现时停止扫描找到了。
这就是为什么 “玩具总动员” 和 “四个房间” 都存储在结构的两个不同字段中,使您的扫描从字面上看是“转移”位置(第一部电影的流派字段将成为第二部电影的第一个字段,依此类推)。
您可以使用 %[^\t]
.
%s
方括号 格式说明符扫描包含一组字符的字符串。但如果 ^
存在,则避免包含该字符。所以在这种情况下,它意味着 "存储字符串并在找到第一个选项卡时停止"。
更好的是:您可以选择使用格式 %N[^\t]
最多存储 N 个字符。给定目标数组的大小,只需将 N 指定为该大小减一(将 space 保留为字符串终止符)。
你的 fscanf
会变成这样:
fscanf(MovieF, "%49[^\t]%49[^\t]%49[^\t]%99[^\t]%99[^\t]\n",
Movie[i].MID, Movie[i].MName, Movie[i].MYear,
Movie[i].MDate, Movie[i].MIMDB, Movie[i].MGen);