c - 如何读取逗号作为 C 中下一个变量的标志?

标签 c

输入文件将在一行中包含一个湖泊的名称,然后是一个逗号,然后是该湖泊的体积(以数百立方英里为单位)。下一行将包含另一个湖泊的名称,一个逗号,然后是它的体积,等等。文件的每一行都包含一个湖泊的名称,一个逗号和一个浮点值的体积。湖泊的名称可能包含一个以上的词;例如“dead horse lake”,但它将在一个格式化的行上。体积可能有小数,如 16.9。您的程序将使用一个子例程,该子例程将湖泊的名称及其体积作为参数。然后,该子例程将在屏幕的一行中打印出湖泊的名称,然后是一组连续的星号,表示下一行以数百立方英里为单位的体积,四舍五入到最近的百立方英里。例如,如果该湖的体积为 15.6 立方英里,则该子程序将在湖名后的一行中打印出 16 个星号。

现在我的程序只读取第一行并显示名称和星号,但我的 lakes.txt 文件中的任何其他信息都不会被读取并且程序终止。有人可以告诉我我做错了什么吗?最初的项目是一个没有逗号的项目,但是教授。决定在那里加一个逗号。我只是将 %19 更改为 %20 并在括号中添加了一个逗号。我不知道这有什么不同,但它奏效了。我想明白为什么。

我是 SO 的新手。对不起,如果我的文字有点偏离。我是一名新程序员,我真的很想了解并成为一名优秀的程序员。您的回答越详细、越深入,对我的帮助就越大。感谢您的帮助!

#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <string.h>

void asterisks_code( char lake[257], float vol );

int main()
{
    char lake[257], tempt[100];
    float vol;
    FILE *fp;
    fp = fopen( "lakes.txt", "r" );
    if( fp == NULL) {//starts 1st if statement
        printf( "File does not exist.");
        return 0;
    }//closes 1st if statement
    while( ( fgets( tempt, sizeof (tempt), fp ) ) != NULL ) {
        if (sscanf(tempt, " %19[A-Za-z, ]%f", lake, &vol) != 2) {//starts 2nd if statement
            fprintf(stderr, "Unexpected data\n");
            break;
        }//closes 2nd if statement
        asterisks_code( lake, vol );
    }//closes while loop
    fclose( fp );
    return 0;
}//closes main function

void asterisks_code( char lake[257], float vol )
{//start of asterisks_code function
    int counter;
    printf( "%s\n", lake );
    for( counter = 0; counter < roundf(vol); counter++ ) {//start of for loop
        printf( "*" );
    }//closes for loop
    printf( "\n" );
}//closes asterisk_code function

最佳答案

我对你有好感。您的教授从一开始就误导了您。

首先,fgets(tempt, sizeof (tempt), fp ) 不保证从fp 中读取整行。如果读取了 sizeof tempt 字节并且该行中还有更多字节,则剩余的行将留在流中以供下一次调用 fgets。我已经在 another answer 中编写了该问题的解决方案,但老实说,您不需要 fgets如果您愿意,您可以使用它,但解决此练习所需的只是 fscanffgetc

我完全建议使用fscanf阅读一次只...至少在您阅读并完全理解之前 the fscanf manual (它非常冗长,表明它非常复杂且容易出错...嗯!)。即便如此,在您尝试使用之前,您仍然至少应该阅读

首先编写一个函数来读取您的 19 字节宽的字段...

int read_lake_name(FILE *fp, char *lake) {
    int n = fscanf(fp, "%19[^,]", lake);
    int left_over = 0;
    fscanf(fp, "%*[^,]%n", &left_over);
    if (left_over > 0) {
        puts("WARNING: Lake name was longer than 19 bytes and has been discarded...");
    }
    fgetc(fp);
    return n;
}

如果提供的字节数超过 19 个,流中就会有一些剩余。这些字节需要被丢弃。注意到第二个fscanf中的*,没有对应的数组参数吗?这是使用 fscanf 进行赋值抑制的一个例子;剩余的字节将被读取并丢弃,而不是分配到数组中。 %n 指令指示 fscanf 分配 fscanf 已读入 left_over 的字节数,这告诉我们是否湖的名字是否被截断了。随后,调用 fgetc 以丢弃剩余的逗号。

此代码非常适合读取(并截断)19 个字节的用户输入,直到下一个逗号,但它不会读取该卷。一旦您读取了最多 19 个字节并丢弃了逗号(以及逗号之前的任何尾随数据),您将需要读取一个浮点值,然后丢弃换行符之前的所有内容,并丢弃换行符(当然)...

int read_lake_volume(FILE *fp, float *v) {
    int n = fscanf(fp, "%f", v);
    int left_over = 0;
    fscanf(fp, "%*[^\n]%n", &left_over);
    if (left_over > 0) {
        puts("WARNING: Lake volume contained trailing invalid characters which have been discarded...");
    }
    fgetc(fp);
    return n;
}

你注意到这里有什么相似之处吗?有了这两个几乎相同的函数,构造一个工作循环应该是微不足道的,但这里是:

while (read_lake_name(fp, name) == 1 && read_lake_volume(fp, &vol) == 1) {
    write_asterisks(name, vol);
}

关于c - 如何读取逗号作为 C 中下一个变量的标志?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/30925538/

相关文章:

c - c中删除二叉树根节点的迭代方法

c - 有没有办法用 scanf 读取括号内的整数?

c - 警告 : format ‘%d’ expects type ‘int *’ , 但参数 2 的类型为 ‘int **’

使用 -h 选项时 javac "no source files"

c - 如何访问函数中包含另一个同名指针的全局指针?

c - float和int的内存表示

c - 使用自修改代码观察 x86 上的陈旧指令提取

c - 使用预增量和后增量运算符时宏的奇怪结果

c - 如何修复对 _imp__* 的 undefined reference ?

python - 使用 pyqt 将输入输入到 .c 文件