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

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.27 09:21:03