I have this intermediary buffer that has the entire contents of a file: char *intermediary_buffer
I need to move this to a different 2D buffer: char **final_buffer
Where a new row is started every time the \n
escape sequence is detected in the original buffer. Effectively storing each line of the file in its own row.
I thought about using a for loop, where it would scan through the intermediary buffer and copy every part leading up to the \n
escape sequence in a row:
for(int i = 0; i < file_size; i++){
if(intermediary_buffer[i] == '\n'){
// Copy all leading up to `\n` to new 2D buffer
}
}
I get lost after creating the for loop . . .
How can I achieve this in a fast way?
One option is to iterate through the memory block that contains the file contents using strcspn
. Allocate pointers and allocate memory to each pointer. realloc
can allocate pointers and strndup
will handle the allocation of memory to each pointer and copy data to the allocated memory.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define SIZE 8129
char **strpdlm ( char *source, char *delim) {
char **target = NULL; // pointer to pointer
int span = 0;
int count = 0;
while ( source && *source) {
span = strcspn ( source, delim); // count to next delimiter
char **temp = NULL;
if ( NULL == ( temp = realloc ( target, sizeof target * ( count + 2)))) { // allocate two more pointers
fprintf ( stderr, "realloc problem\n");
return target;
}
target = temp;
if ( NULL == ( target[count] = strndup ( source, span + 1))) { // allocate memory and copy to one pointer
fprintf ( stderr, "strndup problem\n");
return target;
}
++count;
target[count] = NULL; // the other pointer serves as sentinel NULL
source += span; // advance pointer
if ( *source) { // not at terminating zero
++source; // advance past delimiter
}
}
return target;
}
char *readcontents ( char *filename) {
char *contents = NULL;
char buffer[SIZE] = "";
size_t size = 0;
size_t bytes = 0;
FILE *pf = NULL;
if ( NULL == ( pf = fopen ( filename, "r"))) {
perror ( filename); // why the file could not be opened
return contents;
}
while ( 0 < ( bytes = fread ( buffer, 1, sizeof buffer, pf))) { // read a buffer from file
char *temp = NULL;
if ( NULL == ( temp = realloc ( contents, size + bytes + 1))) { // reallocate contents for buffer
fprintf ( stderr, "problem realloc\n");
fclose ( pf);
return contents;
}
contents = temp;
memmove ( contents + size, buffer, bytes); // append buffer to contents
size += bytes;
contents[size] = 0; // terminating zero
}
fclose ( pf);
return contents;
}
int main ( void) {
char *filename = "file.txt";
char *contents = NULL;
char *delim = "\n";
char **lines = NULL;
if ( NULL == ( contents = readcontents ( filename))) {
fprintf ( stderr, "no contents in file %s\n", filename);
return 1;
}
printf ( "contents\n%s\n", contents);
if ( NULL == ( lines = strpdlm ( contents, delim))) {
free ( contents);
fprintf ( stderr, "strpdlm returned NULL\n");
return 1;
}
free ( contents); // free contents
size_t each = 0;
printf ( "\nlines\n");
while ( lines[each]) { // not at sentinel NULL
printf ( "lines[%zu]%s", each, lines[each]);
++each;
}
printf ( "\n");
each = 0;
while ( lines[each]) { // not at sentinel NULL
free ( lines[each]); // free pointer memory
++each;
}
free ( lines); // free pointers
return 0;
}