【问题标题】:C - Print Specific Line From Text FileC - 从文本文件中打印特定行
【发布时间】:2015-05-26 05:59:50
【问题描述】:

我是编程新手,所以请善待。

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

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

#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 函数,我还没有完全完成这个程序(仍然需要将输入的单词转换为小写)。

【问题讨论】:

  • 你确定要for(int x = lineCount; x &lt;= lineCount; x++)吗?
  • 您需要逐行扫描您的文件。复制第一行。然后显示字数,最后转储重复的行。
  • gets() 不好,使用fgets() slways。 :-)
  • @Ôrel 你能详细解释一下吗? SouravGhosh 我确实使用fgets() 来检索行,然后我使用gets 来获取与文件无关的字符串。谢谢大家的帮助
  • 忽略所有其他问题,当您循环计算行数时,您会消耗文件的所有字符。那么当你fgets(line, 500, infile);你已经在文件的末尾了。

标签: c file search


【解决方案1】:

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

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

【讨论】:

  • 非常感谢您花时间回答我的问题。这正是我需要的,非常感谢! :)
  • 如果你不介意的话,只是一个简单的问题:你为什么使用#define WORD_LEN_MAX 100 然后arrayName[WORD_LEN_MAX 100] 而不是arrayName[100]?只是好奇,因为我从来没有被教过这个。与仅写入数组的最大大小相比,定义最大大小有什么好处吗?再次感谢。
  • 有了这个解决方案,如果你想改变大小,你只需要更新一行,它会添加一些信息,它是 100 还是 500
【解决方案2】:

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

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

当您需要比较单词并对匹配的数量求和时,只需这样做...比较,如果它们匹配,则增加总和。不需要其他任何东西。

至于lineCount 如果您使用面向行的 输入,这很简单,只需为读取的每一行增加计数器即可。

但是如何让单词进行测试呢? strtok(或strsep)是提供的工具。只需阅读一行并对其进行标记化。然后只需比较和递增。

我整理了一个简短的例子。 (大部分代码只是从输入末尾剥离newline)。很简单,读取一行,标记,比较和增加匹配,增加行数。完成:

#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

【讨论】:

  • 感谢您帮助我,非常感谢您抽出宝贵的时间来做这件事。我从你的帖子中学到了很多,非常有帮助!如果可以的话,我会投票(缺乏足够的声誉)。
  • 没问题,很乐意提供帮助。有很多方法可以解决 C 中的大多数问题。这可能是标准的做法,但你解决它的方式绝对没有错。祝你的代码好运。
猜你喜欢
  • 2018-04-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-03-28
  • 1970-01-01
相关资源
最近更新 更多