簡體   English   中英

如何為結構動態分配值

[英]How to assign values dynamically to a struct

我對如何訪問和更改結構的值感到困惑。 該程序接收一些外部文件,並對每個字符串進行標記,然后將其歸類為以下氣候信息字段。 外部文件如下所示:

TDV格式:

 TN     1424325600000   dn20t1kz0xrz    67.0    0.0  0.0     0.0    101872.0    262.5665
 TN     1422770400000   dn2dcstxsf5b    23.0    0.0  100.0   0.0    100576.0    277.8087
 TN     1422792000000   dn2sdp6pbb5b    96.0    0.0  100.0   0.0    100117.0    278.49207
 TN     1422748800000   dn2fjteh8e80    6.0     0.0  100.0   0.0    100661.0    278.28485
 TN     1423396800000   dn2k0y7ffcup    14.0    0.0  100.0   0.0    100176.0    282.02142

這些列的順序是:第一列用於狀態代碼,第二列用於時間戳記(自Unix紀元以來的毫秒數),第三列是位置的geohash字符串(未使用),第四列是濕度百分比,第五列是積雪當前(值0.0或1.0),第六個是雲量百分比,第七個是雷擊次數,第八個是壓力(單位未知,但是數據沒有關系,所以沒關系),第九個是表面溫度(以開爾文為單位)。 我確實意識到我必須轉換時間戳記和表面溫度,因此我對此並不擔心。 我需要匯總整個狀態下的數據(與geohash無關),跟蹤最低和最高溫度以及它們發生的時間,並統計該狀態的記錄數,以便對值進行平均。

單個狀態的輸出應如下所示:

 * Opening file: data_tn.tdv
 * States found: TN
 * -- State: TN --
 * Number of Records: 17097
 * Average Humidity: 49.4%
 * Average Temperature: 58.3F
 * Max Temperature: 110.4F on Mon Aug  3 11:00:00 2015
 * Min Temperature: -11.1F on Fri Feb 20 04:00:00 2015
 * Lightning Strikes: 781
 * Records with Snow Cover: 107
 * Average Cloud Cover: 53.0%

但是,將有多個狀態,每個狀態都有其自己的數據文件要處理。

如您所見,第一個令牌將分配給狀態代碼,但是我不知道如何執行此操作。 我嘗試了許多strcpy和許多其他方法來嘗試將令牌發送到各自的字段中,但是沒有一種有效。

     struct climate_info
        {
            char code[3];
            unsigned long num_records;
            unsigned long timestamp;
            char location[13];
            unsigned int humidity;
            int snow;
            unsigned int cover;
            int strikes;
            long double pressure;
            long double sum_temperature;
        };



struct stats
{
    char code[3];
    long long timestamp;
    double humidity;
    double snow;
    double cloud;
    double strikes;
    double sum_temperature;
}stats;



    void analyze_file(FILE *file, struct climate_info *states[], int num_states);
    void print_report(struct climate_info *states[], int num_states);

    int main(int argc, char *argv[])
    {
        /* TODO: fix this conditional. You should be able to read multiple files. */
        if (argc < 1 )
        {
            printf("Usage: %s tdv_file1 tdv_file2 ... tdv_fileN \n", argv[0]);
            return EXIT_FAILURE;
        }

        /* Let's create an array to store our state data in. As we know, there are
         * 50 US states. */
        struct climate_info *states[NUM_STATES] = { NULL };

        int i;
        for (i = 1; i < argc; ++i)
        {
            /* TODO: Open the file for reading */

            /* TODO: If the file doesn't exist, print an error message and move on
             * to the next file. */
            /* TODO: Analyze the file */
            /* analyze_file(file, states, NUM_STATES); */
            FILE *fp = fopen(argv[i], "r");
                if(fp == NULL)
                {
                    printf("Error opening file");
                    break;
                }
                 else if(fp)
                {
                 analyze_file(fp, states,NUM_STATES);
                }
             fclose(fp);
        }
        print_report(states, NUM_STATES);
        return 0;
    }

    void analyze_file(FILE *file, struct climate_info **states, int num_states)
    {
        const int line_sz = 100;
        char line[line_sz];
        int counter = 0;
        char *token;
        while (fgets(line, line_sz, file) != NULL)
        {
            /* TODO: We need to do a few things here:
             *
             *       * Tokenize the line.
             *       * Determine what state the line is for. This will be the state
             *         code, stored as our first token.
             *       * If our states array doesn't have a climate_info entry for
             *         this state, then we need to allocate memory for it and put it
             *         in the next open place in the array. Otherwise, we reuse the
             *         existing entry.
             *       * Update the climate_info structure as necessary.
             */
  struct climate_info *y = malloc(sizeof(struct climate_info)*num_states);
    token = strtok(line," \t");
    strcpy((y[counter]).code,token);
    counter++;
    printf("%s\n",token);
    while(token)
    {
        printf("token: %s\n", token);
        token = strtok(NULL, " \t");
    }
    printf("%d\n",counter);
        //free(states);
    }

    void print_report(struct climate_info *states[], int num_states)
    {
        printf("States found: ");
        int i;
        for (i = 0; i < num_states; ++i) {
            if (states[i] != NULL)
            {
                struct climate_info *info = states[i];
                printf("%s", info->code);
            }
        }
        printf("\n");

從文件中讀取的值不應直接分配給結構的元素。 您需要一組變量(它們可以在結構中,但不是必需的)以在讀取數據時接收數據,其中sscanf()進行解析和拆分。 然后,您可以驗證狀態碼是否正確,時間是否合理等等。 然后,您將累積信息添加到“統計結構”中,該struct climate_info您當前擁有的struct climate_info相關但又不同。 例如,它不需要Geohash列或壓力塔,但是需要確定最低溫度和時間,以及確定最高溫度和時間。 您可以累計積雪數量,雷擊數量,濕度和雲量以及當前溫度。 然后,當您完成文件時,可以平均溫度,濕度和雲量值,並且可以打印聚合。

由於您明智地使用fgets()從文件中讀取行(請勿更改!),因此應使用sscanf()來解析行。 你需要:

  • 狀態碼( char state[3]; ),
  • 時間值( long long millitime; ),
  • 濕度值( double humidity; ),
  • “ snow present”(雪當前)值( double snow;由於格式為浮點數),
  • “雲量”值( double cloud; ),
  • 雷擊值( double lightning ),
  • 和溫度值( double temperature; )。

然后,您可以使用閱讀它們

if (sscanf(line, "%2[A-Z] %lld %*s %lf %lf %lf %lf %*lf %lf",
           state, &millitime, &humidity, &snow, &cloud, &lightning, &temperature) == 7)
{
    …validate data and report errors if appropriate…
    …stash values appropriately; increment the count…
}
else
{
    …report format error?… 
}

請注意,格式中的*禁止分配; 該列已讀取但被忽略。 代碼檢查壓力是否為數字列。 除了“必須存在”之外,它不會驗證geohash列。 可以將大小指定為上限%*12s

使用fgets()sscanf()的許多優點之一是,您可以更加清楚地報告錯誤-您可以說“ XXX行中的狀態代碼不正確”,然后打印該行,因為它仍然可用。 使用fscanf() ,您將無法如此輕松地報告行內容,這使得調試數據的人變得更加困難。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM