我正在尝试用C读取文件,然后在读取某个单词后存储值。例如,在我的input.txt文件中,以下是内容:
GREETINGS
Hello 13
Namaste 24
Hola 36
FLAVORS
Vanilla 23
Chocolate 78
我想阅读过去GREETINGS
,然后存储Hello
及其值13
,然后Namaste
及其值24
等。然后阅读过去FLAVORS
并存储Vanilla
及其值23
等等等等......
我知道如何打开文件但不知道如何从那里继续。
void readInput() {
char input_file[100];
FILE *fp;
printf("Please enter the name of the file you would like to read: \n");
scanf("%s", input_file);
printf("You entered: %s\n", input_file);
fp = fopen(input_file, "r");
if (fp == NULL) {
printf("File does not exist.\n");
exit(1);
}
else
printf("This file exists!\n");
}
答案 0 :(得分:0)
我不确定您选择要跳过哪些行的确切标准,但阅读行的下一步是使用fscanf
或fgets
。 This tutorial should help you get started with reading files in C.
编辑,在评论后使其更具相关性:
fgets
可能是更好的选择。您需要读取每一行,然后循环遍历每个字符,以检查它们是否全部为大写。
如果它们不是大写的,您可以使用格式为fscanf
的{{1}}来扫描数据行。
答案 1 :(得分:0)
从您的示例数据中,不清楚具有数据的行是否始终具有相同的格式。所以我
建议您在变量中存储当前模式(即GREETINGS
,FLAVOR
等),然后调用
每种模式的特定解析函数,取决于当前值
模式。
我先创建这个枚举
typedef enum {
MODE_GREETINGS = 0, // <-- important that this value is 0
MODE_FLAVORS,
...
MODE_INVALID
} Modes;
和一个变量(这可以是一个全局变量),所有模式:
const char *modes_lookup[] = {
"GREETINGS",
"FLAVORS",
...
};
然后我会编写一个返回模式的函数:
Modes get_mode(const char *src)
{
if(src == NULL)
return MODE_INVALID;
for(size_t i = 0; i < sizeof modes_lookup / sizeof modes_lookup[0]; ++i)
{
if(strcmp(src, modes_lookup[i]) == 0)
return i;
}
return MODE_INVALID;
}
现在您可以像这样解析文件:
char line[1024];
Modes mode = MODE_INVALID;
size_t lineno = 0;
while(fgets(line, sizeof line, fp))
{
lineno++;
// removing newline
line[strcspn(line, "\n")] = 0;
Modes newmode = get_mode(line);
// check if line is a GREETINGS, FLAVOR, etc line
if(newmode != MODE_INVALID)
{
// sets the new mode and continue with the next line
mode = newmode;
continue;
}
// parsing depending on the current mode
if(mode == MODE_GREETINGS)
{
if(parse_greetings(line) == 0)
{
fprintf(stderr, "Cannot parse data on line %zu\n", lineno);
break;
}
continue;
}
if(mode == MODE_FLAVORS) {
if(parse_flavor(line) == 0)
{
fprintf(stderr, "Cannot parse data on line %zu\n", lineno);
break;
}
continue;
}
// more (if mode == MODE_xxx) cases as needed
if(mode == MODE_INVALID)
{
// mode == MODE_INVALID
fprintf(stderr, "File does not start with a mode line.\n");
break;
}
}
然后你必须编写parse_greetings
,parse_flavor
,parse_xxx
函数。就像我说的
之前,从您的样本中不清楚格式是否总是如此
同样,这取决于您使用strtok
还是sscanf
的格式。也
您对如何以及在何处存储值的描述非常模糊,因此
我不知道什么对你最好。
最简单的是sscanf
,如果数据线变得更复杂,那么就可以
使用strtok
。
例如sscanf
int parse_greetings(const char *line)
{
if(line == NULL)
return 0;
char name[20];
int val;
if(sscanf(line, "%19s %d", name, val) != 2)
return 0;
// do whatever you need with 'name' and 'val'
return 1;
}
使用strtok
:
int parse_greetings(char *line)
{
if(line == NULL)
return 0;
char name[20];
int val;
const char *delim = " \t\r\n";
char *token = strtok(line, NULL);
// line has only delimiters
if(token == NULL)
return 0;
strncpy(name, token, sizeof name / sizeof name[0]);
name[(sizeof name / sizeof name[0]) - 1] = 0;
token = strtok(NULL, delim);
if(token == NULL)
return 0;
char *end;
val = strtol(token, &end, 0);
// check if token is a number
if(*end != '\0')
return 0;
// do whatever you need with 'name' and 'val'
return 1;
}