2012-05-12 32 views
5

Đầu tiên, tôi đọc một văn bản vào một bộ đệm bằng cách gọi fread, và sau đó tôi muốn đọc nó từng dòng một, làm thế nào để làm điều đó? Tôi cố gắng sử dụng một sscanf, nhưng có vẻ như không hoạt động.Làm thế nào để đọc từng dòng sau khi tôi đọc một văn bản vào bộ đệm?

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

Tôi biết sử dụng fgets là một cách hay. Tôi chỉ muốn biết thời tiết phương pháp này có thể làm điều tương tự.

+0

Tại sao không sử dụng 'fgets()' để đọc từng dòng một tệp? –

+0

Hoặc 'getline()' nếu bạn đang sử dụng hệ thống tương thích POSIX .. – Jack

Trả lời

7

Hãy thử điều này:

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

Đối với dòng đọc theo dòng bạn có thể sử dụng: fgets(line, 128, fp) hoặc getline(&line, &size, fp);

EDIT

Nếu bạn muốn đọc nó từ một biến, nhìn vào strtok() chức năng:

char * line = strtok(strdup(buffer), "\n"); 
while(line) { 
    printf("%s", line); 
    line = strtok(NULL, "\n"); 
} 
+0

'fgets()' hoặc 'getline()'? Hãy quyết định! :-) –

+0

@AdamLiss: Điều đó tùy thuộc. Thấy rằng có hai câu hỏi ở đây. Người ta có thể được giải quyết bằng cách sử dụng fgets() và người khác có thể được giải quyết bằng cách sử dụng fgets() hoặc getline(). – Jack

+0

cả hai fgets và getline cần tập thơ, vì vậy, không cần phải gọi fread. tôi muốn đọc từng dòng từ bộ đệm, làm thế nào? –

2

thế nào về strtok

char *line; 
line = strtok(texbuf, '\n'); 
+0

Hãy _very_ cẩn thận khi sử dụng 'strtok()'. Nó không reentrant, và nó sửa đổi đầu vào của nó khi nó xử lý nó. –

+0

@ yeah yeah, tôi đã biết điều đó, vì vậy nó chỉ là một cố gắng. một phương pháp thay thế. Tôi nghĩ rằng 'fgets' là đơn giản nhất. –

0

Bạn nói: "Tôi biết cách sử dụng fgets là một cách tốt. Tôi chỉ muốn biết thời tiết phương pháp này có thể làm điều tương tự. ", Tất nhiên bạn có thể, bạn chỉ cần thực hiện lại fgets như trong thư viện C. Thư viện c không thực sự đọc từng dòng, nó đọc trong một toàn bộ đoạn và cung cấp cho bạn một dòng khi bạn gọi fgets.

Không một cách hiệu quả, nhưng một mẫu của các loại điều bạn phải làm.

#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); 
} 
+0

đó là gần như những gì tôi muốn. Tôi gần như quên 'fgets' là một hàm libary, không phải là một lời gọi hệ thống. –

5

bạn có thể tìm thấy vị trí của end-of ký tự dòng sử dụng strchr() như sau:

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

Mọi thứ trước *eol là dòng đầu tiên. Sau đó, hãy thăng tiến từ line đến eol + 1, xóa mọi ký tự \r hoặc \n tiếp theo và lặp lại quy trình cho đến khi strchr() trả lại NULL để cho biết không còn ký tự dòng mới nào nữa. Tại thời điểm đó, di chuyển bất kỳ dữ liệu còn lại vào đầu bộ đệm và đọc đoạn tiếp theo từ tệp.

Nếu bạn lo ngại về hiệu quả bạn có thể tránh di chuyển dữ liệu bằng cách sử dụng 2 bộ đệm và xen kẽ giữa chúng, nhưng ngay cả những phương pháp ngây thơ có lẽ là nhanh hơn so với fgets() nếu tập tin có nhiều dòng.

+0

vâng, tôi nghĩ rằng nó hoạt động. –

+0

phiên bản tốt nhất và đơn giản nhất cho đến nay! – br1

Các vấn đề liên quan