You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

C语言结构体存储姓名后格式化打印无输出问题排查

问题描述

我编写了一个程序,从标准输入读取按换行分隔的名(firstName)和姓(lastName),存入结构体数组的字符数组中。读取存储环节看似正常,但按<lastName>, <firstName>格式打印时出现异常:使用printf("%s, %s",people[0].lastName, people[0].firstName);无任何输出;但将两个字符串分开换行打印,或用puts打印时却能正常输出。注释掉removeNewline()函数后,格式化打印恢复正常,但字符串末尾会带有换行符,无法达到预期输出格式。

完整代码如下:

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

#define MAX_STRING_LENGTH 100
#define MAX_PEOPLE 42

struct Person{
  char firstName [MAX_STRING_LENGTH];
  char lastName[MAX_STRING_LENGTH];
};

void removeNewline(char * string){
  for(int i = 0; string[i] != '\0'; i++){
    if(string[i] == '\n'){
      string[i] = '\0';
    }
  }
}

int parseData(struct Person * people){
    int peopleCounter;
    for(peopleCounter = 0; peopleCounter < MAX_PEOPLE; peopleCounter++){
        char firstName[MAX_STRING_LENGTH];
        char lastName[MAX_STRING_LENGTH];

      if(fgets(firstName,MAX_STRING_LENGTH,stdin) == NULL){
        break;
      }
      fgets(lastName,MAX_STRING_LENGTH,stdin);
        
      removeNewline(firstName);
      removeNewline(lastName);

      strcpy(people[peopleCounter].firstName,firstName);
      strcpy(people[peopleCounter].lastName,lastName);
    }
    return peopleCounter;
}

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

    struct Person people [MAX_PEOPLE];
    parseData(people);

    //PROBLEM
    printf("%s, %s",people[0].firstName, people[0].lastName);

    for(int i = 0; i < 2; i++){
        printperson(people, i);
    }
}

运行命令:./main <people.txt,people.txt示例内容:

George
Washington
Thomas
Jefferson

预期输出:

Washington, George
Jefferson, Thomas

问题原因与修复方案

1. 核心问题:removeNewline未处理Windows风格换行符

如果你的文本文件是Windows格式,每行末尾是\r\n(回车+换行),原函数只将\n替换为\0,但\r会留在字符串末尾。当printf输出时,\r会让光标跳回行首,后续的, %s会覆盖之前的输出,导致看起来没有内容。

同时原函数用循环遍历的方式效率低,改用strchr定位换行符更简洁可靠。修改后的removeNewline函数:

void removeNewline(char * string){
    char *newline = strchr(string, '\n');
    if (newline != NULL) {
        // 处理Windows风格的\r\n换行
        if (newline > string && *(newline - 1) == '\r') {
            *(newline - 1) = '\0';
        } else {
            *newline = '\0';
        }
    }
}

2. 打印参数顺序错误

预期输出是姓, 名,但原代码中printf的参数顺序写反了,改成:

printf("%s, %s\n", people[0].lastName, people[0].firstName);

加上\n保证输出换行,符合预期格式。

3. 补全缺失的printperson函数

原代码调用了未定义的printperson函数,会导致编译错误,补全该函数:

void printperson(struct Person *people, int index) {
    printf("%s, %s\n", people[index].lastName, people[index].firstName);
}

4. 完善输入读取的异常处理

读取lastName时也需检查fgets的返回值,避免文件行数为奇数时出错:

if(fgets(firstName,MAX_STRING_LENGTH,stdin) == NULL){
    break;
}
if(fgets(lastName,MAX_STRING_LENGTH,stdin) == NULL){
    break;
}

修复后的完整代码
#include <stdio.h>
#include <string.h>

#define MAX_STRING_LENGTH 100
#define MAX_PEOPLE 42

struct Person{
    char firstName[MAX_STRING_LENGTH];
    char lastName[MAX_STRING_LENGTH];
};

void removeNewline(char *string){
    char *newline = strchr(string, '\n');
    if (newline != NULL) {
        if (newline > string && *(newline - 1) == '\r') {
            *(newline - 1) = '\0';
        } else {
            *newline = '\0';
        }
    }
}

void printperson(struct Person *people, int index) {
    printf("%s, %s\n", people[index].lastName, people[index].firstName);
}

int parseData(struct Person *people){
    int peopleCounter;
    for(peopleCounter = 0; peopleCounter < MAX_PEOPLE; peopleCounter++){
        char firstName[MAX_STRING_LENGTH];
        char lastName[MAX_STRING_LENGTH];

        if(fgets(firstName, MAX_STRING_LENGTH, stdin) == NULL){
            break;
        }
        if(fgets(lastName, MAX_STRING_LENGTH, stdin) == NULL){
            break;
        }
        
        removeNewline(firstName);
        removeNewline(lastName);

        strcpy(people[peopleCounter].firstName, firstName);
        strcpy(people[peopleCounter].lastName, lastName);
    }
    return peopleCounter;
}

int main(int argc, char *argv[]){
    struct Person people[MAX_PEOPLE];
    int count = parseData(people);

    printf("%s, %s\n", people[0].lastName, people[0].firstName);

    for(int i = 0; i < count; i++){
        printperson(people, i);
    }
    return 0;
}

运行后即可得到预期输出:

Washington, George
Washington, George
Jefferson, Thomas

(注:main中的单独打印和循环打印会重复第一行,可根据需求移除其中一个)

内容的提问来源于stack exchange,提问作者startler03

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.16 21:15:47