我正在编写一个带有输入文件并存储它的C程序。输入文件有两列,第一列是整数,第二列是字符串,如下所示:
12 apple
17 frog
20 grass
我尝试过使用fgets将整行作为字符串然后使用scanf将其分开,但是我遇到了很多问题。我搜索了很多,但没有发现任何能回答我问题的内容,但如果我错过了一些明显的东西,那就很抱歉。 这是我一直在尝试的代码:
while(fgets(line, sizeof(line), fp))
{
scanf(line, "%d\t%s", &key, value);
insert(key, value, newdict);
}
答案 0 :(得分:2)
让我们快速了解strtok
,因为有人提到它。我们假设您的文件名为file.txt
,其内容如下:
10 aaa
20 bbb
30 ccc
我们可以解析它:
#include <stdio.h>
#include <string.h>
#define MAX_NUMBER_OF_LINES 10 // parse a maximum of 10 lines
#define MAX_LINE_SIZE 50 // parse a maximum of 50 chars per line
int main ()
{
FILE* fh = fopen("file.txt", "r"); // open the file
char temp[MAX_LINE_SIZE]; // some buffer storage for each line
// storage for MAX_NUMBER_OF_LINES integers
int d_out[MAX_NUMBER_OF_LINES];
// storage for MAX_NUMBER_OF_LINES strings each MAX_LINE_SIZE chars long
char s_out[MAX_NUMBER_OF_LINES][MAX_LINE_SIZE];
// i is a special variable that tells us if we're parsing a number or a string (0 for num, 1 for string)
// di and si are indices to keep track of which line we're currently handling
int i = 0, di = 0, si = 0;
while (fgets(temp, MAX_LINE_SIZE, fh) && di < MAX_NUMBER_OF_LINES) // read the input file and parse the string
{
temp[strlen(temp) -1] = '\0'; // get rid of the newline in the buffer
char* c = strtok(temp, " "); // set the delimiters
while(c != NULL)
{
if (i == 0) // i equal to 0 means we're parsing a number
{
i = 1; // next we'll parse a string, let's indicate that
sscanf(c, "%d", &d_out[di++]);
}
else // i must be 1 parsing a string
{
i = 0; // next we'll parse a number
sprintf(s_out[si++], "%s", c);
}
c = strtok(NULL, " ");
}
printf("%d %s\n", d_out[di -1], s_out[si - 1]); // print what we've extracted
}
fclose(fh);
return 0;
}
这将从文件中提取内容并将它们存储在相应的数组中,然后打印它们并返回原始内容:
$ ./a.out
10 aaa
20 bbb
30 ccc
答案 1 :(得分:0)
使用:
fgets (name, 100, stdin);
100
是缓冲区的最大长度。您应该根据需要进行调整。
使用:
scanf ("%[^\n]%*c", name);
[]
是扫描集字符。 [^\n]
告诉我,当输入不时,换行符('\n'
)接受输入。然后使用%*c
从输入缓冲区读取换行符(未读取),*
表示此读取输入被丢弃(赋值抑制),因为您不需要它,缓冲区中的这个换行符不会对您可能采取的下一个输入产生任何问题。
答案 2 :(得分:0)
这里的问题似乎是你正在从文件中读取两次。首先是fgets
,然后是scanf
。在使用scanf
时,您可能不会从编译器中获得错误,但是当您使用line
作为格式字符串并且其他参数与格式不匹配时,应该收到警告。如果您检查scanf
的返回值,也会很明显,因为它会返回成功扫描的项目数。你的电话很可能会返回零(或当你点击文件结尾时减去一个)。
您应该使用sscanf
来解析您使用fgets
读取的行。
参见例如this reference适用于不同的scanf
变体。
答案 3 :(得分:0)
使用sscanf(在getline的支持下)可以解决您的问题,如下所示:
#include <stdio.h>
#include <stdlib.h>
int main(void)
{
FILE *fp;
char *line = NULL;
size_t len = 0;
ssize_t read;
/* tokens bags */
char tok_str[255];
int tok_int;
fp = fopen("./file.txt", "r");
if (fp == NULL)
exit(EXIT_FAILURE);
/* Reads the line from the stream. */
while ((read = getline(&line, &len, fp)) != -1) {
/* Scans the character string pointed by line, according to given format. */
sscanf(line, "%d\t%s", &tok_int, tok_str);
printf("%d-%s\n", tok_int, tok_str);
}
if (line)
free(line);
exit(EXIT_SUCCESS);
}
或者,甚至更简单。您可以使用fscanf(在feof的支持下)并使用以下内容替换上面显示的while循环(以及其他一些冗余代码清理):
/* Tests the end-of-file indicator for the stream. */
while (!feof(fp)) {
/* Scans input from the file stream pointer. */
fscanf(fp,"%d\t%s\n",&tok_int, tok_str);
printf("%d-%s\n", tok_int, tok_str);
}
假设您的文件包含以下行(单行格式为 number [tab] string [newline] ):
12 apple
17 frog
20 grass
输出将是:
12-apple
17-frog
20-grass