如何计算字符符号在文本文件中出现的次数?

时间:2015-04-11 17:29:56

标签: c symbols

我正在尝试编写一个读取文本文件的程序,然后计算符号(用户在命令行参数中的选择)在整个文本文件中出现的次数。然后它会将它出现的次数写入输出文本文件。我的问题是它没有成功打印符号或数字,而如果我计算一个LETTER出现的次数它可以正常工作。

例如,如果input.txt包含:

Hello my name is programmer!!

然后跑步:

$ gcc myProgram.c
$ ./a.out input.txt output.txt !

注意第一个参数:input.txt,第二个参数:output.txt,第三个参数:!

这应该打印:

$ cat output.txt
The character being written was '!' and it occurred 2 times.
$

但是,它什么都不打印。

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

int main(int argc, char *argv[]){

    FILE *finp;
    FILE *output;
    char letter;

    int ex=0;

    if((finp=fopen(argv[1], "r")) == NULL){

        printf("Error Reading input!\n");

    }

    while((letter = fgetc(finp))!=EOF){

        /*From ASCII TABLE*/
        if(letter==33){
            ex++;}}

    if(output=fopen(argv[2], "w")){


        if(strcmp(argv[3],"!")==0){
            fprintf(output, "The character being written was '%s' and it occured %d
                    times", argv[3], ex);
        }


        if(output==NULL){
            printf("ERROR\n");
            exit(1);
        }

    }
    fclose(finp);
}

2 个答案:

答案 0 :(得分:3)

需要进行许多微小的更改,其中大多数都在评论中指出。这里的代码或多或少地按照我的方式修复。

源代码:lc.c

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

int main(int argc, char *argv[])
{
    FILE *finp;
    FILE *output;
    int symbol;
    int letter;
    int count = 0;

    if (argc != 4)
    {
        fprintf(stderr, "Usage: %s input output symbol\n", argv[0]);
        exit(1);
    }

    if ((finp = fopen(argv[1], "r")) == NULL)
    {
        fprintf(stderr, "Error opening file %s for input\n", argv[1]);
        exit(1);
    }

    if ((output = fopen(argv[2], "w")) == NULL)
    {
        fprintf(stderr, "Error opening file %s for output\n", argv[2]);
        exit(1);
    }

    symbol = argv[3][0];

    while ((letter = fgetc(finp)) != EOF)
    {
        if (letter == symbol)
            count++;
    }

    fprintf(output, "The character being written was '%c' and it occurred %d times\n",
            symbol, count);

    fclose(finp);
    fclose(output);
    return 0;
}

示例构建并运行

这假定存在合适的makefile以显示所显示的编译标记。它是我实际使用的标志的一个子集,但额外的标志不会对此代码产生任何额外的警告(错误)。

$ make lc
    gcc -O3 -g -std=c11 -Wall -Wextra -Werror lc.c -o lc 
$ cat input.txt
Hello my name is programmer!!
$ ./lc input.txt output.txt !
$ cat output.txt
The character being written was '!' and it occurred 2 times
$ ./lc input.txt output.txt e
$ cat output.txt
The character being written was 'e' and it occurred 3 times
$ ./lc input.txt output.txt m
$ cat output.txt
The character being written was 'm' and it occurred 4 times
$ ./lc input.txt output.txt Z
$ cat output.txt
The character being written was 'Z' and it occurred 0 times
$ 

请注意这个程序设计有多么不方便。每次运行程序时,都必须运行cat output.txt或类似的东西才能看到生成的内容。这就是程序优先于文件写入标准输出的原因,这说明了原因。是的,我可以使用:

$ ./lc input.txt /dev/stdout o
The character being written was 'o' and it occurred 2 times
$ 

但不需要这样做会更方便。

由于要计算的符号几乎是强制性的,因此它应该是第一个参数。第二个参数应该是可选的,但可以指定输入文件;如果没有提供,程序将读取标准输入。第三个参数也可以是可选的,指定输出文件,默认为标准输出:

Usage: lc symbol [input [output]]

或者,可能更有用也更常规,它应始终写入标准输出,并应在强制符号参数后读取命令行上的所有文件:

Usage: lc symbol [file ...]

如果要将输出转到文件,请使用I / O重定向。或者允许通过选项和参数指定输出:

Usage: lc [-o output] symbol [file ...]

或:

Usage: lc [-o output] -c symbol [file ...]

建议强制性参数不需要-c前缀,这是一个有说服力的论据。另一方面,您可以对代码进行概括,以便在未指定-c symbol的情况下,它将对文件中的所有符号进行计数,并对打印进行概括,以便将所有字符打印出来 - 零计数,甚至是所有计数。您也可以允许-c symbol重复,或在-c之后跟踪字符串中的所有字符。有很多方法可以有效地改变这个程序。

答案 1 :(得分:2)

编译器为发布的代码提出了一些错误和一些警告。

以下是更正错误/警告的版本:

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

int main(int argc, char *argv[])
{
    FILE *finp   = NULL;
    FILE *output = NULL;
    int   letter; // character to be found

    int ex=0; // character occurrence counter

    if( 4 != argc )
    { // then wrong number of parameters.
        printf( "usage: %s <inFileName> <outFileName> <searchChar>", argv[0] );
        exit( EXIT_FAILURE );
    }

    // implied else, right number of parameters

    if( NULL == (finp=fopen(argv[1], "r") ) )
    {
        perror( "fopen for the input file failed" );
        exit( EXIT_FAILURE );
    }

    // implied else, fopen successful

    if( NULL == (output=fopen(argv[2], "w") ) )
    {
        perror( "fopen for the output file failed" );
        fclose( finp ); // cleanup
        exit( EXIT_FAILURE );
    }

    // implied else, fopen successful

    while( EOF != (letter = fgetc(finp) ) )
    {
        /*From ASCII TABLE*/
        if( letter == argv[3][0] )
        { // then desired character found
            ex++;
        } // end if
    } // end while

    fprintf(
        output,
        "The search character is '%c' and it occurred %d times\n",
        argv[3][0],
        ex);

    fclose(finp);
    fclose(output);
    return 0;
} // end function: main