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

C语言读取不含换行符行的方法及fgets分词变体相关问询

fgets 去换行与按行读取token相关问题解答

核心问题解答

  • 标准C库没有原生提供自动去除末尾换行符的fgets变体,常规的低成本实现方案是调用fgets读取到字符串后,手动判断末尾是否为\n,如果是就替换为\0即可。如果需要封装成独立函数,你实现的fgetsnn逻辑是可行的。
  • 标准库也没有自带直接读取一行内所有token的fgets版本,你可以先读取到不带换行的整行字符串后,搭配strtok/strtok_r系列函数拆分token即可满足需求。

性能问题说明

你观察到自己实现的逐字符读取版本比原生fgets慢10%~20%是正常现象。原生fgets内部使用块读取机制批量填充文件缓冲区,不需要每次都调用fgetc触发单次字符读取的逻辑开销,性能自然更高。
你提到的switch分支顺序影响性能的判断是对的,出现概率最高的普通字符分支排在最后会增加多余的判断开销,你后续调整的把普通字符用if优先判断的优化思路是合理的,能够减少分支预测失败的概率,提升运行效率。
至于你尝试一次性读取整个文件没有看到性能提升,这是因为现代操作系统默认就会对文件做页缓存,读取文件时内核已经提前把文件内容缓存到内存中了,用户态自己实现全量读取的增益会被系统缓存抵消。如果是机械硬盘的场景,大部分时候性能瓶颈都在硬件IO上,用户态逻辑优化带来的性能提升不会特别明显。

你提到的修改ASCII码顺序提升拆分速度的思路,在通用场景下不具备可操作性,因为ASCII码是标准定义的,无法随意修改,如果要提升token拆分速度,可以在整行读取到内存后,再一次性遍历拆分,避免IO和拆分逻辑耦合,能获得更好的性能。

参考实现示例

逐字符读取的switch版本

// Read characters from file and exclude terminating newline
// Input argument 'size' must be integer larger than one
char *fgetsnn(char *s0, int size, FILE *fp) {
  size--;
  char c;
  char *s=s0;
  char *se=s0+size;
  while (s<se) {
    c=fgetc(fp);
    switch (c) {
      case EOF:
        *s='\0';
        if (ferror(fp)!=0) {
          return(NULL);
        };
        if (s==s0) {
          return(NULL);
        } else {
          return(s0);
        };
      case '\n':
        *s='\0';
        return(s0);
      case '\0':
        *s='\0';
        return(NULL);
      default:
        *s=c;
        s++;
    };
  };
  *s='\0';
  return(s0);
};

优化分支判断的if+switch版本

// Read characters from file and exclude terminating newline
// Input argument 'size' must be integer larger than one
char *fgetsnn(char *s0, int size, FILE *fp) {
  size--;
  char c;
  char *s=s0;
  char *se=s0+size;
  while (s<se) {
    c=fgetc(fp);
    if (c>'\n') {
      *s=c;
      s++;
    } else {
      switch (c) {
        case '\n':
          *s='\0';
          return(s0);
        case EOF:
          *s='\0';
          if (ferror(fp)!=0) {
            return(NULL);
          };
          if (s==s0) {
            return(NULL);
          } else {
            return(s0);
          };
        case '\0':
          *s='\0';
          return(NULL);
        default:
         *s=c;
        s++;
      };
    };
  };
  *s='\0';
  return(s0);
};

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.01 02:45:00