C - 从文本文件中打印特定行

时间:2015-05-26 05:59:51

标签: c file search

我是编程新手,所以请保持愉快。

目前我正在尝试编写一个打开文本文件的程序,读入两个单词,搜索文本文件计算两个单词出现的次数,然后最后打印出第一个单词出现的第一行。

到目前为止,这就是我所做的:

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

FILE *infile;
char inputWord1[100], inputWord2[100], filename[100], wordInText[100], line[500]; 
int i, count, strComp, word1Count, word2Count, wordLen, lineCount; 
char c;

int main() { 
    printf("Enter the first word: "); 
    gets(inputWord1); 
    printf("Enter the second word: "); 
    gets(inputWord2); 
    printf("Enter the file name: "); 
    gets(filename); 

    infile = fopen(filename, "r"); 
    if(infile == NULL) { 
        printf("Error"); 
        exit(1); 
    } 

    word1Count = 0; word2Count = 0; lineCount = 1;
    while(fscanf(infile, "%s", wordInText) != EOF) { 
        wordLen = strlen(wordInText);
        for(i = 0; i < wordLen; i++) {
            if(wordInText[i] >= 65 && wordInText[i] <= 90) { 
                wordInText[i] = wordInText[i] + 32; 
            }
        }

        for(c = getc(infile); c != EOF; c = getc(infile)) {
            if(c == '\n') { 
                lineCount = lineCount + 1;
            }
        }

        strComp = strcmp(wordInText, inputWord1); 
        if(strComp == 0) { 
            word1Count++;
            if(word1Count == 1) { 
                for(int x = lineCount; x <= lineCount; x++) {
                    fgets(line, 500, infile); 
                    printf("%s\n", line);
                }
            }
        }
        strComp = strcmp(wordInText, inputWord2); 
        if(strComp == 0) { 
            word2Count++; 
        }
    }
    printf("Word 1 appears %d times\n", word1Count); 
    printf("Word 2 appears %d times\n", word2Count);
}

所以这一切都有效:

strComp = strcmp(wordInText, inputWord1); 
        if(strComp == 0) { 
            word1Count++;
            if(word1Count == 1) { 
                for(int x = lineCount; x <= lineCount; x++) {
                    fgets(line, 500, infile); 
                    printf("%s\n", line);
                }
            }
        }

最后一个for循环无法正常工作。它打印出\ n但不打印该行。我真的不知道为什么它不起作用。所有其他部分工作正常。

如果有人对如何解决这个问题有任何想法,我会非常感激。请记住我只知道基本的C函数,我还没有完成这个程序(仍然需要将输入的单词转换为小写)。

2 个答案:

答案 0 :(得分:0)

应该替换

gets以避免缓冲区溢出 我使用了一些定义,当我们找到输入行为双字并在末尾打印时。 文件逐行读取,每行逐字拆分。 解析应该更新,例如允许多个空格,支持更多的单词分隔符等...

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

#define WORD_LEN_MAX 100                                                       
#define LINE_LEN_MAX 500                                                       

int main() {                                                                   
    FILE *infile;                                                              
    char inputWord1[WORD_LEN_MAX], inputWord2[WORD_LEN_MAX];                   
    char filename[WORD_LEN_MAX];                                               
    char wordInText[WORD_LEN_MAX], line[LINE_LEN_MAX];                         
    char firsAppear[LINE_LEN_MAX];                                             
    int word1Count, word2Count, lineCount, i;                                  
    printf("Enter the first word: ");                                          
    gets(inputWord1);                                                          
    printf("Enter the second word: ");                                         
    gets(inputWord2);                                                          
    printf("Enter the file name: ");                                           
    gets(filename);                                                            


    infile = fopen(filename, "r");                                             
    if(infile == NULL) {                                                       
        printf("Error cannot open %s", filename);                              
        exit(1);                                                               
    }                                                                          

    word1Count = 0; word2Count = 0; lineCount = 1;                             
    while(fgets(line, sizeof(line), infile) != NULL) {                         
        char *p = line;                                                        
        lineCount++;                                                           
        while (*p != '\0' && *p != '\n') {                                     
            i = 0;                                                             
            while (*p != ' ' && *p != '\0' && *p != '\n') {                    
                wordInText[i++] = tolower(*p++);                               
            }                                                                  
            if (*p == ' ') {                                                   
                p++;                                                           
            }                                                                  
            wordInText[i] = '\0';                                              

            if(!strcmp(wordInText, inputWord1)) {                              
                word1Count++;                                                  
                if(word1Count == 1) {                                          
                    strncpy(firsAppear, line, sizeof(firsAppear));             

                }                                                              
            }                                                                  
            if(!strcmp(wordInText, inputWord2)) {                              
                word2Count++;                                                  
            }                                                                  
        }                                                                      
    }                                                                          
    printf("Word 1 appears %d times\n", word1Count);                           
    printf("Word 2 appears %d times\n", word2Count);                           
    printf("%s", firsAppear);                                                  
}

答案 1 :(得分:0)

有很多方法可以做到这一点。但是,您选择的方法必须面向更难的一端。在寻找正确使用的工具时,在阅读时,使用面向行的输入几乎总是正确的选择。既然如此,gets 永远是正确的选择。这是非常不安全的,已从C库中删除,改为使用fgets(或getline)。

避免使用全局变量。你的程序没用。它们的用途有限,但对于简单的程序,你几乎不会使用它们。

当你需要比较单词并总结匹配数时,就这样做...比较,如果匹配则增加总和。不需要其他任何东西。

对于lineCount如果你使用面向行的输入,它是微不足道的,只需增加每行读取的计数器。

但如何获得测试的话? strtok(或strsep)是提供的工具。只需阅读一行并标记化即可。然后只需比较和增加。

我把一个简短的例子放在一起。 (大多数代码只是从输入的末尾剥离newline)。它很简单,读取一行,标记,比较和增加匹配,增加lineCount。完成:

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

/* Avoid Globals */

#define MAXL 500
#define MAXW 100

int main (void)
{
    char inputWord1[MAXW] = { 0 };      /* Always Initialize your Variables */
    char inputWord2[MAXW] = { 0 };
    char filename[MAXW] = { 0 };
    char line[MAXL] = { 0 };
    char *token = NULL;
    char *delim = " ,.;\n";
    size_t word1Count = 0;              /* can't be negative, use   */
    size_t word2Count = 0;              /* size_t or unsigned       */
    size_t lineCount = 0;
    size_t len = 0;
    FILE *infile = NULL;

    printf ("\nEnter the first word: ");        /* Do NOT use gets, it is insecure  */
    fgets (inputWord1, MAXW, stdin);            /* use fgets or getline instead     */        

    len = strlen (inputWord1);
    while (len > 0 && (inputWord1[len-1] == '\n' || inputWord1[len-1] == '\r'))
        inputWord1[--len] = 0;                  /* strip newline or carriage return */

    printf ("\nEnter the second word: ");
    fgets (inputWord2, MAXW, stdin);

    len = strlen (inputWord2);
    while (len > 0 && (inputWord2[len-1] == '\n' || inputWord2[len-1] == '\r'))
        inputWord2[--len] = 0;                  /* strip newline or carriage return */

    printf ("\nEnter the file name: ");
    fgets (filename, MAXW, stdin);

    len = strlen (filename);
    while (len > 0 && (filename[len-1] == '\n' || filename[len-1] == '\r'))
        filename[--len] = 0;                    /* strip newline or carriage return */

    infile = fopen (filename, "r");
    if (infile == NULL) {
        printf ("error: file open failed. '%s'\n", filename);
        exit (1);
    }

    printf ("\nThe lines processed are:\n\n");

    /* read each line, tokenize, compare and increment */
    while (fgets (line, MAXL, infile) != NULL)
    {
        len = strlen (line);
        while (len > 0 && (line[len-1] == '\n' || line[len-1] == '\r'))
            line[--len] = 0;                    /* strip newline or carriage return */

        printf ("  %2zu  %s\n", lineCount, line);
        for (token = strtok (line, delim); token != NULL; token = strtok (NULL, delim)) 
        {
            if (strcmp (token, inputWord1) == 0)
                word1Count++;
            if (strcmp (token, inputWord2) == 0)
                word2Count++;
        }

        lineCount++;
    }

    printf ("\nWord 1 appears %zu times\n", word1Count);
    printf ("Word 2 appears %zu times\n", word2Count);
    printf ("Number of lines: %zu\n\n", lineCount);

    return 0;
}

使用/输出

$ ./bin/countw1w2

Enter the first word: me

Enter the second word: chequer

Enter the file name: dat/ll_replace_poem.txt

The lines processed are:

   0  Eye have a spelling chequer,
   1  It came with my Pea Sea.
   2  It plane lee marks four my revue,
   3  Miss Steaks I can knot sea.
   4  Eye strike the quays and type a whirred,
   5  And weight four it two say,
   6  Weather eye am write oar wrong,
   7  It tells me straight aweigh.
   8  Eye ran this poem threw it,
   9  Your shore real glad two no.
  10  Its vary polished in its weigh.
  11  My chequer tolled me sew.
  12  A chequer is a bless thing,
  13  It freeze yew lodes of thyme.
  14  It helps me right all stiles of righting,
  15  And aides me when eye rime.
  16  Each frays come posed up on my screen,
  17  Eye trussed too bee a joule.
  18  The chequer pours over every word,
  19  Two cheque sum spelling rule.

Word 1 appears 4 times
Word 2 appears 4 times
Number of lines: 20