C语言中按任意数量空白字符分割字符串的实现方案咨询
嘿,这个问题我之前处理类似的文本解析需求时也碰到过,给你几个实用的解决方案,还顺便修正了你原代码里的几个小问题:
处理空白分隔的用户名/密码行的几种方法
1. 修正strtok的用法(最小改动就能搞定)
你之前用strtok踩了个小坑——它不支持正则表达式的\s语法,它的分隔符参数是字符集合字符串。只要把所有空白字符(空格、制表符、换行符等)直接写进去,strtok就会自动把连续的分隔符当成一个来处理,完美适配你的场景!
另外注意你原代码里fgets的参数顺序写反了,还有fopen没检查返回值(万一文件打不开会直接崩溃),修正后的代码如下:
#include <stdio.h> #include <string.h> void parse() { FILE* open = fopen("file.txt", "r"); // 要明确指定只读模式"r" if (!open) { // 一定要检查文件是否成功打开 perror("Failed to open file"); return; } char line[101]; char* name; char* password; while (fgets(line, sizeof(line), open) != NULL) { // 参数顺序:缓冲区、大小、文件指针 // 用空白字符集合作为分隔符:空格、制表符、换行符、回车符 name = strtok(line, " \t\n\r"); if (!name) continue; // 跳过空行 password = strtok(NULL, " \t\n\r"); if (password) { // 确保密码字段存在 printf("username : %s\n", name); printf("password : %s\n", password); } } fclose(open); // 别忘了用完文件后关闭它! }
2. 用sscanf直接提取(最简洁省心的方式)
sscanf的%s格式符天生就适合这种场景——它会自动跳过前导空白,读取到下一个空白字符为止,一行代码就能搞定两个字段的提取,代码比strtok更简洁:
#include <stdio.h> void parse() { FILE* open = fopen("file.txt", "r"); if (!open) { perror("Failed to open file"); return; } char line[101]; char name[51], password[51]; // 单独分配缓冲区更安全,避免修改原字符串的问题 while (fgets(line, sizeof(line), open) != NULL) { // 用%s读取两个字段,自动跳过中间的任意空白 if (sscanf(line, "%s %s", name, password) == 2) { // 检查是否成功读取到两个字段 printf("username : %s\n", name); printf("password : %s\n", password); } } fclose(open); }
3. 用strspn/strcspn手动定位(适合需要自定义逻辑的场景)
如果以后你需要更精细的控制(比如处理特殊字符、部分字段可能为空的情况),可以用strspn和strcspn这两个函数手动定位字段的起始和结束位置,完全不依赖strtok或sscanf:
#include <stdio.h> #include <string.h> #include <ctype.h> void parse() { FILE* open = fopen("file.txt", "r"); if (!open) { perror("Failed to open file"); return; } char line[101]; while (fgets(line, sizeof(line), open) != NULL) { // 跳过行首的所有空白 char* start = line; while (isspace((unsigned char)*start)) start++; if (*start == '\0') continue; // 跳过空行 // 找到用户名的结束位置(第一个空白字符) char* name_end = start; while (!isspace((unsigned char)*name_end) && *name_end != '\0') name_end++; // 跳过用户名后的所有空白 char* pass_start = name_end; while (isspace((unsigned char)*pass_start)) pass_start++; if (*pass_start == '\0') continue; // 跳过只有用户名没有密码的行 // 找到密码的结束位置(行尾或下一个空白) char* pass_end = pass_start; while (!isspace((unsigned char)*pass_end) && *pass_end != '\0') pass_end++; // 临时添加字符串结束符,方便打印 char temp_name = *name_end; char temp_pass = *pass_end; *name_end = '\0'; *pass_end = '\0'; printf("username : %s\n", start); printf("password : %s\n", pass_start); // 恢复原字符串(如果后续还要用的话) *name_end = temp_name; *pass_end = temp_pass; } fclose(open); }
小总结
- 如果只是简单的提取需求,用
sscanf最省心,代码少还不容易出错; - 要是你习惯用
strtok,只要修正分隔符就能正常工作; - 手动定位的方法适合需要自定义解析逻辑的复杂场景。
内容的提问来源于stack exchange,提问作者cloudiebro
相关产品推荐
相关产品推荐

