我需要从下到上读取文件中列出的数字。我怎么能用C?
做到这一点该文件如下:
float
例如,我想阅读最后三个数字。它们必须是8.77
6.56
9.3
类型。
{{1}}
PS:实际上我需要一个使用fseek等播放文件指针位置的解决方案。
答案 0 :(得分:27)
了解没有现代操作系统跟踪文件中换行符的位置非常重要。 (VMS可以,而且我非常确定一些IBM大型机操作系统,但你可能不会使用其中任何一种。)因此,不可能寻求线路边界。也不可能以相反的顺序逐字节读取。
因此,反过来读取文件中最后三个数字的最简单方法是按正向顺序读取整个文件,将最近看到的三个数字保存在缓冲区中。点击EOF时,只需向后处理该缓冲区。
一种更有效但更复杂的技术是猜测文件中最后三个数字前的位置;寻找那个位置,然后丢弃角色,直到你突破;并从那一点开始使用前一段中的技术。如果您猜错了,缓冲区中的数字少于三个,请再次猜测。
第三种方法是使用fseek
(使用SEEK_END
)和fread
来读取文件的最后1024个字节,设置指向块结尾的指针,并向后解析。这将是非常有效的,但是会比以前的建议更加令人头疼的角落案例变得正确。 (如果文件的最后三行总共超过1024个字节,你到底做了什么?)
仅供参考,在C中读取浮点数的正确方法是使用fgets
和strtod
。请勿使用atof
或scanf
; atof
没有告诉您有关语法错误的信息,scanf
会在溢出时触发未定义的行为。
P.S。如果你有shell实用程序tac
(这是一个GNUism),最简单的选择就是编写你的程序来处理标准输入上的前三个数字,然后调用它为tac < input.file | ./a.out
。 Skimming the code让我相信tac
实现了我的第三种方法&#34;,还有一些额外的聪明才智。
答案 1 :(得分:6)
嗯,显而易见的方法是将它们全部读出来,将它们放入一个数组然后得到最后三个。
答案 2 :(得分:3)
从文件向后读取的概念不存在。
一种解决方案是读取所有数字并仅存储最后三次读取。
float numbers[3];
char line[100]; // Make it large enough
int = 0;
char* end;
for ( ; ; ++i )
{
i %= 3; // Make it modulo 3.
if ( fgets(line, 100, stdin) == NULL )
{
// No more input.
break;
}
float n = strtof(line, &end);
if ( line == end )
{
// Problem converting the string to a float.
// Deal with error
break;
}
if ( errno == ERANGE )
{
// Problem converting the string to a float within range.
// Deal with error
break;
}
numbers[i] = n;
}
如果文件中至少有三个数字,则最后三个数字为numbers[i]
,numbers[(i+2)%3]
和numbes[(i+1)%3]
。
答案 3 :(得分:1)
首先,打开文件:
FILE* fp = fopen(..., "r");
然后,跳到EOF:
fseek(fp, 0, SEEK_END);
现在,回到X行:
int l = X, ofs = 1;
while (l && fseek(fp, ofs++, SEEK_END) == 0) {
if (fgetc(fp) == '\n' && ofs > 2) l--;
}
最后,从当前位置读取X数字:
float numbers[X];
for(int p = 0; p < X; p++) fscanf(fp, "%f", &numbers[p];
答案 4 :(得分:0)
我用以下代码解决了我的问题。我读了文件的后半部分。
FILE *fp = fopen("sample.txt","r");
if( fp == NULL )
{
perror("Error while opening the file.\n");
exit(EXIT_FAILURE);
}
int size=0;
char ch;
//Count lines of file
while(( ch = fgetc(fp) ) != EOF )
{
if (ch=='\n') { size++; }
}
int i;
float value;
//Move the pointer to the end of the file and calculate the size of the file.
fseek(fp, 0, SEEK_END);
int size_of_file = ftell(fp);
for (i=1; i<=size/2; i++)
{
//Set pointer to previous line for each i value.
fseek(fp, (size_of_file-1)-i*5, SEEK_SET);
fscanf(fp, "%f", &value);
}