提问人:aisezc 提问时间:12/7/2022 最后编辑:chqrlieaisezc 更新时间:12/7/2022 访问量:73
realloc() int 数组中的 C 语言更改值
realloc() C-language change value in int array
问:
我正在尝试使用每个循环,因此我只为C语言中的数组使用必要的内存,但是输出值发生了变化。尽管如此,当我在代码中使用 Valgrind 时,我有正确的值。realloc()
int
我正在做 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;
}
答:
你的卡路里阅读代码中有好东西,但相当杂乱无章。分配的数据不归零,因此使用 in 不好。您尚未显示输入数据格式。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()
我生成了一个文件,其中包含 100 到 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
要求和的数字块,用空行分隔
此代码与前面的答案密切相关,但“添加到数组”代码被提取到一个函数中,因此可以使用两次。最好使用结构来封装数组详细信息。我可能还应该使用而不是尺寸。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
评论
calories[i] += atoi(line);
— 数组的元素没有归零,所以加法不好;你应该分配。