简体   繁体   中英

Read next line in Text file C Programming

I know about fscanf(), fgets() and those other functions to read the next line of a text file. However, if you are given a text file by 'cat msg1.txt |./anonymizer' would you use the same functions? For my program the code for the main is:

int main (void)
{
    char input[1000]= {'\0'}; //the sentence the user will enter
    printf("Enter a sentence:");
    scanf("%[^\n]", input);
    char newSentence[1000]={'\0'};
    sentence=(char *) &newSentence;
    line=getText(input,0);
    divide(input);
    printf("%s\n",sentence);
    return 0;
}

In the command line I enter:

gcc -o anonymizer anonymizer.c
cat msg1.txt | ./anonymizer

My msg1 text file contains:

Hi, my email addresses are h.potter@hogwarts.edu and 1a@2b3c@lkj@ Although it's not an email addresses, I'd hate if@ you saw my secret@word. Gary.zenkel@nbcuni.comHoever, input variable only contains the first line: 'Hi, my email addresses are h.potter@hogwarts.edu and 1a@2b3c@lkj@'

How can I get the input variable to contain the other two lines?

Almost. While it may not actually be defined in such a way, scanf(...) is essentially equivalent to fscanf(stdin, ...) . Similar for gets / fgets . You should be able to use either to read from your standard input stream.

To my limited knowledge (I could be wrong), with the standard libc, there are no efficient ways to read a line when you do not know the max line length. You may get memory overflow with scanf() and gets() because they do not check the length of your buffer. If you use fgets() , you may waste time on frequent strlen() and realloc() . If you use fgetc() , it will be slow as fgetc() has a huge overhead.

For efficient line reading, we have to keep some intermediate information. It is not that easy. I am attaching an implementation. It is quite complicated, but it is very efficient and generic. If you do not care about the details, you may just focus on the main() function about how to use the routines.

To try this program:

gcc -Wall prog.c; ./a.out < input.txt > output.txt

Program:

#include <stdio.h>
#include <string.h>
#include <stdlib.h>

#ifndef kroundup32
#define kroundup32(x) (--(x), (x)|=(x)>>1, (x)|=(x)>>2, (x)|=(x)>>4, (x)|=(x)>>8, (x)|=(x)>>16, ++(x))
#endif

#define kstype_t FILE* // type of file handler
#define ksread_f(fp, buf, len) fread((buf), 1, (len), (fp)) // function to read a data chunk

typedef struct {
    int l, m; // l: length of string; m: allocated size
    char *s; // string
} kstring_t;

typedef struct {
    kstype_t f; // file handler
    int begin, end, is_eof, bufsize;
    unsigned char *buf; // buffer
} kstream_t;

kstream_t *ks_open(kstype_t fp, int bufsize)
{
    kstream_t *ks;
    ks = (kstream_t*)calloc(1, sizeof(kstream_t));
    ks->bufsize = bufsize;
    ks->buf = (unsigned char*)malloc(bufsize);
    ks->f = fp;
    return ks;
}

void ks_close(kstream_t *ks)
{
    free(ks->buf); free(ks);
}

int ks_readline(kstream_t *ks, int delimiter, kstring_t *str)
{
    str->l = 0;
    if (ks->begin >= ks->end && ks->is_eof) return -1;
    for (;;) {
        int i;
        if (ks->begin >= ks->end) {
            if (!ks->is_eof) {
                ks->begin = 0;
                ks->end = ksread_f(ks->f, ks->buf, ks->bufsize);
                if (ks->end < ks->bufsize) ks->is_eof = 1;
                if (ks->end == 0) break;
            } else break;
        }
        for (i = ks->begin; i < ks->end; ++i)
            if (ks->buf[i] == delimiter) break;
        if (str->m - str->l < i - ks->begin + 1) {
            str->m = str->l + (i - ks->begin) + 1;
            kroundup32(str->m);
            str->s = (char*)realloc(str->s, str->m);
        }
        memcpy(str->s + str->l, ks->buf + ks->begin, i - ks->begin);
        str->l = str->l + (i - ks->begin);
        ks->begin = i + 1;
        if (i < ks->end) break;
    }
    if (str->s == 0) {
        str->m = 1;
        str->s = (char*)calloc(1, 1);
    }
    str->s[str->l] = '\0';
    return str->l;
}

int main()
{
    kstream_t *ks;
    kstring_t str;
    str.l = str.m = 0; str.s = 0; // initialize the string struct
    ks = ks_open(stdin, 4096); // initialize the file handler
    while (ks_readline(ks, '\n', &str) >= 0) // read each line
        puts(str.s); // print it out
    ks_close(ks); free(str.s); // free
    return 0;
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM