分析 C 中的输入

问题描述 投票:0回答:1

我有一个混合类型的数组(整数和双精度数)。 我需要通读输入值的行。

我试图将第 2~11 行的前两个值存储为数组,并将同一行的第 4~13 个值存储为 10*10 数组

我想将它们传递给 C 编译器并使用 printf 函数打印出这些值。但是,当我尝试存储双精度数以查找 (73.29 77.35 66.66 44.12 49.65 60.72 78.76 29.45 15.16 的平均值时,我在存储值时遇到了问题,并收到错误“不兼容的指针到整数转换返回'int [10][2]'” 35.70)在第二个ROM中

这些是输入值。

10

104 80 34.31 73.29 77.35 66.66 44.12 49.65 60.72 78.76 29.45 15.16 35.70 106 121 114
106 90 49.36 49.33 47.02 40.86 46.57 49.04 49.77 40.75 49.54 42.33 43.42 124 -1
114 90 80.85 81.50 66.26 84.71 50.63 17.01 70.02 54.95 82.38 28.54 69.71 132 -1
121 60 33.65 10.47 51.25 57.63 13.60 44.24 17.20 33.32 24.15 29.60 24.25 201 -1
124 40 31.13 36.52 24.10 29.71 28.05 16.02 32.55 15.17 36.31 30.95 20.39 221 351 -1
132 60 29.42 15.55 30.03 29.92 22.67 21.25 11.80 23.48 25.30 23.52 22.90 121 797 -1
201 80 43.27 06.62 10.43 12.28 21.59 32.42 22.72 22.11 27.61 21.36 27.77 -1
221 50 24.16 48.13 44.73 43.19 49.57 47.68 39.90 49.93 45.13 45.58 41.50 -1
351 90 77.83 86.72 82.94 85.29 85.66 85.58 81.95 84.71 88.00 89.49 84.69 104 797 -1
797 40 22.11 20.26 26.67 24.44 27.17 27.29 22.07 24.14 20.30 10.67 24.16 -1
0.6 0.8
int main(int argc, char* argv[]){

       int rows;
    int location_ID, speed_lim;
    double latest_ave_speed;
    double historical_speed[10];
    double location_details[10][2];
    
    //for scanning the traffic data
    int val;
    double speed;// each of the speed values recorded
    //fiugre out the number of rows of locations

    scanf("%d" ,&rows);
    //reading each line
    //the first three vals 
    
    while (scanf("%d %d %lf", &location_ID, &speed_lim, &latest_ave_speed )== 3){
        //get the location details
        for (int i=0; i<10; i++){

            for(int j=0; j<2; j++){
                location_details[i][j]= scanf("%d",&val);


            }

            return location_details;

            for(int j=3; j<12; j++){

                historical_speed[j-3] =scanf("%lf", &speed);

                merged_historical_speed(historical_speed);
            

                
            }

我试图将数据重新排列成一个 10X2 整数数组来存储第 2~11 行的前两个整数,以及一个 10X10 数组来存储这些行的第 3~12 列以返回双精度数的平均值。

arrays c pointers
1个回答
0
投票

请贴出完整的程序。

您不会将数据传递到

C
编译器。您将把您的数据传递给这个
C
程序。

当然,我们可以说您有一个混合类型的数组,但似乎您有一组具有预定义格式的数据读数,例如

  • 位置 ID
  • 限速
  • 最新平均速度
  • 10 个新的快速阅读
  • 一些尚未使用或从未使用过的附加数据

而且您似乎想获得读数的平均值。

如果有数十个字段,简单的方法是编写一个简单的函数解析器,其中包含一个构建每个记录的循环和一个获取每个字段的内部循环。

由于只有 13 个字段,我们可以使用简单的

scanf
sscanf
调用。

我将在这里展示一个小例子。在示例中,我不会显示所有字段,只是因为它很无聊。
但我会向您展示一种安全的方法来编写此类内容。

围绕数据编写:代码离数据越远,完成它的难度就越大。您的数据记录似乎是


typedef struct
{
  int    location;
  int    limit;
  double latest_average;
  double reading[10];
  double avg;
} Speed_data;

由于似乎需要平均值,因此可以在读取数据时计算平均值,然后将其保存在结构体中。或不。我救了。

还有一堆记录,比如

typedef struct
{
    unsigned size;
    Speed_data* rcd;
} Data_set;

始终对数据进行封装。 OOP 有其价值...

  • 代码中没有松散的计数器
  • 没有指针浮动
  • 将数据视为一个整体
  • 没有带有数十个参数的函数

并且有一个如上所述的输入文件...一个好的开始是考虑这样的程序

#include <stdio.h>
#include <stdlib.h>
int main(void)
{
    const char* in_file = "data.txt";
    FILE*       in      = fopen(in_file, "r");
    if (in == NULL) return -1;
    fprintf(stderr, "    '%s' open\n", in_file);
    char  line[250] = {0};
    char* p         = line;  // p points to line
    p               = fgets(line, sizeof(line), in);
    if (p == NULL) return -2;  // read nothing
    const int N = atoi(line);
    if (N < 1) return -3;
    fprintf(stderr, "    Reading %d lines of data\n", N);
    for (int i = 0; i < N; i += 1)
    {
        p = fgets(line, sizeof(line), in);
        if (p == NULL)
        {
            fprintf(
                stderr,
                "    Error after after reading %d lines\n",
                i);
            break;
        }
        fprintf(stderr, "%4d %s", i, line);
    }
    fclose(in);
    return 0;
}

总的来说,首先,确保数据按预期读取、文件被消耗等等......

输出

    'data.txt' open
    Reading 10 lines of data
   0 104 80 34.31 73.29 77.35 66.66 44.12 49.65 60.72 78.76 29.45 15.16 35.70 106 121 114
   1 106 90 49.36 49.33 47.02 40.86 46.57 49.04 49.77 40.75 49.54 42.33 43.42 124 -1
   2 114 90 80.85 81.50 66.26 84.71 50.63 17.01 70.02 54.95 82.38 28.54 69.71 132 -1
   3 121 60 33.65 10.47 51.25 57.63 13.60 44.24 17.20 33.32 24.15 29.60 24.25 201 -1
   4 124 40 31.13 36.52 24.10 29.71 28.05 16.02 32.55 15.17 36.31 30.95 20.39 221 351 -1
   5 132 60 29.42 15.55 30.03 29.92 22.67 21.25 11.80 23.48 25.30 23.52 22.90 121 797 -1
   6 201 80 43.27 06.62 10.43 12.28 21.59 32.42 22.72 22.11 27.61 21.36 27.77 -1
   7 221 50 24.16 48.13 44.73 43.19 49.57 47.68 39.90 49.93 45.13 45.58 41.50 -1
   8 351 90 77.83 86.72 82.94 85.29 85.66 85.58 81.95 84.71 88.00 89.49 84.69 104 797 -1
   9 797 40 22.11 20.26 26.67 24.44 27.17 27.29 22.07 24.14 20.30 10.67 24.16 -1

这有利于道德支持;)

现在我们可以读取数据并有
Data_set
来保存它

考虑这个示例程序和类似的函数

        Speed_data* so_cnvrt(const char* ln);

这可以将一条线转换为具有正确字段和计算平均值的

struct
Speed_data

也考虑一个函数

        int so_show(Data_set* set, const char* msg)

可以在文件中打印完整的数据集

所以这个

main.c
可以工作:

int main(void)
{
    // open file
    const char* in_file = "data.txt";
    FILE*       in      = fopen(in_file, "r");
    if (in == NULL) return -1;
    fprintf(stderr, "    '%s' open\n", in_file);
    char  line[250] = {0};
    char* p         = line;  // p points to line

    // get size of input
    p               = fgets(line, sizeof(line), in);
    if (p == NULL) return -2;  // read nothing
    const int N = atoi(line);
    if (N < 1) return -3;

    // create array
    Data_set data = {0};
    data.size     = 10;
    data.rcd      = malloc(data.size * sizeof(Speed_data));
    if (data.rcd == NULL) return -4;

    // process input
    fprintf(stderr, "    Reading %d lines of data\n    ", N);
    for (int i = 0; i < N; i += 1)
    {
        p = fgets(line, sizeof(line), in);
        if (p == NULL) break;
        Speed_data* one = so_cnvrt(line);
        if (NULL == one) // read error
        {
            fprintf(
                stderr, "    Error after %d lines\n", i);
            free(data.rcd);
            free(one);
            fclose(in);
            break;
        }
        data.rcd[i] = *one; // shallow copy
    }
    fclose(in);
    so_show(&data, "a simple test");
    free(data.rcd); // free data
    return 0;
}

这是从第一个程序复制和粘贴的问题。有用吗?

    'data.txt' open
    Reading 10 lines of data
    a simple test    10 lines in this set:

-------------------------------------------------
|          |          |         average         |
|    loc   |    lim   |    latest  |   actual   |
-------------------------------------------------
|    104   |     80   |    34.31   |     53.09  |
|    106   |     90   |    49.36   |     45.86  |
|    114   |     90   |    80.85   |     60.57  |
|    121   |     60   |    33.65   |     30.57  |
|    124   |     40   |    31.13   |     26.98  |
|    132   |     60   |    29.42   |     22.64  |
|    201   |     80   |    43.27   |     20.49  |
|    221   |     50   |    24.16   |     45.53  |
|    351   |     90   |    77.83   |     85.50  |
|    797   |     40   |    22.11   |     22.72  |
-------------------------------------------------

它有效。我没有打印这 10 篇阅读材料,只是因为它很无聊。但这是编辑功能的问题。

完整
C
代码

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

typedef struct
{
    int    location;
    int    limit;
    double latest_average;
    double reading[10];
    double avg;
} Speed_data;

Speed_data* so_cnvrt(const char*); // 1 line => 1 record

typedef struct
{
    unsigned size;
    Speed_data* rcd;
} Data_set;

int         so_show(Data_set*,const char*);


int main(void)
{
    // open file
    const char* in_file = "data.txt";
    FILE*       in      = fopen(in_file, "r");
    if (in == NULL) return -1;
    fprintf(stderr, "    '%s' open\n", in_file);
    char  line[250] = {0};
    char* p         = line;  // p points to line

    // get size of input
    p               = fgets(line, sizeof(line), in);
    if (p == NULL) return -2;  // read nothing
    const int N = atoi(line);
    if (N < 1) return -3;

    // create array
    Data_set data = {0};
    data.size     = 10;
    data.rcd      = malloc(data.size * sizeof(Speed_data));
    if (data.rcd == NULL) return -4;

    // process input
    fprintf(stderr, "    Reading %d lines of data\n    ", N);
    for (int i = 0; i < N; i += 1)
    {
        p = fgets(line, sizeof(line), in);
        if (p == NULL) break;
        Speed_data* one = so_cnvrt(line);
        if (NULL == one) // read error
        {
            fprintf(
                stderr, "    Error after %d lines\n", i);
            free(data.rcd);
            free(one);
            fclose(in);
            break;
        }
        data.rcd[i] = *one; // shallow copy
    }
    fclose(in);
    so_show(&data, "a simple test");
    free(data.rcd); // free data
    return 0;
}

Speed_data* so_cnvrt(const char* ln)
{
    if (ln == NULL) return NULL;  // no data
    const char* mask =
        "\
%d %d %lf\
%lf %lf %lf %lf %lf\
 %lf %lf %lf %lf %lf";
    Speed_data* one = malloc(sizeof(Speed_data));
    if (one == NULL) return NULL;
    int res = sscanf(
        ln, mask, &one->location, &one->limit,
        &one->latest_average, &one->reading[0],
        &one->reading[1], &one->reading[2], &one->reading[3],
        &one->reading[4], &one->reading[5], &one->reading[6],
        &one->reading[7], &one->reading[8], &one->reading[9]);
    if (res != 13)
    {
        free(one);
        return NULL;
    };
    one->avg = 0.;
    for (int i = 0; i < 10; i += 1)
        one->avg += one->reading[i];
    one->avg /= 10;
    return one;
}

int so_show(Data_set* set, const char* msg)
{
    if (set == NULL) return -1;
    if (msg != NULL) printf("%s", msg);
    printf("    %d lines in this set:\n\n", set->size);
    
   const char* l0 =
        "-------------------------------------------------";
    const char* l1 =
        "|          |          |         average         |";
    const char* l2 =
        "|    loc   |    lim   |    latest  |   actual   |";
    printf("%s\n%s\n%s\n%s\n", l0,l1,l2,l0);
    for (unsigned i = 0; i < set->size; i += 1)
    {
        printf(
            "|    %3d   |    %3d   |   %6.2f   |    %6.2f  "
            "|\n",
            set->rcd[i].location, set->rcd[i].limit,
            set->rcd[i].latest_average, set->rcd[i].avg);
    }
    printf("%s\n\n",l0);
    return 0;
}

这不是一个完整的解决方案,但可能是一种方法。

© www.soinside.com 2019 - 2024. All rights reserved.