Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/search/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
在文本文件C中搜索字符串_C_Search_String - Fatal编程技术网

在文本文件C中搜索字符串

在文本文件C中搜索字符串,c,search,string,C,Search,String,以下代码一次读取一个文本文件一个字符,然后将其打印到标准输出: #include <stdio.h> int main() { char file_to_open[] = "text_file.txt", ch; FILE *file_ptr; if((file_ptr = fopen(file_to_open, "r")) != NULL) { while((ch = fgetc(file_ptr)) != EOF)

以下代码一次读取一个文本文件一个字符,然后将其打印到标准输出:

#include <stdio.h>

int main()
{
    char file_to_open[] = "text_file.txt", ch;
    FILE *file_ptr;

    if((file_ptr = fopen(file_to_open, "r")) != NULL)
    {
        while((ch = fgetc(file_ptr)) != EOF)
        {
            putchar(ch);
        }
    }
    else
    {
        printf("Could not open %s\n", file_to_open);
        return 1;
    }
    return(0);
}
strings.txt

1993 - 1999 Pentium 1997 - 1999 Pentium II 1999 - 2003 Pentium III 1998 - 2009 Xeon 2006 - 2009 Intel Core 2 Nehalem AMD Athlon Pentium 尼哈勒姆 阿特隆酒店 奔腾 在这种情况下,
text_file.txt
的前三行将匹配。我对C语言中的文件操作做了一些研究,似乎我可以用
fgetc
[就像我在代码中做的那样]一次读一个字符,用
fgets
读一行,用
fread
读一个块,但我想在我的情况下没有一个单词是完美的?

记住:fgetc(),getc(),getchar都返回一个整数,不是一个字符。整数可能是EOF或有效字符,但它返回的值比字符类型支持的范围多一个值

您正在为“fgrep”命令编写代理:

fgrep -f strings.txt text_file.txt > out.txt
您需要使用fgets()读取行,而不是读取字符。(忘记存在get()函数!)

我缩进了您的代码并插入了一个返回0;在结尾处(尽管如果从main()的结尾处掉下来,C99会隐式返回0;)。然而,C99也要求每个函数都有一个显式的返回类型——我为您在“int main()”中添加了“int”(但您不能用C99兼容的借口在结尾不返回0)。错误消息应该写入标准错误,而不是标准输出

您可能需要对字符串列表使用动态分配。简单的搜索将简单地应用“strstr()”搜索每行输入中的每个所需字符串(确保在找到匹配项后中断循环,以便在一行上有多个匹配项时不会重复该行)


更复杂的搜索将预先计算哪些字符可以忽略,这样您就可以并行搜索所有字符串,跳过文本的速度比循环中的快。这可能是对搜索算法的修改,例如Boyer Moore或Knuth Morris Pratt(添加:或Rabin Karp,其设计用于并行搜索多个字符串)。

按块读取总是更好,因为它是底层文件系统的工作方式

因此,只需按块读取,检查缓冲区中是否出现任何单词, 然后读取另一个缓冲区已满。您只需小心地在新缓冲区中重新复制上一个缓冲区的最后几个字符,以避免在搜索词位于缓冲区边界时丢失检测


如果这个简单的算法还不够(在您的情况下,它可能是不够的),那么还有更复杂的算法可以在一个缓冲区中同时搜索多个子字符串cf。

我假设这是一个学习练习,您只是在寻找一个开始的地方。否则,你不应该重新发明轮子

下面的代码应该让您了解其中所涉及的内容。它是一个程序,允许您指定要搜索的文件名和要在该文件中搜索的单个参数。您应该能够修改它,将要搜索的短语放入字符串数组中,并检查该数组中的任何单词是否出现在所读取的任何行中

您正在寻找的关键功能是

#包括
#包括
#包括
#ifdef调试
#定义初始分配2
#否则
#定义初始分配512
#恩迪夫
煤焦*
读取行(文件*fin){
字符*缓冲区;
char*tmp;
int read_chars=0;
int bufsize=初始分配;
char*line=malloc(bufsize);
如果(!行){
返回NULL;
}
缓冲区=行;
而(fgets(缓冲区、bufsize-读取字符、fin)){
read_chars=strlen(行);
如果(第[read_chars-1]行='\n'){
行[read_chars-1]='\0';
回流线;
}
否则{
bufsize=2*bufsize;
tmp=realloc(直线,bufsize);
如果(tmp){
直线=tmp;
缓冲区=行+读取字符;
}
否则{
自由线;
返回NULL;
}
}
}
返回NULL;
}
int
main(int argc,char*argv[]){
文件*fin;
字符*行;
如果(argc!=3){
返回退出失败;
}
fin=fopen(argv[1],“r”);
国际单项体育联合会(财务){
而(行=读取行(fin)){
if(strstr(行,argv[2])){
fprintf(标准输出,“%s\n”,行);
}
自由线;
}
}
财务总监(财务);
返回0;
}
样本输出:

E:\Temp> searcher.exe searcher.c char char * char *buffer; char *tmp; int read_chars = 0; char *line = malloc(bufsize); while ( fgets(buffer, bufsize - read_chars, fin) ) { read_chars = strlen(line); if ( line[read_chars - 1] == '\n' ) { line[read_chars - 1] = '\0'; buffer = line + read_chars; main(int argc, char *argv[]) { char *line; E:\Temp>searcher.exe searcher.c char 煤焦* 字符*缓冲区; char*tmp; int read_chars=0; char*line=malloc(bufsize); 而(fgets(缓冲区、bufsize-读取字符、fin)){ read_chars=strlen(行); 如果(第[read_chars-1]行='\n'){ 行[read_chars-1]='\0'; 缓冲区=行+读取字符; main(int argc,char*argv[]){ 字符*行;
你为什么要写这个程序?!使用grep/awk/sed来做这个。不,Tim。标记是用来搜索的。没有人会去搜索。是的,我知道用标准的Unix工具我可以在几秒钟内解决这个问题,但这是为了更深入地理解C文件IO。当你使用fgetc()时,我相当肯定stdio将按块和缓冲字符读取…是的,但是调用fgetc本身会有成本,如果您想将输入与一个字符串(或多个字符串)进行比较你必须将其复制到某个地方。这比读取完整缓冲区并使用它的成本要高得多。如果你不想管理自己直接读取缓冲区的血淋淋的细节,那么按照Jonathan的建议读取完整行也是读取完整缓冲区的一个好选择。你的意思是
fgrep-f strings.txt text\u file.txt>out.txt?是的,是的,
fgrep-f strings.txt text_file.txt
。我想更多的接触意味着更多的选择。谢谢。编写一个C程序来做这件事完全是浪费时间。任何与学习有关的事情都不是浪费时间,至少我认为是这样。但如果这不是为了学习一些东西
#include <stdio.h>
#include <string.h>
#include <stdlib.h>

#ifdef DEBUG
#define INITIAL_ALLOC 2
#else
#define INITIAL_ALLOC 512
#endif

char *
read_line(FILE *fin) {
    char *buffer;
    char *tmp;
    int read_chars = 0;
    int bufsize = INITIAL_ALLOC;
    char *line = malloc(bufsize);

    if ( !line ) {
        return NULL;
    }

    buffer = line;

    while ( fgets(buffer, bufsize - read_chars, fin) ) {
        read_chars = strlen(line);

        if ( line[read_chars - 1] == '\n' ) {
            line[read_chars - 1] = '\0';
            return line;
        }

        else {
            bufsize = 2 * bufsize;
            tmp = realloc(line, bufsize);
            if ( tmp ) {
                line = tmp;
                buffer = line + read_chars;
            }
            else {
                free(line);
                return NULL;
            }
        }
    }
    return NULL;
}

int
main(int argc, char *argv[]) {
    FILE *fin;
    char *line;

    if ( argc != 3 ) {
        return EXIT_FAILURE;
    }

    fin = fopen(argv[1], "r");

    if ( fin ) {
        while ( line = read_line(fin) ) {
            if ( strstr(line, argv[2]) ){
                fprintf(stdout, "%s\n", line);
            }
            free(line);
        }
    }

    fclose(fin);
    return 0;
}
E:\Temp> searcher.exe searcher.c char char * char *buffer; char *tmp; int read_chars = 0; char *line = malloc(bufsize); while ( fgets(buffer, bufsize - read_chars, fin) ) { read_chars = strlen(line); if ( line[read_chars - 1] == '\n' ) { line[read_chars - 1] = '\0'; buffer = line + read_chars; main(int argc, char *argv[]) { char *line;