【问题标题】:How to count multiple characters from a file in C language using POSIX functions?如何使用 POSIX 函数计算 C 语言文件中的多个字符?
【发布时间】:2020-09-10 14:32:32
【问题描述】:

我正在尝试使用标准 POSIX 函数编写一个接收文件和字符串的程序,程序计算字符串包含的文件中的所有字符。

例如,如果用户写:

count.exe x.txt abcd

程序计算文件x.txt中每个字符的个数:a,b,c,d

示例消息:

Number of 'a' characters in 'x.txt' file is: 4
Number of 'b' characters in 'x.txt' file is: 9
Number of 'c' characters in 'x.txt' file is: 7
Number of 'd' characters in 'x.txt' file is: 0

到目前为止我得到的代码:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <errno.h>

#define BUFSIZE     1024


void exit_sys(const char* msg)
{
    perror(msg);
    exit(EXIT_FAILURE);
}

void exit_fail(const char* msg)
{
    fprintf(stderr, "%s\n", msg);
    exit(EXIT_FAILURE);
}

int get_count(char* p, size_t size, char c)
{
    int count = 0;
    size_t i;

    for (i = 0; i < size; ++i)
        if (p[i] == c)
            ++count;

    return count;
}


void run_count_characters_application(int argc, char** argv)
{
    int fd;
    char c;
    char buf[BUFSIZE];
    int n;
    int count;

    if (argc != 3)
        exit_fail("usage: ./mycounter file character");

    if (strlen(argv[2]) < 0)
        exit_fail("You have to give at least one character");

    c = argv[2][0];

    if ((fd = open(argv[1], O_RDONLY)) < 0)
        exit_sys("open");

    count = 0;


    while ((n = read(fd, buf, BUFSIZE)) > 0)
        count += get_count(buf, n, c);

    if (n < 0)
        exit_sys("read");


    printf("Count:%d\n", count);

    close(fd);
}

int main(int argc, char** argv)
{
    run_count_characters_application(argc, argv);

    return 0;
}

到目前为止我在这段代码中得到的问题是它只计算一个字符(只计算第一个字符),我想知道如何让它读取并计算我在命令中写入的其他字符,谢谢你提前:)

【问题讨论】:

  • 你正在做c = argv[2][0];,它只传递c的ASCII值,而不是其余的字符
  • 你必须保留几个计数器,一个用于参数字符串中的每个字符。您可以将它们存储在unsigned int counter[UCHAR_MAX + 1] 中,然后只更新和打印您感兴趣的那些(例如counter['a']++)。不过,这仅适用于 ascii 字符...
  • @Inian 我该如何解决这个问题?
  • @MarcoLucidi 你能举例解释一下吗,因为我非常了解 C 语言,但我并不完全理解如何去做。

标签: c posix counting


【解决方案1】:

因为您要求在 cmets 中提供示例:

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

void die(const char *reason)
{
        fprintf(stderr, "%s\n", reason);
        exit(EXIT_FAILURE);
}

int main(int argc, char **argv)
{
        if (argc != 3)
                die("usage: ./count file characters");

        FILE *f = fopen(argv[1], "r");
        if (f == NULL)
                die("unable to open file");

        unsigned int counter[UCHAR_MAX + 1] = { 0 };
        int c;
        while ((c = fgetc(f)) != EOF)
                counter[c]++;
        fclose(f);

        size_t len = strlen(argv[2]);
        for (unsigned int i = 0; i < len; i++) {
                char c = argv[2][i];
                unsigned int count = counter[c];
                printf("Number of '%c' characters in '%s' file is: %u\n", c, argv[1], count);
        }
}

$ cc count.c -o count
$ echo "bbaaafff" > test.txt
$ ./count test.txt afm
Number of 'a' characters in 'test.txt' file is: 3
Number of 'f' characters in 'test.txt' file is: 3
Number of 'm' characters in 'test.txt' file is: 0
$

函数fgetc()

在文件结尾或错误时,将读取为无符号字符转换为 int 或 EOF 的字符返回。

unsigned char 可以存储 UCHAR_MAX + 1 可能的值(通常为 0 到 255),所以我创建了一个可以由这些值(counter)索引的数组来存储我们的计数。将其视为来自其他语言的“映射”,将字符映射到其计数。

然后在最后,我循环输入字符串中的字符并打印它们的计数。

正如 cmets 中已经提到的,这仅适用于 ASCII 字符。

【讨论】:

  • 如何使用 open(); 而不是 fopen(); 而对于 fclose(); 可以我只使用 close();?,因为我试图了解这些和其他的有什么区别,例如 fread(); > read() ;fwrite(); > write();, fgetc(); > getc();.
  • @ArjanitKotorri 长话短说:open()read()close()... 是 unix 系统调用,而 fopen()fread()fclose()... 是 c 库这些系统调用的包装器,它们为您提供缓冲 I/O 并允许您编写更多可移植代码。见:C fopen vs open
  • 我们可以说 open():, read();, close();...是 POSIX 函数,而 fopen();fread();fclose(); 是标准 C 函数,如果不是FILE *f = fopen(argv[1], "r");我做了FILE *f = open(argv[1], O_RDONLY);
  • @ArjanitKotorri fopen() 和朋友也在 POSIX 中定义,因此它们也是“POSIX 函数”(参见:fopen)。最后一条语句不起作用:open() 返回一个文件描述符(int),而fopen() 返回一个FILE
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-03-02
  • 1970-01-01
  • 2020-07-25
  • 2021-12-14
  • 1970-01-01
  • 2020-01-05
相关资源
最近更新 更多