Skip to content

Instantly share code, notes, and snippets.

@weirddan455
Created January 1, 2022 19:51
Show Gist options
  • Save weirddan455/638b478d2eacfd3659396bf99962daa0 to your computer and use it in GitHub Desktop.
Save weirddan455/638b478d2eacfd3659396bf99962daa0 to your computer and use it in GitHub Desktop.
Advent of Code Input Parsing
#include <fcntl.h>
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#include <sys/stat.h>
int main(void)
{
// Using POSIX open/read functions
// If using Windows, you probably want to use fopen/fread (or native Windows API)
// From my testing, these functions don't work very well on Windows.
// PS: The process of opening/reading the file can be copy+pasted and used in every AoC puzzle (works the same for any input).
// Open the file. open() returns a file descriptor "fd" that refers to the file.
int fd = open("input", O_RDONLY);
if (fd == -1)
{
perror("open");
return 1;
}
// Get the file size using fstat (fileInfo struct in an output parameter)
struct stat fileInfo;
if (fstat(fd, &fileInfo) != 0)
{
perror("fstat");
close(fd);
return 1;
}
// Allocate memory equal to the file size.
char *data = malloc(fileInfo.st_size);
if (data == NULL)
{
puts("malloc failed");
close(fd);
return 1;
}
// Read the contents of the file into the buffer we just allocated.
ssize_t bytesRead = read(fd, data, fileInfo.st_size);
// Close the file. It's read into the buffer and we don't need it anymore.
close(fd);
// -1 return value means failure. In this case, it will put the error number into "errno" which we can print out with perror() to understand why it failed.
if (bytesRead == -1)
{
perror("read");
free(data);
return 1;
}
// Check that we actually read in the entire file.
if (bytesRead != fileInfo.st_size)
{
printf("Error: read %d bytes. %d expected.\n", bytesRead, fileInfo.st_size);
free(data);
return 1;
}
// Count up the newlines in the input. This gives us the number of entries. In day 1, they're all just ints.
int numbers = 0;
for (ssize_t i = 0; i < bytesRead; i++)
{
if (data[i] == '\n')
{
numbers++;
}
}
// Allocate memory to store the ints we're about to parse.
int *array = malloc(numbers * sizeof(int));
if (array == NULL)
{
puts("malloc failed");
free(data);
return 1;
}
// Actual parsing begins.
ssize_t dataIndex = 0;
// Loop for each number in the input.
for (int i = 0; i < numbers; i++)
{
// Declare a string on the stack and keep track of its index.
// String needs to be large enough to hold each digit + a null termination character.
int stringIndex = 0;
char string[8];
// Continue until we hit a newline. If on Windows, this may need to be replaced by '\r' if you have CRLF line endings.
while (data[dataIndex] != '\n')
{
// Copy each digit into the string, advancing both indicies afterwards.
string[stringIndex++] = data[dataIndex++];
}
// Advance the dataIndex one more time to skip past the newline. If CRLF, do dataIndex += 2; instead.
dataIndex++;
// Add in the null termination character.
string[stringIndex] = 0;
// Use the atoi function to convert the string of digits into an int and store that value into our array.
array[i] = atoi(string);
}
return 0;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment