gpt4 book ai didi

c - realloc() C语言改变int数组中的值

转载 作者:行者123 更新时间:2023-12-05 03:16:19 27 4
gpt4 key购买 nike

我尝试在每个循环中使用 realloc(),因此我只为 C 中的 int 数组使用必要的内存,但输出值已更改。尽管如此,在我的代码中使用 Valgrind 时,我得到了正确的值。

我在做 Advent of Code 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

程序的输出是:

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

要求和的数字 block ,用空行分隔

此代码与之前的答案非常相似,但“添加到数组”代码被提取到一个函数中,因此可以使用两次。使用结构来封装数组细节可能会更好。我可能还应该使用 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

(注意末尾没有空行!)

输出:

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

关于c - realloc() C语言改变int数组中的值,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/74707228/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com