C语言读取特定格式文本文件并拆分至type、username、password变量
问题:C语言读取「Type:Username Password」格式文本并拆分存储
需求:读取文本文件中格式为Type:Username Password的内容,将Type、Username、Password分别存入type、username、password三个独立变量中。
示例输入:
Admin:Username Password
期望输出:
Type:Admin User:Username Pw:Password
用户尝试的代码:
int ch; int i = 0; while ((ch = fgetc(fp)) != EOF) { // Check for the colon character if (ch == ':') { // We have reached the end of the type string // Move to the next variable i = 0; continue; } // Check for the space character if (ch == ' ') { // We have reached the end of the username string // Move to the next variable i = 0; continue; } // Store the character in the appropriate variable if (i < 50) { if (type[0] == 0) { type[i] = ch; } else if (username[0] == 0) { username[i] = ch; } else { password[i] = ch; } i++; } }
现有代码的问题
- 状态判断逻辑错误:用
type[0] == 0判断是否写入type的逻辑不严谨——如果输入的Type字段为空(比如:abc 123),会直接跳到username的写入分支;且一旦type写入过内容,后续无法处理多行输入的状态切换。 - 未添加字符串结束符:C语言字符串必须以
\0结尾,现有代码只写入字符未加结束符,会导致输出乱码。 - 未处理换行符:输入行末尾的换行符会被写入password变量,导致字段包含多余换行。
- 数组越界风险:判断
i < 50但未预留\0的位置,写入满50字符时无法添加结束符,依然会越界。
解决方案
方法1:使用fscanf直接按格式读取(推荐)
利用fscanf的格式匹配功能,直接按规则拆分内容,代码简洁高效:
#include <stdio.h> #include <string.h> #define MAX_LEN 50 int main() { FILE *fp = fopen("input.txt", "r"); if (!fp) { perror("Failed to open file"); return 1; } char type[MAX_LEN], username[MAX_LEN], password[MAX_LEN]; // %[^:] 读取所有非冒号字符,跳过冒号后读取用户名和密码 while (fscanf(fp, "%[^:]:%s %s", type, username, password) == 3) { printf("Type:%s\nUser:%s \nPw:%s\n", type, username, password); } fclose(fp); return 0; }
方法2:修正逐字符读取的代码(状态机方式)
如果必须逐字符读取,可引入状态变量标记当前写入的字段,同时处理结束符和换行:
#include <stdio.h> #include <string.h> #define MAX_LEN 50 int main() { FILE *fp = fopen("input.txt", "r"); if (!fp) { perror("Failed to open file"); return 1; } char type[MAX_LEN] = {0}, username[MAX_LEN] = {0}, password[MAX_LEN] = {0}; int ch; int idx = 0; int state = 0; // 0:读type,1:读username,2:读password while ((ch = fgetc(fp)) != EOF) { // 处理换行,输出当前行并重置状态 if (ch == '\n') { // 给当前字段加结束符 switch(state) { case 0: type[idx] = '\0'; break; case 1: username[idx] = '\0'; break; case 2: password[idx] = '\0'; break; } printf("Type:%s\nUser:%s \nPw:%s\n", type, username, password); // 重置状态和数组 state = 0; idx = 0; memset(type, 0, sizeof(type)); memset(username, 0, sizeof(username)); memset(password, 0, sizeof(password)); continue; } // 切换状态 if (ch == ':' && state == 0) { type[idx] = '\0'; state = 1; idx = 0; continue; } if (ch == ' ' && state == 1) { username[idx] = '\0'; state = 2; idx = 0; continue; } // 写入对应字段,预留结束符位置 if (idx < MAX_LEN - 1) { switch(state) { case 0: type[idx] = ch; break; case 1: username[idx] = ch; break; case 2: password[idx] = ch; break; } idx++; } } // 处理文件最后一行无换行的情况 switch(state) { case 0: type[idx] = '\0'; break; case 1: username[idx] = '\0'; break; case 2: password[idx] = '\0'; break; } printf("Type:%s\nUser:%s \nPw:%s\n", type, username, password); fclose(fp); return 0; }
内容的提问来源于stack exchange,提问作者Andew Tayloe
相关产品推荐
相关产品推荐

