如何修改C语言字符串分割代码以处理多组连续数据?
多组「姓名+父姓+母姓+专业+ID」字符串的C语言分割代码修改方案
问题背景
现有代码仅能正确分割单组格式为「姓名(首字母大写+后续小写)+父姓+母姓+专业+数字ID」的字符串,但无法处理多组该格式拼接的连续字符串(例如CristinaRodriguezRiveraComputacion210302414RamiroSilvaPerezIndustrial217890453...),需要对代码进行针对性修改。
核心修改点
- 让分割函数返回当前组的结束位置,支持循环处理下一组
- 修复ID字段的提取逻辑(原代码直接取到字符串末尾,多组场景下会包含下一组内容)
- 补充字符串终止符,避免内存溢出和乱码
- 添加循环逻辑,遍历处理所有分组
具体修改步骤
1. 修正complete_lowercase函数
原函数未给目标字符串添加终止符,且未处理边界越界问题,修改后:
int complete_lowercase(char dinamic[], int longdinamico, char destiny[], int ini, int max_dest_len) { if (ini >= longdinamico || !isupper(dinamic[ini])) { destiny[0] = '\0'; return ini; } int fin = ini + 1; while (fin < longdinamico && islower(dinamic[fin])) { ++fin; } // 限制复制长度,避免目标数组溢出 int copy_len = fin - ini; if (copy_len > max_dest_len - 1) { copy_len = max_dest_len - 1; } memcpy(destiny, &dinamic[ini], copy_len); destiny[copy_len] = '\0'; // 添加字符串终止符 return fin; }
- 新增
max_dest_len参数,限制复制长度防止溢出 - 添加边界检查,避免越界访问
- 给目标字符串添加
'\0',确保是合法C字符串
2. 重写separate_data函数
将原无返回值的函数改为返回当前组处理后的结束索引,同时修正ID提取逻辑:
int separate_data(char dinamic[], int longdinamico, char name[], char father[], char mother[], char degree[], char id[], int max_field_len) { int current_pos = complete_lowercase(dinamic, longdinamico, name, 0, max_field_len); current_pos = complete_lowercase(dinamic, longdinamico, father, current_pos, max_field_len); current_pos = complete_lowercase(dinamic, longdinamico, mother, current_pos, max_field_len); current_pos = complete_lowercase(dinamic, longdinamico, degree, current_pos, max_field_len); // 提取ID:从current_pos开始,直到非数字或字符串结束 int id_start = current_pos; while (current_pos < longdinamico && isdigit(dinamic[current_pos])) { ++current_pos; } int id_len = current_pos - id_start; if (id_len > max_field_len - 1) { id_len = max_field_len - 1; } memcpy(id, &dinamic[id_start], id_len); id[id_len] = '\0'; return current_pos; // 返回当前组的结束位置,作为下一组的起始 }
- 改为返回
int类型,返回当前组处理完后的索引 - 单独处理ID字段:仅提取连续数字部分,避免包含下一组的内容
- 统一使用
max_field_len限制字段长度,防止溢出
3. 修改main函数,添加循环处理逻辑
原函数仅处理一次分组,修改后循环处理所有分组:
int main(){ FILE* ent = fopen("DatosEntrada.txt","r"); FILE* sal = fopen("SalidaBytes.txt","a"); const int MAX_FIELD_LEN = 15; // 统一字段最大长度 if(ent != NULL){ char name[MAX_FIELD_LEN]; char father[MAX_FIELD_LEN]; char mother[MAX_FIELD_LEN]; char degree[MAX_FIELD_LEN]; char id[MAX_FIELD_LEN]; // 获取文件长度并读取全部内容 fseek(ent, 0, SEEK_END); int longarch = ftell(ent); rewind(ent); char dinamic[longarch+1]; fscanf(ent,"%s", dinamic); // 注意:&dinamic改为dinamic,数组名本身是指针 dinamic[longarch] = '\0'; // 确保字符串终止 int current_pos = 0; // 循环处理每一组数据,直到处理完整个字符串 while (current_pos < longarch) { // 重置字段为空格 memset(name, ' ', MAX_FIELD_LEN); memset(father, ' ', MAX_FIELD_LEN); memset(mother, ' ', MAX_FIELD_LEN); memset(degree, ' ', MAX_FIELD_LEN); memset(id, ' ', MAX_FIELD_LEN); // 处理当前组,更新current_pos到下一组起始 current_pos = separate_data(dinamic, longarch, name, father, mother, degree, id, MAX_FIELD_LEN); // 写入文件(注意:这里会保留字段的空格填充,和原逻辑一致) fwrite(name, sizeof(char), MAX_FIELD_LEN, sal); fwrite(father, sizeof(char), MAX_FIELD_LEN, sal); fwrite(mother, sizeof(char), MAX_FIELD_LEN, sal); fwrite(degree, sizeof(char), MAX_FIELD_LEN, sal); fwrite(id, sizeof(char), MAX_FIELD_LEN, sal); } printf("\n所有分组处理完成,已写入文件\n"); fclose(ent); fclose(sal); }else{ fprintf(stdout, "ERROR: %s", strerror(errno)); } return 0; }
- 添加
current_pos变量跟踪当前处理位置,循环处理所有分组 - 修正
fscanf的参数错误(原代码&dinamic是错误的,数组名直接作为指针即可) - 统一用
MAX_FIELD_LEN管理字段长度,提高可维护性 - 每次处理前重置字段为空格,保持原代码的输出格式
修改后的完整代码
#include <stdio.h> #include <errno.h> #include <ctype.h> #include <string.h> int complete_lowercase(char dinamic[], int longdinamico, char destiny[], int ini, int max_dest_len) { if (ini >= longdinamico || !isupper(dinamic[ini])) { destiny[0] = '\0'; return ini; } int fin = ini + 1; while (fin < longdinamico && islower(dinamic[fin])) { ++fin; } int copy_len = fin - ini; if (copy_len > max_dest_len - 1) { copy_len = max_dest_len - 1; } memcpy(destiny, &dinamic[ini], copy_len); destiny[copy_len] = '\0'; return fin; } int separate_data(char dinamic[], int longdinamico, char name[], char father[], char mother[], char degree[], char id[], int max_field_len) { int current_pos = complete_lowercase(dinamic, longdinamico, name, 0, max_field_len); current_pos = complete_lowercase(dinamic, longdinamico, father, current_pos, max_field_len); current_pos = complete_lowercase(dinamic, longdinamico, mother, current_pos, max_field_len); current_pos = complete_lowercase(dinamic, longdinamico, degree, current_pos, max_field_len); int id_start = current_pos; while (current_pos < longdinamico && isdigit(dinamic[current_pos])) { ++current_pos; } int id_len = current_pos - id_start; if (id_len > max_field_len - 1) { id_len = max_field_len - 1; } memcpy(id, &dinamic[id_start], id_len); id[id_len] = '\0'; return current_pos; } int main(){ FILE* ent = fopen("DatosEntrada.txt","r"); FILE* sal = fopen("SalidaBytes.txt","a"); const int MAX_FIELD_LEN = 15; if(ent != NULL){ char name[MAX_FIELD_LEN]; char father[MAX_FIELD_LEN]; char mother[MAX_FIELD_LEN]; char degree[MAX_FIELD_LEN]; char id[MAX_FIELD_LEN]; fseek(ent, 0, SEEK_END); int longarch = ftell(ent); rewind(ent); char dinamic[longarch+1]; fscanf(ent,"%s", dinamic); dinamic[longarch] = '\0'; int current_pos = 0; while (current_pos < longarch) { memset(name, ' ', MAX_FIELD_LEN); memset(father, ' ', MAX_FIELD_LEN); memset(mother, ' ', MAX_FIELD_LEN); memset(degree, ' ', MAX_FIELD_LEN); memset(id, ' ', MAX_FIELD_LEN); current_pos = separate_data(dinamic, longarch, name, father, mother, degree, id, MAX_FIELD_LEN); fwrite(name, sizeof(char), MAX_FIELD_LEN, sal); fwrite(father, sizeof(char), MAX_FIELD_LEN, sal); fwrite(mother, sizeof(char), MAX_FIELD_LEN, sal); fwrite(degree, sizeof(char), MAX_FIELD_LEN, sal); fwrite(id, sizeof(char), MAX_FIELD_LEN, sal); } printf("\n所有分组处理完成,已写入文件\n"); fclose(ent); fclose(sal); }else{ fprintf(stdout, "ERROR: %s", strerror(errno)); } return 0; }
内容的提问来源于stack exchange,提问作者SwagKiller
相关产品推荐
相关产品推荐

