如何在C语言中连接字符数组

3

我有一个文本文件,其中记录了频道的名称,格式如下:

General
Private
Programming
Calculus

我要做的是,如果用户在控制台中键入“/channels”,则程序应该以以下格式打印所有频道:

Channels are : General, Private, Programming, Calculus

我的问题是以逗号分隔的格式打印这些频道。目前我可以打印频道,但它们按照文本文件中的格式打印(每行一个频道名称)。如果有人能够解释一下最佳实现方法,我将不胜感激。以下是我目前用于打印频道的代码:

void get_channels() {
    char tmp[50];
    FILE *f;
    f = fopen("../1part/channels.txt", "r");
    if (f == NULL) { perror("Mistake reading: "); exit(1); } ;
    while (fgets(tmp, sizeof(tmp), f)) {
        printf("%s", tmp);
    }

    fclose(f);
}
2个回答

3

你需要从由fgets()读取的行中去除末尾的换行符。

void get_channels(void) {
    char tmp[50];
    FILE *f;
    const char *separator = "";

    f = fopen("../1part/channels.txt", "r");
    if (f == NULL) {
        perror("Mistake reading: ");
        exit(1);
    }
    printf("Channels are: ");
    while (fgets(tmp, sizeof(tmp), f)) {
        /* strip the newline character if present */
        tmp[strcspn(tmp, "\n")] = '\0';
        printf("%s%s", separator, tmp);
        separator = ", ";
    }
    printf("\n");

    fclose(f);
} 

注意:

  • 如果文件末尾没有换行符,则删除该行的最后一个字符会无法正常工作。
  • 如果文件中的一行超过49个字符,tmp也不会以换行符结束。删除最后一个字符也是错误的,但上面的代码仍然处理不当此情况,因为这样的一行将被分成2个条目。扩大缓冲区是一个简单的解决方法。
  • separator字符串在每个条目之前输出,将其初始化为空字符串,并在每个条目之后更改为", "是生成连接列表而不进行额外测试的简单方法。

对于这种情况下的 separator,我们避免了每个项目的测试,但是进行了赋值操作,无论如何都更好吗? - aurox
赋值通常比测试便宜得多,因为它不会引起分支。不同的处理器行为不同,只有仔细的基准测试才能证明对于给定的处理器和目标环境组合,哪种方法更有效。 - chqrlie

1
我的问题是以逗号分隔的方式打印这些频道。你可能需要从 fgets 中删除 \n - 这样你就可以在一行中 printf 几个项了。
while (fgets(tmp, sizeof(tmp), f))
{
    tmp[strlen(tmp) - 1] = '\0'; // remove \n
    printf("%s, ", tmp);
}

是的,我知道如何去掉换行符,但我的问题是在之后插入逗号。 - GamerGirl
这将在末尾留下一个多余的逗号。 - vgru
是的,我知道我可以用字符“,”替换回车符,而不是删除它,但就像你说的那样,它总是在末尾留下一个逗号。 - GamerGirl

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接