在 printf 中的引号(格式)之间添加逗号会改变输出吗?

Dan*_*oos 5 c linux terminal scanf line-endings

我面临着一个非常奇怪的问题,我只能在 Linux 上产生。我确实在互联网上找不到类似的东西,但如果我的搜索技巧不够好,如果这是任何问题的重复,我深表歉意。

采用下面的最小可行代码:我在仍然遇到问题的情况下尽可能地减少了代码。

#include <stdio.h>

#define MAX 10
#define MAXNAME 30

typedef struct sup{
    int rating;
    char supName[MAXNAME];
}sup;

typedef struct spec{
    char name[MAXNAME];
    float width;
    float height;
    float depth;
    char material[MAXNAME];
    sup supvisor[MAX];
}spec;

int read_Supervisors(char fileName[], spec *specread){
    int i=0;

    char buffer[MAX];
    FILE *supervisors = fopen(fileName, "r");

    while (i < MAX && fgets (buffer, sizeof(buffer), supervisors)) {

        if(sscanf(buffer, "%19s %d", specread->supvisor[i].supName, &specread->supvisor[i].rating) == 2){
            i++;}}

    fclose(supervisors);

    return i;
}

void read_Specs(char fileName[],spec *spec1){
    FILE *specs = fopen(fileName, "r");

    fscanf(specs, "%29[^\n]\n %19s\n %f\n %f\n %f", spec1->name, spec1->material,&spec1->width, &spec1->height, &spec1->depth);
    fclose(specs);
}

int main(int argc, char *argv[]) {
    spec spec1 = {.name = ""}; // Initialize .name at zero
    //Read specs file.
    read_Specs(argv[1],&spec1);

    int iteration = read_Supervisors(argv[2], &spec1), 
    selectedSuper = 1, 
    calculatedDays = 50;

    float priceOfProject = 1;

    //Print all the values.
    printf("Dear %s,"
           "\nThank you for your order.\n"
           "Your retaining wall of specifications:\n"
           "Material: %s\n"
           "width: %.2f m\n"
           "height: %.2f m\n"
           "depth: %.3f m\n"
           "Will be completed in %d days and the assigned project supervisor is %s\n"
           "The estimated price is: $%.2f\n", spec1.name, spec1.material, spec1.width,spec1.height,spec1.depth,calculatedDays, spec1.supvisor[selectedSuper].supName,priceOfProject);
    return 0;
}
Run Code Online (Sandbox Code Playgroud)

输出:

#include <stdio.h>

#define MAX 10
#define MAXNAME 30

typedef struct sup{
    int rating;
    char supName[MAXNAME];
}sup;

typedef struct spec{
    char name[MAXNAME];
    float width;
    float height;
    float depth;
    char material[MAXNAME];
    sup supvisor[MAX];
}spec;

int read_Supervisors(char fileName[], spec *specread){
    int i=0;

    char buffer[MAX];
    FILE *supervisors = fopen(fileName, "r");

    while (i < MAX && fgets (buffer, sizeof(buffer), supervisors)) {

        if(sscanf(buffer, "%19s %d", specread->supvisor[i].supName, &specread->supvisor[i].rating) == 2){
            i++;}}

    fclose(supervisors);

    return i;
}

void read_Specs(char fileName[],spec *spec1){
    FILE *specs = fopen(fileName, "r");

    fscanf(specs, "%29[^\n]\n %19s\n %f\n %f\n %f", spec1->name, spec1->material,&spec1->width, &spec1->height, &spec1->depth);
    fclose(specs);
}

int main(int argc, char *argv[]) {
    spec spec1 = {.name = ""}; // Initialize .name at zero
    //Read specs file.
    read_Specs(argv[1],&spec1);

    int iteration = read_Supervisors(argv[2], &spec1), 
    selectedSuper = 1, 
    calculatedDays = 50;

    float priceOfProject = 1;

    //Print all the values.
    printf("Dear %s,"
           "\nThank you for your order.\n"
           "Your retaining wall of specifications:\n"
           "Material: %s\n"
           "width: %.2f m\n"
           "height: %.2f m\n"
           "depth: %.3f m\n"
           "Will be completed in %d days and the assigned project supervisor is %s\n"
           "The estimated price is: $%.2f\n", spec1.name, spec1.material, spec1.width,spec1.height,spec1.depth,calculatedDays, spec1.supvisor[selectedSuper].supName,priceOfProject);
    return 0;
}
Run Code Online (Sandbox Code Playgroud)

请注意,当删除逗号时,打印输出是 ,ear 而不是 Dear Jason oliver,Dear %s,效果Dear %s非常好。我可以在 the 之前加逗号%s,但不能在 the 之后加逗号。

我尝试了很多事情,增加#defines,我尝试拆分为多个 printf,我尝试过不同版本的 C11、C23,我也尝试更新我的 linux。我要注意的是,这是 Linux 的全新安装。

以下是有关我正在使用的 linux(22.04) 环境的一些信息: Linux Linux 5.19.0-35-generic #36~22.04.1-Ubuntu SMP PREEMPT_DYNAMIC Fri Feb 17 15:17:25 UTC 2 x86_64 x86_64 x86_64 GNU/Linux

编译版本:gcc(Ubuntu 11.3.0-1ubuntu1~22.04)11.3.0

文件结构:

规格.dat 文件:

,ear Jason Oliver
Thank you for your order.
Your retaining wall of specifications:
Material: Concrete
width: 5.50 m
height: 1.00 m
depth: 0.250 m
Will be completed in 50 days and the assigned project supervisor is Sally
The estimated price is: $1.00
Run Code Online (Sandbox Code Playgroud)

Builders.dat 文件:

Jason Oliver
Concrete
5.50
1.0
0.250
Run Code Online (Sandbox Code Playgroud)

ybu*_*ill 8

您的输入文件必须使用\r\nWindows 上流行的行结尾,而不是\nUnix 使用的单行结尾。您的代码读取名称直至字符\n,因此\r成为name. 当您将名称打印到终端时,\r指示它将光标移动到行的开头(它是回车控制字符)。之后打印的下一个字符是逗号,因此它会覆盖位于同一位置的“Dear”的“D”。

您也可以将您的内容修复为从字符串中fscanf排除。请注意,在这种情况下,格式字符串中的\r以下内容是不正确的。\n一个简单的空格就可以跳过\rand\n以及其他空白字符:

fscanf(specs, "%29[^\r\n] %19s %f %f %f", spec1->name, spec1->material,&spec1->width, &spec1->height, &spec1->depth);
Run Code Online (Sandbox Code Playgroud)

或者,如果可以的话,您可以使用dos2unix适用于大多数操作系统的命令来修复输入文件:

$ dos2unix specs.dat
Run Code Online (Sandbox Code Playgroud)

  • @DanielBoos `%[^\r\n]` 如果读取单个 `'\r'` 或 `'\n'` 则停止该说明符。扫描格式的下一部分是_未读_。 (3认同)
  • 接得好。遗憾的是我们仍然被这个愚蠢的“\n”与“\r\n”问题所困扰。 (2认同)