How to read line by line after i read a text into a buffer?
Asked Answered
B

4

7

First , I read a text into a buffer by calling fread, and then I want to read it line by line, how to do it? I try to use a sscanf , but it seems not to work.

char textbuf[4096];
char line[256];
FILE *fp;
fp = fopen(argv[1],"r");
memset(textbuf, 0, 4096);
fread(textbuf, 1, 4096, fp);

I know using fgets is a good way. I just want to know weather this method can do the same thing.

Bangor answered 12/5, 2012 at 2:14 Comment(2)
Why not use fgets() to read the file one line at a time?Settera
Or getline() if you are on system POSIX-compatible..Trite
T
11

Try this:

fgets(textbuf, sizeof(textbuf), fp);

For read line by line you can use: fgets(line, 128, fp) or getline(&line, &size, fp);

EDIT

If you want to read it from a variable, look at strtok() function:

char * line = strtok(strdup(buffer), "\n");
while(line) {
   printf("%s", line);
   line  = strtok(NULL, "\n");
}
Trite answered 12/5, 2012 at 2:22 Comment(4)
@AdamLiss: It's depends. See that have two questions here. One can be solved using fgets() only and another can be solved by using fgets() or getline().Trite
both fgets and getline need file poiter, so, there is no need to call fread. i want to read line by line from buffer, how ?Bangor
@ccsnailpp: something like the second code example? or want read this from a variable?Trite
@Trite i want to read it from a variable, not from a file poiterBangor
S
8

You can find the location of the end-of-line character using strchr() like this:

char *eol = strchr(line, '\n');

Everything before *eol is the first line. Then advance from line to eol + 1, remove any subsequent \r or \n characters, and repeat the process until strchr() returns NULL to indicate there are no more newline characters. At that point, move any remaining data to the beginning of the buffer and read the next chunk from the file.

If you're concerned about efficiency you can avoid moving the data by using 2 buffers and alternating between them, but even the naive method is probably faster than fgets() if the file has many lines.

Settera answered 12/5, 2012 at 2:30 Comment(1)
best and simplest version so far!Sightless
A
2

how about strtok

char *line;
line = strtok(texbuf, '\n');
Angara answered 12/5, 2012 at 2:23 Comment(2)
Be very careful using strtok(). It's not reentrant, and it modifies its input as it processes it.Settera
@nos yeah, i have already known that, so it's just a trying. an alternative method. I think fgets is the simplest.Bangor
M
0

You said "I know using fgets is a good way. I just want to know weather this method can do the same thing.", of course you can, you just re-implement fgets as in the c library. The c library doesn't actually read line by line, it reads in a whole chunk and gives you a line when you call fgets.

Not an efficient way, but a sample of the kind of things you have to do.

#include <stdio.h>
typedef struct my_state {
 unsigned char * buf;
 int offset;
 int buf_size;
 int left;
 FILE * file;
} my_state_t;
int takeone(my_state_t * state) {
 if ((state->left - state->offset)<=0) {
  if (feof(state->file)) return -1;
  state->left = fread(state->buf,1,state->buf_size,state->file);
  state->offset = 0;
  if (state->left == 0) return -1;
 }
 return state->buf[state->offset++];
}
int getaline(my_state_t * state, char * out, int size) {
 int c;
 c = takeone(state);
 if (c < 0) return 0;
 while (c >=0 && size > 1) {
  *out++ = c;
  --size;
  if (c == '\n') break;
  c = takeone(state);
 }
 *out=0;
 return 1;
}
int main(int argc, char ** argv){
 FILE *fp;
 char textbuf[4096];
 char line[256];
 my_state_t fs;
 fs.buf=textbuf;
 fs.offset=0;
 fs.buf_size=4096;
 fs.left=0;
 fp = (argc>1)? fopen(argv[1],"rb") : stdin;
 fs.file = fp;
 while (getaline(&fs,line,256)) {
  printf("-> %s", line);
 }
 fclose(fp);
}
Margertmargery answered 12/5, 2012 at 2:29 Comment(1)
that's almost what i want. I nearly forget fgets is a libary function , not a system call.Bangor

© 2022 - 2024 — McMap. All rights reserved.