I am very new to C (started 4 days ago, do have a background in Python and Java). I tried to create a dynamic array (python list) to solve advent of code day 4 part 2. The own
list and win
list works normally, I don't understand why the cardInstancesCount
just refused to take in a value.
Valgrind output
==1444== Invalid write of size 4
==1444== at 0x1097FD: main (part2.c:91)
==1444== Address 0x0 is not stack'd, malloc'd or (recently) free'd
#include <math.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int is_a_num_char(char *p_char) { return (*p_char >= '0' && *p_char <= '9'); }
int extract_int(char **p_start) {
char *p_end = *p_start;
while (is_a_num_char(p_end)) p_end++;
size_t length = p_end - *p_start;
char tmp[length + 1];
tmp[length] = '\0';
memcpy(tmp, *p_start, length);
*p_start = p_end;
return (int)strtol(tmp, (char **)NULL, 10);
}
int main(int argc, char *argv[]) {
FILE *file = fopen(argv[1], "r");
int res = 0;
char buffer[500];
int tmpNum;
int cardQuantity = 0;
int *cardInstancesCount = NULL;
for (int cardIdx = 0; fgets(buffer, sizeof(buffer), file); cardIdx++) {
int *win = NULL;
int *own = NULL;
int winIdx = 0;
int ownIdx = 0;
int matchCount = 0;
char *p_line = buffer;
// Skip to ':'
while (*p_line != ':') p_line++;
// Load list of winning numbers
for (; *p_line != '|'; p_line++) {
if (!is_a_num_char(p_line)) {
continue;
}
tmpNum = extract_int(&p_line);
int *tmp = realloc(win, sizeof(int) * (winIdx + 1));
if (tmp == NULL) {
printf("%s\n", "Memory Allocation Failed");
return 1;
}
win = tmp;
win[winIdx++] = tmpNum;
}
// Load list of own numbers
for (; *p_line != '\0'; p_line++) {
if (!is_a_num_char(p_line)) {
continue;
}
tmpNum = extract_int(&p_line);
int *tmp = realloc(own, sizeof(int) * (ownIdx + 1));
if (tmp == NULL) {
printf("%s\n", "Memory Allocation Failed");
return 1;
}
own = tmp;
own[ownIdx++] = tmpNum;
}
// Check how many matchings
for (int ownCheckIdx = 0; ownCheckIdx < ownIdx; ownCheckIdx++) {
for (int winCheckIdx = 0; winCheckIdx < winIdx; winCheckIdx++) {
if (own[ownCheckIdx] == win[winCheckIdx]) {
matchCount++;
break;
}
}
}
free(win);
free(own);
if (cardQuantity == cardIdx) {
printf("%p\n", &cardInstancesCount);
int *tmp =
realloc(cardInstancesCount, sizeof(int) * (cardQuantity + 1));
if (tmp = NULL) {
printf("%s\n", "Memory Allocation Failed");
return 1;
}
cardInstancesCount = tmp;
printf("%p\n", &cardInstancesCount);
cardInstancesCount[cardIdx] = 1; // Line 91
printf("%s\n", "no");
printf("%d",*cardInstancesCount);
}
// If need to expand cardQuantity
int newCardQuantity = cardIdx + matchCount + 1;
if (newCardQuantity > cardQuantity) {
int *tmp =
realloc(cardInstancesCount, sizeof(int) * newCardQuantity);
if (tmp == NULL) {
printf("%s\n", "Memory Allocation Failed");
return 1;
} else {
cardInstancesCount = tmp;
}
// Initialise all 1 for new card discovery
for (int i = cardQuantity; i < newCardQuantity; i++) {
cardInstancesCount[i] = 1;
}
cardQuantity = newCardQuantity;
// Add current instance to the cards
for (int i = cardIdx + 1; i < newCardQuantity; i++) {
cardInstancesCount[i] += cardInstancesCount[cardIdx];
}
// Set newCardQuantity
cardQuantity = newCardQuantity;
}
// If no cardQuantity expansion.
else {
for (int i = cardIdx + 1; i < newCardQuantity; i++) {
cardInstancesCount[i] += cardInstancesCount[cardIdx];
}
}
}
for (int i = 0; i < cardQuantity; i++) {
printf("%d", cardInstancesCount[i]);
}
free(cardInstancesCount);
printf("Res: %d\n", res);
return 0;
}
The code that works for part 1
#include <math.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int is_a_num_char(char *p_char) { return (*p_char >= '0' && *p_char <= '9'); }
int extract_int(char **p_start) {
char *p_end = *p_start;
while (is_a_num_char(p_end)) p_end++;
size_t length = p_end - *p_start;
char tmp[length + 1];
tmp[length] = '\0';
memcpy(tmp, *p_start, length);
*p_start = p_end;
return (int)strtol(tmp, (char **)NULL, 10);
}
int main(int argc, char *argv[]) {
FILE *file = fopen(argv[1], "r");
int res = 0;
char buffer[500];
int tmpNum;
while (fgets(buffer, sizeof(buffer), file)) {
int *win = NULL;
int *own = NULL;
int winIdx = 0;
int ownIdx = 0;
int matchCount = 0;
char *p_line = buffer;
while (*p_line != ':') p_line++;
for (; *p_line != '|'; p_line++) {
if (!is_a_num_char(p_line)) {
continue;
}
tmpNum = extract_int(&p_line);
int *tmp = realloc(win, sizeof(int) * (winIdx + 1));
if (tmp == NULL) {
printf("%s\n", "Memory Allocation Failed");
return 1;
}
win = tmp;
win[winIdx++] = tmpNum;
}
for (; *p_line != '\0'; p_line++) {
if (!is_a_num_char(p_line)) {
continue;
}
tmpNum = extract_int(&p_line);
int *tmp = realloc(own, sizeof(int) * (ownIdx + 1));
if (tmp == NULL) {
printf("%s\n", "Memory Allocation Failed");
return 1;
}
own = tmp;
own[ownIdx++] = tmpNum;
}
for (int ownCheckIdx = 0; ownCheckIdx < ownIdx; ownCheckIdx++) {
for (int winCheckIdx = 0; winCheckIdx < winIdx; winCheckIdx++) {
if (own[ownCheckIdx] == win[winCheckIdx]) {
matchCount++;
break;
}
}
}
if (matchCount) {
res += (int)pow(2, matchCount - 1);
}
free(win);
free(own);
}
printf("Res: %d\n", res);
return 0;
}
I try valgrind, try printing out stuff, try using malloc instead of null to assign the first memory address.
realloc(cardInstancesCount, sizeof(int) * (cardQuantity + 1));
if (tmp = NULL) {
Line 84. I didn't compare it. Just setting the pointer to NULL
.