Skip to content

Instantly share code, notes, and snippets.

@Colk-tech
Last active June 17, 2021 15:17
Show Gist options
  • Select an option

  • Save Colk-tech/9feb379c500946c82ddf091aa6688437 to your computer and use it in GitHub Desktop.

Select an option

Save Colk-tech/9feb379c500946c82ddf091aa6688437 to your computer and use it in GitHub Desktop.
A useful library to read a file which is variable length. Written in C.
//
// Created by Manaki ITO on 2021/06/17.
//
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define DEFAULT_STR_BUFFER_LENGTH 512
#define DEFAULT_BUFFER_BYTES DEFAULT_STR_BUFFER_LENGTH * sizeof(char)
#define print_error(...) {fprintf(stderr, "\x1b[31m"); fprintf(stderr, __VA_ARGS__); fprintf(stderr, "\x1b[39m\n");}
#define fatal_with_message(exit_code, ...) {print_error(__VA_ARGS__); exit(exit_code);}
void read_lines_from(char *filename, char **result);
long long int line_number(char *filename);
int find_char(char *string, long long int str_length, char query);
void delete_char(char *string, long long int str_length, char query);
int sample_usage(void) {
char filename[] = "filename.c";
long long int lines = line_number(filename);
char **result = NULL;
result = (char**) malloc(sizeof(char*) * lines - 1);
read_lines_from(filename, result);
for (int i = 0; i < lines - 1; i++) {
printf("%s\n", result[i]);
}
return 0;
}
void read_lines_from(char *filename, char **result) {
FILE *fp = NULL;
char *current_line = NULL;
char *buf = NULL;
long long int line_count = 0;
long long int current_buffer_bytes = -1;
fp = fopen(filename, "r");
if (fp == NULL) {
fatal_with_message(1,
"[X] Error: Failed to open \"%s\".\n"
"Make sure the file name is correct and not accessed by any other process.\n"
"Aborting",
filename);
}
buf = (char *) malloc(sizeof(char) * DEFAULT_BUFFER_BYTES);
if (buf == NULL) {
fatal_with_message(1,
"[X] Unexpected error: Failed to allocate memory.\n"
"Make sure the file name is correct and not accessed by any other process.\n"
"Aborting")
}
while (1) {
current_buffer_bytes = DEFAULT_BUFFER_BYTES;
current_line = (char *) malloc(current_buffer_bytes);
if (current_line == NULL) {
fatal_with_message(1,
"[X] Unexpected error: Failed to allocate memory.\n"
"Make sure the file name is correct and not accessed by any other process.\n"
"Aborting")
}
if (fgets(current_line, DEFAULT_BUFFER_BYTES, fp) == NULL) {
break;
}
while (1) {
int continue_required = !(
find_char(current_line, current_buffer_bytes, '\n') ||
find_char(current_line, current_buffer_bytes, EOF));
if (!continue_required) {
break;
}
if (fgets(buf, DEFAULT_BUFFER_BYTES, fp) == NULL) {
break;
}
current_buffer_bytes += DEFAULT_STR_BUFFER_LENGTH;
current_line = realloc(current_line, current_buffer_bytes);
if (current_line == NULL) {
fatal_with_message(1,
"[X] Unexpected error: Failed to allocate memory.\n"
"Make sure the file name is correct and not accessed by any other process.\n"
"Aborting")
}
strcat(current_line, buf);
memset(buf, '\0', DEFAULT_BUFFER_BYTES);
}
delete_char(current_line, current_buffer_bytes / sizeof(char), '\n');
delete_char(current_line, current_buffer_bytes / sizeof(char), '\r');
result[line_count] = (char *) malloc(current_buffer_bytes);
memcpy(result[line_count], current_line, current_buffer_bytes);
free(current_line);
line_count++;
}
fclose(fp);
}
long long int line_number(char *filename) {
FILE *fp;
size_t read_size;
char buf[DEFAULT_BUFFER_BYTES];
long long int lines = 0;
if ((fp = fopen(filename, "r")) == NULL) {
fatal_with_message(1,
"[X] Unexpected error: Failed to allocate memory.\n"
"Make sure the file name is correct and not accessed by any other process.\n"
"Aborting")
}
while ((read_size = fread(buf, 1, DEFAULT_BUFFER_BYTES, fp)) > 0) {
for (size_t i = 0; i < read_size; i++) {
if (buf[i] == '\n') {
lines++;
}
}
}
lines++;
fclose(fp);
return lines;
}
int find_char(char *string, long long int str_length, char query) {
long long int i = 0;
while (i < str_length) {
if (string[i] == query) {
return 1;
}
i++;
}
return 0;
}
void delete_char(char *string, long long int str_length, char query) {
char *temp;
long long int size = str_length * sizeof(char);
temp = (char *) malloc(size);
if (temp == NULL) {
fatal_with_message(1,
"[X] Unexpected error: Failed to allocate memory.\n"
"Make sure the file name is correct and not accessed by any other process.\n"
"Aborting")
}
memset(temp, '\0', size);
for (int i = 0; i < str_length; i++) {
if (string[i] != query) {
temp[i] = string[i];
}
}
memcpy(string, temp, str_length * sizeof(char));
free(temp);
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment