我有一个数据文件,其中包含3个包含浮点数的列(假设数字列现在是固定的),但最后一列是包含空格(但在一行中)的字符串。
面临的问题不是所有文本行文件都包含最后一个注释字符串,否则使用
fscanf(<file pointer>, %f %f %f %[^\n]%*c,&var1,&var2,&var3,temp)
有效
如下:(对于3行数据)
FILE *fp1=NULL;
printf("HELLO\n");
double value1 = 0.00,value2 = 0.00,value3=0.00;
int i=0;
char temp[200];
fp1 = fopen(textfile,"r");
rewind(fp1);
if(fp1 == 0) {
perror("ERROR OPENING FILE ");
return ;
}
char format[] = "%lf %lf %lf %[^\n]s%*c";
i=3;
while(i--)
{
fscanf(fp1,format,&value1,&value2,&value3,temp) ;
printf("%lf,%lf,%lf - ",value1,value2,value3);
printf("%s\n",temp);
}
fclose(fp1);
上面的代码适用于每一行是否包含一个注释作为最后一列,但如果注释不在行的末尾,那么行将被合并。
1.00 1.1 1.4 //this is first line
2.00 2.1 2.4
4.00 4.1 4.4 //this is fourth line
3.00 3.1 3.4
5.00 5.1 5.4 //this is fifth line
HELLO
1.000000,1.100000,1.400000 - //this is first line
2.000000,2.100000,2.400000 - 4.00 4.1 4.4 //this is fourth line
3.000000,3.100000,3.400000 - 5.00 5.1 5.4 //this is fifth line
希望我的问题很明确。
答案 0 :(得分:1)
嗯,当然它失败了,因为你明确要求用空格分隔三个双打,然后是另一个空格,然后是一些任意长的文本,然后是另一个字符(换行符)。
您需要将评论设为可选。使用fscanf()
和fgets()
的组合:
char format[] = "%lf %lf %lf";
fscanf(fp1, format, &value1, &value2, &value3);
if (fgets(temp, 200, fp1)) {
temp[strcspn(temp, "\n")] = '\0';
}
答案 1 :(得分:0)
问题很微妙。在scanf()
- 系列格式字符串中,空格表示0或更多空格字符,表示空格,制表符或换行符。此外,除%c
,%[…]
和%n
之外的所有格式说明符都跳过可选的前导空格。并且函数不关心白色空间中的换行(换行仅在扫描集中起作用)。如果您需要面向行的输入,那么您应该阅读fgets()
或POSIX的getline()
行,然后使用sscanf()
处理字符串。
您的格式字符串是:
char format[] = "%lf %lf %lf %[^\n]s%*c";
当代码到达数据行时:
2.00 2.1 2.4
4.00 4.1 4.4 //this is fourth line
格式会读取三个数字2.00
,2.1
和2.4
;然后它扫描一些空格,读取换行符,找到4
4.00
,然后将扫描设置处理到换行符,然后用{{1}读取并丢弃换行符}。
如果您想坚持使用%*c
或scanf()
,则部分修复方法是在扫描集之前删除空格。您还需要或多或少地分析fscanf()
的返回值,如下所示。请注意,当没有注释时,换行符将保留在输入缓冲区中,但下一个fscanf()
将在下一个数字之前跳过换行符。
但是,您最好转向基于行的输入。使用fscanf()
而不是直接文件扫描功能时,可以将空格保留为格式字符串。部分修复是检查已成功扫描的值的数量。为了便于理解输出,我用格式字符串中的方括号括起注释材料。
将代码提取为类似于MCVE(Minimal, Complete, Verifiable Example)的内容并从标准输入而不是您打开的文件流中读取,您最终可以使用以下代码:
sscanf()
示例运行:
#include <stdio.h>
#include <string.h>
int main(void)
{
char line[4096];
while (fgets(line, sizeof(line), stdin) != 0)
{
char temp[200];
double value1 = 0.00, value2 = 0.00, value3 = 0.00;
char format[] = "%lf %lf %lf %[^\n]s%*c";
int nf = sscanf(line, format, &value1, &value2, &value3, temp);
if (nf == 4)
printf("Comment: %lf,%lf,%lf - [%s]\n", value1, value2, value3, temp);
else if (nf == 3)
printf("Plain: %lf,%lf,%lf\n", value1, value2, value3);
else
{
line[strcspn(line, "\n")] = '\0';
printf("Invalid: [%s]\n", line);
}
}
return 0;
}
有趣的是,从问题复制的数据在第二行末尾有一个空白。早期版本的代码在格式字符串中省略了扫描集之前的空格。第二行然后显示为注释行,而不是简单的行,并且所有注释都包括前导空格。注意:Comment: 1.000000,1.100000,1.400000 - [//this is first line ]
Plain: 2.000000,2.100000,2.400000
Comment: 4.000000,4.100000,4.400000 - [//this is fourth line]
Plain: 3.000000,3.100000,3.400000
Comment: 5.000000,5.100000,5.400000 - [//this is fifth line]
格式字符串难以掌握。