C - 使用sscanf读取多个整数和浮点数

时间:2013-11-09 06:43:40

标签: c file integer fgets scanf

我正在为我的C编程类做一个练习题,它告诉我编写一个从文件中读取变量的程序。在第一行,它应该读取整数N。

从那里,它应该读取一个整数,然后在N行的每一行上有五个浮点。它应该计算文件中所有浮点数的总和,并将其写入另一个文件。

我编写了一个程序,应该使用fgets将一行复制到一个字符串,然后使用sscanf来剖析它并将这些段分配给不同的数组位置。但是,我遇到了通过sscanf获取无关信息的一些问题(可能是空值或换行符)。它没有正确存储整数N(它产生大的随机值并通过无限循环创建运行时错误),它可能也不在循环内部工作。

如何完善它以使其正确读取整数和浮点数?

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

#define MAX_STRING 30
#define MAX_LINE_SIZE 200

int main(void)
{
    FILE *f1, *f2;
    char filename[MAX_STRING];
    char fileline[MAX_LINE_SIZE];
    int N, eN;
    float totalwage = 0;
    int* ssn;
    float** wage;

    printf ("Enter a file name for data analysis: ");
    scanf ("%s", &filename); //get file name from user input for reading

    f1 = fopen (filename, "r");

    fgets (fileline, MAX_LINE_SIZE, f1); //read first line
    sscanf (fileline, "%d", &N); //pull integer from first line to determine how many lines follow

    for (eN = 0; eN < N; eN ++) //read N lines following the first
    {
        // VVV read single line from file
        fgets (fileline, MAX_LINE_SIZE, f1);
        // VVV record data from line
        sscanf (fileline, "%d, %f, %f, %f, %f, %f", &ssn[eN], &wage[eN][0], &wage[eN][1], &wage[eN][2], &wage[eN][3], &wage[eN][4]);
        // VVV add the 5 wages on each line to a total
        totalwage += wage[eN][0] + wage[eN][1] + wage[eN][2] + wage[eN][3] + wage[eN][4];
    }

    fclose (f1);

    printf ("Enter a file name for the result: ");
    scanf ("%s", &filename); //get file name from user input for writing

    f2 = fopen (filename, "w");

    fprintf (f2, "%f", totalwage); //store total of wages in file specified by user

    printf ("\nThe information has been stored. Press any key to exit.\n");
    getchar();
}

正在读取的文件是'wages.txt',其内容如下:

10
1, 10, 20, 30, 40, 50
2, 11, 12, 13, 14, 15
3, 21, 23, 25, 27, 29
4, 1, 2, 3, 4, 5
5, 30, 60, 90, 120, 150
6, 37, 38, 39, 40, 41
7, 40, 50, 60, 70, 80
8, 5, 10, 15, 20, 25
9, 80, 90, 100, 110, 120
10, 1000, 2000, 3000, 4000, 2000

作为回顾,问题在于存在运行时错误,程序因某种无限循环而崩溃。通过一些调试,我发现它没有正确地读取第一行中的整数。而不是值十,它存储大值,就好像它读取空字符一样。


我添加了代码,试图为ssn和工资分配内存。但是,我不确定它是否正确完成,并且程序仍然存在崩溃的运行时错误。

ssn = malloc (N*MAX_STRING);
wage = malloc (N*MAX_STRING);
for (eN = 0; eN < N; eN ++)
{
    wage[eN] = malloc (N*MAX_STRING);
}

3 个答案:

答案 0 :(得分:3)

你没有为工资分配任何记忆。它被声明为指向float的指针;这很好,但指针并没有指向任何地方。

ssn也是如此。

这一行之后:

sscanf (fileline, "%d", &N); //pull integer from first line to determine how many lines follow

您需要为ssn和工资分配内存。

由于这是家庭作业,我不打算告诉你如何分配内存;你需要能够自己解决这个问题。

答案 1 :(得分:0)

正如其他人所指出的那样

scanf ("%s", &filename);

应该是:

scanf ("%s", filename);

请注意,如果列数发生变化,sscanf是个大问题

修订用于strtod

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

#define MAX_STRING 30
#define MAX_LINE_SIZE 200
#define COLS 5

int main(void)
{
    FILE *f1, *f2;
    char filename[MAX_STRING];
    char fileline[MAX_LINE_SIZE];
    int N, eN, i;
    float totalwage = 0;
    float (*wage)[COLS];
    char *p;

    printf ("Enter a file name for data analysis: ");
    scanf ("%s", filename); //get file name from user input for reading
    f1 = fopen (filename, "r");
    fgets (fileline, MAX_LINE_SIZE, f1); //read first line
    sscanf (fileline, "%d", &N); //pull integer from first line to determine how many lines follow
    wage = malloc((sizeof(float) * COLS) * N);
    /* check malloc ... */
    for (eN = 0; eN < N; eN ++) //read N lines following the first
    {
        // VVV read single line from file
        p = fgets (fileline, MAX_LINE_SIZE, f1);
        strtol(p, &p, 10); /* skip first column */
        for (i = 0; i < COLS; i++) {
            wage[eN][i] = strtod(p + 1, &p); /* p+1 skip comma, read a float */
            totalwage += wage[eN][i]; /* sum */
        }
    }
    free(wage);
    fclose (f1);
    printf ("Enter a file name for the result: ");
    scanf ("%s", filename); //get file name from user input for writing
    f2 = fopen (filename, "w");
    fprintf (f2, "%f", totalwage); //store total of wages in file specified by user
    printf ("\nThe information has been stored. Press any key to exit.\n");
    getchar();
    fclose(f2); /* you forget to close f2 */
    return 0;
}

另请注意,您只是为了总和来阅读浮点数,不需要存储它们,因此可以避免malloc,并且在现实世界中检查fopen的结果,{{1 } ...

答案 2 :(得分:0)

当您分配内存来存储一个浮点数时,您需要了解浮点值由四个字节组成,因此当您调用malloc时,需要考虑这一点,以存储一个浮点数:malloc( sizeof(float ) )来存储数组对于int,浮点malloc( N*sizeof(float ) )的大小为sizeof(int)