C:组合 `sscanf` 说明符最多读取多个字符

C: Combining `sscanf` specifiers to read upto a number of characters

我需要读取文本文件中表示电影放映的字符串行并对其进行格式化。我需要用sscanf扫描fgets保存的字符串。我的问题是如何使 sscanf 仅读取最多 x 个字符,同时还使用 [^] 说明符。电影标题长度的最大长度为 44。我知道 C 有 %0.*s,但我需要将它与 [^] 结合使用。我试过 %0.44[^,] 但无济于事。我的代码如下。我已经评论了我认为的解决方案。

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

int main(void) {
    const int MAX_TITLE_CHARS = 44;  // Maximum length of movie titles
    const int LINE_LIMIT = 100;   // Maximum length of each line in the text file
    char line[LINE_LIMIT];
    char inputFileName[25];


    FILE *file;
    file = fopen("D:\movies.csv", "r");

    char currentLine[LINE_LIMIT];
    char movieTitle[MAX_TITLE_CHARS];
    char movieTime[5];
    char movieRating[5];

    fgets(currentLine, LINE_LIMIT, file);
    while(!feof(file)){
        
    //  sscanf(currentLine, "%[^,],%0.44[^,],%[^,]", movieTime, movieTitle, movieRating);
        sscanf(currentLine, "%[^,],%[^,],%[^,]", movieTime, movieTitle, movieRating);

        printf("%-44s |\n", movieTitle);
        fgets(currentLine, LINE_LIMIT, file);
    }


    return 0;
}

这将打印出以下内容

Wonders of the World                         |
Wonders of the World                         |
Journey to Space                             |
Buffalo Bill And The Indians or Sitting Bull's History Lesson |
Buffalo Bill And The Indians or Sitting Bull's History Lesson |
Buffalo Bill And The Indians or Sitting Bull's History Lesson |
Adventure of Lewis and Clark                 |
Adventure of Lewis and Clark                 |
Halloween                                    |

我需要它

Wonders of the World                         |
Wonders of the World                         |
Journey to Space                             |
Buffalo Bill And The Indians or Sitting Bull |
Buffalo Bill And The Indians or Sitting Bull |
Buffalo Bill And The Indians or Sitting Bull |
Adventure of Lewis and Clark                 |
Adventure of Lewis and Clark                 |
Halloween                                    |
sscanf(currentLine, "%[^,],%43[^,],%[^,]", movieTime, movieTitle, movieRating);

其中 43 是要读取的字符数,剩下一个用于空终止符。我假设编译器对 0. 抱怨零宽度和未知转换类型不满意。

I know C has %0.*s

不,不是。对于sscanf,限制接受的字符数的方法是在%之后以十进制数字的形式给出宽度,没有0.,如"%3s"。它必须是一个实际的数字;它不能像 printf 中那样是 *,它指定数字作为参数传递。

要将其与 [ 转换说明符一起使用,您可以使用 "%44[^,]".

如果最大移动标题长度为 44 个字符,则将它们作为字符串保存的数组应声明为 char movieTitle[MAX_TITLE_CHARS+1]; 以允许终止空字符。

如果要根据符号 MAX_TITLE_CHARS 参数化 sscanf 字符串,以便它在值更改时进行调整,您可以通过将 MAX_TITLE_CHARS 定义为宏而不是 const int object:

#define MAX_TITLE_CHARS 44

并定义宏以将参数转换为字符串:

//  Two macros are needed due to the order of operations in macro replacement.
#define ExpandAndStringize(x)   #x
#define Stringize(x)            ExpandAndStringize(x)

并使用它们:

sscanf(currentline,"%[^,],%" Stringize(MAX_TITLE_CHARS) "[^,],%[^,]", movieTime, movieTitle, movieRating);