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

Mac环境下C++ cin读取特定首字符单词时出现首字符截断错误

Mac系统下cin读取特定首字母字符串截断问题

问题现象

我在学习《Accelerated C++》、编译测试第4章的成绩统计程序时,发现cin无法正确读取以特定字符开头的姓名,运行示例如下:

$ echo "zach 1 1 1 fred 2 2 2 albert 3 3 3 james 4 4 4 adam 5 5 5" | ./main 
james 4
lbert 3
m     5
red   2
zach  1

从输出可以看到,以a、f这类字符开头的姓名会被误读,字符串开头至少被截断1个字符。

我试过复制网上公开的全章节习题参考答案代码编译运行,仍然存在相同问题。控制台打印结果显示,姓名在读取阶段就已经出现截断,完全无法定位问题产生原因。

这个问题仅在Mac系统下出现:同一份代码在Windows设备上编译运行可以得到正确输出,在另一台Mac设备上运行则会复现相同错误。

最小复现代码

以下是遵循书中代码规范编写的最小可复现示例(MRE),运行后会表现出相同异常:

#include <iostream>
#include <vector>

using std::cin;
using std::cout;
using std::endl;
using std::istream;
using std::string;
using std::vector;

double sum_vec(vector<double> &vec)
{
    double total = 0;
    for (vector<double>::size_type i = 0; i < vec.size(); i++)
    {
        total += vec[i];
    }
    return total;
}

istream &read_nums(istream &in, vector<double> &vec)
{
    if (in)
    {
        vec.clear();

        double x;
        while (in >> x)
            vec.push_back(x);

        in.clear();
    }
    return in;
}

istream &read(istream &in)
{
    string s;
    in >> s;

    vector<double> vec;

    read_nums(in, vec);

    double total = sum_vec(vec);

    cout << s << " " << total << endl;

    return in;
}

int main()
{
    while (read(cin))
    {
    }
}

将上述代码编译为test可执行文件后,运行结果如下:

$ echo "albert 1 bruce 2 chris 3 dan 4 edward 5 fanny 6" | ./test
albert 1
ruce 2
hris 3
4 0
ward 5
y 6
 0

使用的编译命令为:

g++ -o test test.cpp

执行g++ --version查看编译器版本,输出如下:

Configured with: --prefix=/Library/Developer/CommandLineTools/usr --with-gxx-include-dir=/Library/Developer/CommandLineTools/SDKs/MacOSX10.15.sdk/usr/include/c++/4.2.1
Apple clang version 12.0.0 (clang-1200.0.32.29)
Target: x86_64-apple-darwin19.6.0
Thread model: posix
InstalledDir: /Library/Developer/CommandLineTools/usr/bin

问题根因

这是Mac系统自带老旧标准库的已知bug:

  • 命令里调用的g++实际是Apple clang的软链接,默认会链接苹果从GCC 4.2.1时代遗留的老旧libstdc++库。这个库的流读取逻辑存在缺陷:当流从读取数字的状态切换到读取字符串时,数字解析失败后的字符回退逻辑出错,会吞掉后续字符串的首字节。如果被吞掉的首字节是a、b、c、d、e、f这类十六进制合法字符,或者x、p、+、-、.这类浮点数解析的合法字符,就会触发你看到的截断现象。
  • Windows下的MSVC标准库、Linux下的新版libstdc++/libc++都早已修复这个问题,所以不会复现。

修复方案

任选一种即可解决:

  • 编译时指定链接苹果维护的新版libc++库,在编译命令中添加-stdlib=libc++参数,完整命令参考:g++ -std=c++11 -stdlib=libc++ -o test test.cpp
  • 不要使用系统自带的老旧编译工具链,通过Homebrew安装最新版gcc或clang,用安装后的新版本编译代码即可。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.30 16:15:33