DEV Community

齊藤敦志
齊藤敦志

Posted on

Reading text file and split by line

#c

There are many troublesome in text processing in the programming language C. Even just write program that read line by line make time consume. I have read articles that try to implement it.

I have experience to write chat CGI that include line text processing.

Just read the whole file at once by fread.

reading text by line

And replace return to null. It is apparently an array of rows.

replace return to null

The implementation is above.

// whole.h
char** whole(const char* const filename);
void freewhole(char** m);
Enter fullscreen mode Exit fullscreen mode
// whole.c
#include <stdio.h>
#include <stdlib.h>

static long int filesize(FILE* fp) {
  fseek(fp, 0, SEEK_END);
  long int size = ftell(fp);
  fseek(fp, 0, SEEK_SET);
  return size;
}

static int countline(char* block) {
  int line = 0;

  for(int i=0, flag=0; block[i]; i++)
    switch(block[i]) {
    case '\r': line++; flag=1; break;
    case '\n': if(flag) flag = 0; else line++; break;
    default: flag = 0;
    }

  return line+2;
}

static char* nextline(char* str) {
  char* n;
  for(n=str; *n!='\n' && *n!='\r' && *n!='\0'; n++);
  switch(*n) {
  case '\0': return NULL;
  case '\r': *n++='\0'; if(*n=='\n') n++; if(*n=='\0') return NULL; break;
  case '\n': *n++='\0'; if(*n=='\0') return NULL; break;
  }
  return n;
}

static char* readall(const char* const filename) {
  FILE* fp = fopen(filename, "rb");
  if(fp==NULL) {perror(NULL); exit(EXIT_FAILURE); }
  int size = filesize(fp);
  char* block = malloc(size+1);
  if(block==NULL) {perror(NULL); exit(EXIT_FAILURE); }
  int read_size = fread(block, 1, size, fp);
  fclose(fp);
  block[read_size]='\0';
  return block;
}

static char** split(char* block) {
  int linelength=countline(block);
  char** lines = malloc(linelength*sizeof(char*));
  if(lines==NULL) {perror(NULL); exit(EXIT_FAILURE); }
  char** p;
  for(p=lines; block!=NULL; block=nextline(block)) *p++=block;
  *p=NULL;
  return lines;
}

char** whole(const char* const filename) {
  char* block = readall(filename);
  return split(block);
}

void freewhole(char** m) {
  free(m[0]);
  free(m);
}
Enter fullscreen mode Exit fullscreen mode

Example of use.

// example.c
#include <stdio.h>
#include "whole.h"

int main(void) {
  char** lines = whole("test.txt");

  for(int i=0; lines[i]; i++) printf("%d %s\n", i, lines[i]);

  freewhole(lines);

  return 0;
}
Enter fullscreen mode Exit fullscreen mode

Top comments (0)