阅读文本文件C编程中的下一行

时间:2013-06-03 19:59:52

标签: c text-files

我知道 fscanf(),fgets() 以及读取文本文件下一行的其他函数。但是,如果您通过 'cat msg1.txt |给出了一个文本文件./anonymizer' 你会使用相同的功能吗? 对于我的程序,主要的代码是:

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;
}

在命令行中输入:

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

我的msg1文本文件包含:

  

嗨,我的电子邮件地址是h.potter@hogwarts.edu和1a @ 2b3c @ lkj @   虽然它不是电子邮件地址,但我讨厌@如果你看到了我的电子邮件地址   悄悄话。 Gary.zenkel@nbcuni.com然而,仅输入变量   包含第一行:'嗨,我的电子邮件地址是   h.potter@hogwarts.edu和1a @ 2b3c @ lkj @'

如何让输入变量包含其他两行?

2 个答案:

答案 0 :(得分:0)

几乎。虽然实际上可能没有以这种方式定义,scanf(...)基本上等同于fscanf(stdin, ...)。类似于gets / fgets。您应该能够使用其中一个来读取标准输入流。

答案 1 :(得分:0)

对于我有限的知识(我可能是错的),使用标准的libc,当你不知道最大行长度时,没有有效的方法来读取一行。使用scanf()gets()可能会导致内存溢出,因为它们不会检查缓冲区的长度。如果您使用fgets(),则可能会在频繁的strlen()realloc()上浪费时间。如果您使用fgetc(),则速度会很慢,因为fgetc()会产生巨大的开销。

为了有效读取线路,我们必须保留一些中间信息。这并不容易。我附加了一个实现。它非常复杂,但非常有效且通用。如果您不关心细节,可以关注如何使用例程的main()函数。

试试这个程序:

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

程序:

#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;
}