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

C语言从文件读取字符串拆分失败,求代码逻辑排查

问题分析与修复

问题描述

需要拆分的输入字符串:

"CristinaRodriguezRiveraComputacion210302414RamiroSilvaPerezIndustrial217890453PatriciaDuranSanchezCivil215643525RaulColinGranadosComputacion215678342"

期望输出格式(每个字段模拟占15字节块):

Cristina Rodríguez Rivera Computación 210302414

当前代码运行后输出不符合预期,以下是原代码及修复方案:


原代码(修正转义字符后)

#include <stdio.h>
#include <errno.h>
#include <stdbool.h>
#include <ctype.h>
#include <string.h>

typedef struct{
   char name[15];
   char father[15];
   char mother[15];
   char degree[15];
   char id[15];
}Student;

Student al;

int main(){
    FILE*  ent = fopen("DatosEntrada.txt","r");
    FILE*  sal = fopen("longitud.txt","a");

    if(ent != NULL){
        char name[15];
        char father[15];
        char mother[15];
        char degree[15];
        char id[15];

        fseek(ent, 0, SEEK_END);
        int longarch = ftell(ent);
        rewind(ent);

        char dinamic[longarch];
        fscanf(ent,"%s",&dinamic);

        int longitud =  strlen(dinamic);

        int contador=0,iterador=0;
        for(int i=0;i<longarch;i++){
            if( isupper(dinamic[i]) ){
                    if( islower(dinamic[i-1])  && islower(dinamic[i+1])  ){
                        iterator=0;
                        counter++;
                    }

                    if(counter== 0){
                        iterator=0;
                        name[iterator] = dinamic[i];
                        iterator++;
                    }else if(counter== 1){
                        father[iterator] = dinamic[i];
                        iterator++;
                    }else if(counter== 2){
                        mother[iterator] = dinamic[i];
                        iterator++;
                    }else if(counter== 3){
                        degree[iterator] = dinamic[i];
                        iterator++;
                    }
            }else if( islower(dinamic[i])  ){
                    if(counter== 0){
                        name[iterator] = dinamic[i];
                        iterator++;
                    }else if(counter== 1){
                        father[iterator] = dinamic[i];
                        iterator++;
                    }else if(counter== 2){
                        mother[iterator] = dinamic[i];
                        iterator++;
                    }else if(counter== 3){
                        degree[iterator] = dinamic[i];
                        iterator++;
                    }
            }else if( isdigit(dinamic[i])  ){
                    if( islower(dinamic[i-1]) && isdigit(dinamic[i+1]) ){
                        iterator=0;
                        counter++;
                    }else if( isupper(dinamic[i+1]) && isdigit(dinamic[i-1]) ){
                        id[iterator] = dinamic[i];
                        counter=0;
                        printf("(%s,%s,%s,%s,%s)\n",name,father,mother,degree,id);
                        strcpy(al.name,name);
                        strcpy(al.father,father);
                        strcpy(al.mother,mother);
                        strcpy(al.degree,degree);
                        strcpy(al.id,id);
                        fwrite(&al,sizeof(Student), 1, sal);
                    }
                    if(counter== 4){
                        id[iterator] = dinamic[i];
                        iterator++;
                    }
            }
        }
        fclose(ent);
        fclose(sal);
    }else{
       fprintf(stdout, "ERROR: %s", strerror(errno));
    }
}

修复后代码

#include <stdio.h>
#include <errno.h>
#include <stdbool.h>
#include <ctype.h>
#include <string.h>

typedef struct{
   char name[15];
   char father[15];
   char mother[15];
   char degree[15];
   char id[15];
}Student;

Student al;

int main(){
    FILE*  ent = fopen("DatosEntrada.txt","r");
    FILE*  sal = fopen("longitud.txt","a");

    if(ent != NULL){
        char name[15] = {0};
        char father[15] = {0};
        char mother[15] = {0};
        char degree[15] = {0};
        char id[15] = {0};

        fseek(ent, 0, SEEK_END);
        int longarch = ftell(ent);
        rewind(ent);

        char dinamic[longarch];
        fscanf(ent,"%s",dinamic); // 修正:数组名无需取地址

        int longitud = strlen(dinamic);
        int contador=0, iterador=0;

        for(int i=0; i<longitud; i++){ // 修正:用字符串长度循环,避免处理无效字符
            if(isupper(dinamic[i])){
                // 处理字段切换:仅当当前大写字母前后都是小写时,判定为新字段开头
                if(i > 0 && i < longitud-1 && islower(dinamic[i-1]) && islower(dinamic[i+1])){
                    iterador = 0;
                    contador++;
                }

                // 写入字符时限制长度,避免数组溢出
                if(contador == 0 && iterador < 14){
                    name[iterador++] = dinamic[i];
                }else if(contador == 1 && iterador <14){
                    father[iterador++] = dinamic[i];
                }else if(contador == 2 && iterador <14){
                    mother[iterador++] = dinamic[i];
                }else if(contador == 3 && iterador <14){
                    degree[iterador++] = dinamic[i];
                }
            }
            else if(islower(dinamic[i])){
                if(contador == 0 && iterador <14){
                    name[iterador++] = dinamic[i];
                }else if(contador == 1 && iterador <14){
                    father[iterador++] = dinamic[i];
                }else if(contador == 2 && iterador <14){
                    mother[iterador++] = dinamic[i];
                }else if(contador == 3 && iterador <14){
                    degree[iterador++] = dinamic[i];
                }
            }
            else if(isdigit(dinamic[i])){
                // 切换到ID字段:前一个字符是小写字母
                if(i >0 && islower(dinamic[i-1])){
                    iterador = 0;
                    contador++;
                }

                // 写入ID字符
                if(contador ==4 && iterador <14){
                    id[iterador++] = dinamic[i];
                }

                // 判定学生数据结束:下一个字符是大写字母(下一个学生开头)
                if(i < longitud-1 && isupper(dinamic[i+1])){
                    // 添加字符串终止符,避免乱码
                    name[14] = '\0';
                    father[14] = '\0';
                    mother[14] = '\0';
                    degree[14] = '\0';
                    id[iterador] = '\0';

                    // 输出预期格式
                    printf("%s %s %s %s %s\n", name, father, mother, degree, id);

                    // 安全复制到结构体,避免溢出
                    strncpy(al.name, name, 14);
                    al.name[14] = '\0';
                    strncpy(al.father, father,14);
                    al.father[14] = '\0';
                    strncpy(al.mother, mother,14);
                    al.mother[14] = '\0';
                    strncpy(al.degree, degree,14);
                    al.degree[14] = '\0';
                    strncpy(al.id, id,14);
                    al.id[14] = '\0';

                    fwrite(&al,sizeof(Student), 1, sal);

                    // 重置计数器与数组,处理下一个学生
                    contador = 0;
                    iterador =0;
                    memset(name,0,sizeof(name));
                    memset(father,0,sizeof(father));
                    memset(mother,0,sizeof(mother));
                    memset(degree,0,sizeof(degree));
                    memset(id,0,sizeof(id));
                }
            }
        }

        // 处理最后一个学生(字符串末尾无大写字母的情况)
        if(contador ==4){
            id[iterador] = '\0';
            name[14] = '\0';
            father[14] = '\0';
            mother[14] = '\0';
            degree[14] = '\0';
            printf("%s %s %s %s %s\n", name, father, mother, degree, id);
            strncpy(al.name, name,14);
            al.name[14] = '\0';
            strncpy(al.father, father,14);
            al.father[14] = '\0';
            strncpy(al.mother, mother,14);
            al.mother[14] = '\0';
            strncpy(al.degree, degree,14);
            al.degree[14] = '\0';
            strncpy(al.id, id,14);
            al.id[14] = '\0';
            fwrite(&al,sizeof(Student), 1, sal);
        }

        fclose(ent);
        fclose(sal);
    }else{
       fprintf(stdout, "ERROR: %s", strerror(errno));
    }
    return 0;
}

核心修复说明

  1. 变量名统一:修正原代码中contador/counter、iterador/iterator混用的问题,避免未定义行为。
  2. 字符串终止符:所有字符数组添加\0终止符,解决打印乱码问题。
  3. 边界越界防护:访问dinamic[i-1]/dinamic[i+1]前先判断索引有效性,避免数组越界。
  4. 循环逻辑修正:使用字符串实际长度而非文件长度循环,避免处理无效空字符。
  5. 字段切换优化:简化ID字段的切换条件,修正学生数据结束的判定逻辑,确保分割准确。
  6. 溢出防护:写入字符时限制长度不超过14(留位置给终止符),使用strncpy代替strcpy避免数组溢出。
  7. 输入修正:去掉fscanf中dinamic前的&,数组名本身就是指针。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.23 15:24:07