【问题标题】:Ending a loop when fscanf reads a certain value from a text file当 fscanf 从文本文件中读取某个值时结束循环
【发布时间】:2015-03-06 03:36:24
【问题描述】:

我正在尝试编写一个程序,该程序从文本文件中读取一个字符和一个浮点数,然后将这些值保存到一个变量中。 文本文件以这种方式格式化:

S 15.24
G 28.00
S 56.90
H 90.00
0

我正在尝试读取字符,然后让它通过一个开关运行,根据浮点数之前的哪个字符进行一些计算(所有 S 值组合在一起,所有 G 值组合在一起,等等) 为了让它遍历所有可用的行,我使用了一个 while 循环,当读取的字符到达列表末尾的 0 时终止。 仅出于测试目的,我让程序在退出循环时打印“完成”。但是,当我运行程序时,它会遍历每个字符并将其正确打印到终端,直到它打印 0 之前的值。一旦到达 0,程序不会执行任何其他操作,但不会打印“完成” “就像我认为的那样。
这是我正在使用的代码:

int main()
{
int s_num,g_num,h_num,S,H,G,n_total;
float amount,s_total,s_sum,g_sum,h_sum;
char char_name;

FILE*Input; 
Input = fopen("Input.txt","r");
FILE*Output;
Output = fopen("Output.txt","w+");


char_name = 1; //Just using 1 as a way to make the while loop occure

while(char_name != '0')
{
    fscanf(Input,"%c%f",&char_name,&amount);
    switch(char_name)
    {
        case 'S':
            printf("S,%f\n",amount);
            break;
        case 'G':
            printf("G,%f\n",amount);
            break;
        case 'H':
            printf("H,%f\n",amount);
            break;


    }



}
printf("done");

return 0;


}

(忽略未使用的值,将在实际程序中使用)

一旦循环达到 0,我需要进行哪些更改才能终止循环?

【问题讨论】:

  • 尝试用fscanf(Input,"%c%f%*c",&char_ name,&amount);fscanf(Input,"%c",&char_ name);fscanf(Input,"%f%*c",&amount);替换fscanf(Input,"%c%f",&char_ name,&amount);
  • 第一个似乎奏效了。你能解释一下 *c 的意义吗?
  • %*c%c 做同样的事情,只是它不会将结果存储在任何地方。 %*c 扫描一个字符并丢弃它。在您的情况下,它将扫描每行末尾的换行符并将其丢弃。

标签: c while-loop switch-statement


【解决方案1】:

以下代码:

 fscanf(Input,"%c%f",&char_name,&amount);

在点击文件中的最后一个数据行时将无法读取浮点数。不需要 switch 语句。使用 if 语句检查第一个字符是否为 '0',然后中断或读取浮点数并打印字符和数字。

while (TRUE)
{
    fscanf(Input,"%c",&char_name);
    if (char_name == '0')
        break;
    fscanf(Input,"%f",&amount);
    printf("%c,%f\n",char_name,amount);
}   

【讨论】:

  • 使用此代码似乎会使程序陷入循环,一遍又一遍地打印 ,0.00000000。
  • @Ezri 这个想法是正确的。我可能没有阅读回车和换行或其他内容。你不是用IDE来调试的吗?您可以一次执行一行代码并检查各种变量的值。试试看,告诉我它是怎么回事。如果一切都失败了,我会仔细研究一下。这是作业吗?
【解决方案2】:

使用fgets() 然后解析行是最好的方法。但是使用fscanf(),推荐:

  1. 更改格式以忽略空格。否则'%c' 将采用空白值

    // fscanf(Input,"%c%f",&char_name,&amount);
    fscanf(Input," %c%f",&char_name,&amount);  // add space
    
  2. 检查来自fscanf() 的返回值。不要使用值 char_name,amount,除非来自 fscanf() 的返回值表明这些值确实已填充。

    int cnt = fscanf(Input," %c%f",&char_name,&amount);
    switch(cnt) {
       case 1: Handle_OnlyCharName(); break;           // Candidate only "0" line
       case 2: Handle_BothCharNameAndAmount(); break;  // OP's switch(char_name)
       case EOF: Handle_IOErrorOrEndOfFile(); break;   // No more data
       default: NeverShouldGetHere();
    }
    

【讨论】:

  • default case 会被处决吗?扫描%c 会失败吗(如果不是EOF)?
  • @Cool Guy “默认案例会被执行吗?”嗯,也许 - 当空白在 EOF 或 IO 错误之前。必须测试。
猜你喜欢
  • 2021-06-22
  • 2021-04-05
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-09-16
相关资源
最近更新 更多