簡體   English   中英

realloc() C語言改變int數組中的值

[英]realloc() C-language change value in int array

我試圖在每個循環中使用realloc() ,所以我只對 C 中的int數組使用必要的 memory,但 output 值已更改。 盡管如此,在我的代碼上使用 Valgrind 時,我有正確的值。

我正在做代碼 2022 來臨的第一天。

輸入文件是一個 .txt 文件,如下所示:

7569
1357
10134
4696
4423
8869
3562
6597

4038
9038
1352
8005
4811
6281
3961
4023

7234
3510
7728
1569
4583
7495
3941
6015
6531
2637

我試圖對數字求和並將其存儲在我的數組中的特定索引中,如果有空行則增加我的索引。

鑒於該示例輸入,它應該像這樣打印:

elf [0] = 47207
elf [1] = 41509 
elf [2] = 51243

我得到了什么:

elf [245] = 63138
elf [246] = 181168
elf [247] = 41570
elf [248] = 36264
elf [249] = 59089
elf [250] = 185061

我想要什么(結果使用 valgrind):

elf [245] = 63138
elf [246] = 52399
elf [247] = 41570
elf [248] = 36264
elf [249] = 59089
elf [250] = 56308

我的代碼:

int *read_calories(char *filename)
{
    FILE *fp = fopen(filename, "r");
    char *line = NULL;
    int i = 0;
    size_t len = 0;
    ssize_t nread;
    struct stat size;
    stat(filename, &size);
    int tab_size = 1;
    int *calories = malloc(sizeof(int) * 2);

    if (fp == NULL)
    {
        perror("Can't open file\n");
        exit(EXIT_FAILURE);
    }

    while ((nread = getline(&line, &len, fp)) != -1) 
    {
        if (nread == 1) {
            i++;
            ++tab_size;
            calories = realloc(calories, tab_size * sizeof(int));
        } else {
            calories[i] += atoi(line);
        }
    }
    calories[i + 1] = '\0';
    free(line);
    fclose(fp);

    return calories;
}

int main()
{
    int *calories = read_calories("input.txt");
    for (int i = 0; calories[i] != '\0'; i++) {
        printf("elf [%d] = %d \n", i, calories[i]);
    }
    free(calories);
    return 0;
}

您的卡路里閱讀代碼中包含一些好東西,但相當雜亂無章。 malloc()分配的數據沒有歸零,所以在calories[i] += atoi(line);中使用+= 不好。 您沒有顯示輸入數據格式。

目前尚不清楚您是否必須讀取一堆數字直到空白行並將總和存儲在數組中(然后沖洗並重復到 EOF),或者您是否只需要從文件中讀取數字並將它們存儲到陣列。

每一行都有一個編號單獨存放

下面的代碼假定每一行都包含一個應該存儲在數組中的數字。 適應其他風格的處理並不困難。

#include <assert.h>
#include <errno.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

extern int *read_calories(const char *filename);

int *read_calories(const char *filename)
{
    FILE *fp = fopen(filename, "r");
    if (fp == NULL)
    {
        fprintf(stderr, "Failed to open file '%s' for reading (%d: %s)\n", filename, errno, strerror(errno));
        exit(EXIT_FAILURE);
    }

    int tab_used = 0;
    int tab_size = 2;
    int *calories = malloc(sizeof(int) * tab_size);
    if (calories == NULL)
    {
        fprintf(stderr, "Failed to allocate memory (%d: %s)\n", errno, strerror(errno));
        exit(EXIT_FAILURE);
    }

    char *line = NULL;
    size_t len = 0;
    while (getline(&line, &len, fp) != -1) 
    {
        if (tab_used == tab_size - 1)
        {
            size_t new_size = 2 * tab_size;
            void  *new_data = realloc(calories, new_size * sizeof(int));
            if (new_data == NULL)
            {
                fprintf(stderr, "Failed to allocate memory (%d: %s)\n", errno, strerror(errno));
                exit(EXIT_FAILURE);
            }
            calories = new_data;
            tab_size = new_size;
        }
        calories[tab_used++] = atoi(line);
    }
    calories[tab_used] = 0;
    free(line);
    fclose(fp);

    return calories;
}

int main(void)
{
    int *calories = read_calories("input.txt");
    assert(calories != NULL);
    for (int i = 0; calories[i] != 0; i++)
        printf("elf [%d] = %d \n", i, calories[i]);
    free(calories);
    return 0;
}

我不熱衷於perror() — 它可以完成工作並且很簡單,但是相對來說很難從中獲得好的信息。 該代碼確保數組中有一個額外的條目用於末尾的零條目。 但是,它不會在數組中間發現零條目。 這通常是由於atoi()未能轉換值造成的。

我生成了一個包含 10 到 1000 之間的 10 個隨機值的input.txt文件:

478
459
499
997
237
423
185
630
964
594

程序中的 output 是:

elf [0] = 478 
elf [1] = 459 
elf [2] = 499 
elf [3] = 997 
elf [4] = 237 
elf [5] = 423 
elf [6] = 185 
elf [7] = 630 
elf [8] = 964 
elf [9] = 594 

要求和的數字塊,由空行分隔

此代碼與之前的答案密切相關,但“添加到數組”代碼被提取到 function 中,因此可以使用兩次。 使用結構來封裝數組細節可能會更好。 我可能還應該使用size_t而不是int作為尺寸。

#include <assert.h>
#include <errno.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

static void add_to_array(int **table, int *tab_size, int *tab_used, int value)
{
    if (*tab_used == *tab_size - 1)
    {
        size_t new_size = 2 * *tab_size;
        void  *new_data = realloc(*table, new_size * sizeof(int));
        if (new_data == NULL)
        {
            fprintf(stderr, "Failed to allocate memory (%d: %s)\n", errno, strerror(errno));
            exit(EXIT_FAILURE);
        }
        *table = new_data;
        *tab_size = new_size;
    }
    (*table)[(*tab_used)++] = value;
}

static int *read_calories(const char *filename)
{
    FILE *fp = fopen(filename, "r");
    if (fp == NULL)
    {
        fprintf(stderr, "Failed to open file '%s' for reading (%d: %s)\n", filename, errno, strerror(errno));
        exit(EXIT_FAILURE);
    }

    int tab_used = 0;
    int tab_size = 2;
    int *calories = malloc(sizeof(int) * tab_size);
    if (calories == NULL)
    {
        fprintf(stderr, "Failed to allocate memory (%d: %s)\n", errno, strerror(errno));
        exit(EXIT_FAILURE);
    }

    char *line = NULL;
    size_t len = 0;
    int current_sum = 0;
    ssize_t nread;
    while ((nread = getline(&line, &len, fp)) != -1) 
    {
        if (nread == 1)
        {
            add_to_array(&calories, &tab_size, &tab_used, current_sum);
            current_sum = 0;
        }
        else
            current_sum += atoi(line);
    }
    if (current_sum > 0)
        add_to_array(&calories, &tab_size, &tab_used, current_sum);
    calories[tab_used] = 0;
    free(line);
    fclose(fp);

    return calories;
}

int main(void)
{
    int *calories = read_calories("input.txt");
    assert(calories != NULL);
    for (int i = 0; calories[i] != 0; i++)
        printf("elf [%d] = %d \n", i, calories[i]);
    free(calories);
    return 0;
}

修改后的數據文件:

184
861
513
507
790

897
715
287
729
534
777
945

950
696
605

287
763
839
860
779

522
140
281
190
744
976

420
462
591
710
435
707
580
855
208

806
205
799

537
395

922
356
397
464
435
470
973

203
713
264

(注意末尾沒有空行!)

Output:

elf [0] = 2855 
elf [1] = 4884 
elf [2] = 2251 
elf [3] = 3528 
elf [4] = 2853 
elf [5] = 4968 
elf [6] = 1810 
elf [7] = 932 
elf [8] = 4017 
elf [9] = 1180 

Awk 腳本交叉檢查結果:

awk 'NF == 0 { print sum; sum = 0 } NF == 1 { sum += $1 } END { print sum }' input.txt

結果:

2855
4884
2251
3528
2853
4968
1810
932
4017
1180

暫無
暫無

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

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