为什么C++没有用C++元素/样式重新实现C标准函数?

Jic*_*hao 9 c c++ stl

有关具体示例,请考虑atoi(const std::string &).这非常令人沮丧,因为我们作为程序员需要使用它.

  1. 更一般的问题是为什么C++标准库没有用C++字符串,C++向量或其他C++标准元素重新实现标准C库而不是保留旧的C标准库并迫使我们使用旧的char *接口?

    它耗时并且在这两个接口之间转换数据类型的代码并不容易优雅.

  2. 这是为了兼容的原因,考虑到比现在有更多的遗留C代码,保留这些C标准接口会使从C代码到C++的转换更容易吗?

  3. 另外,我听说过许多其他可用于C++的库对STL进行了大量的增强和扩展.那么库是否支持这些功能呢?

PS:考虑到第一个具体问题的更多答案,我编辑了很多来澄清问题,以概述我更加好奇的问题.

jal*_*alf 14

另一个更普遍的问题是为什么STL不重新实现所有标准C库

因为旧的C库可以解决问题.如果C++标准库能够比旧版本更好地执行它,则它只重新实现现有功能.对于C库的某些部分来说,编写新的C++实现的好处并不足以证明额外的标准化工作是正确的.

至于atoi等等,在类中的C++标准库中有这些的新版本std::stringstream.

要从类型T转换为类型U:

T in;
U out;
std::stringstream sstr(in);
sstr >> out;
Run Code Online (Sandbox Code Playgroud)

与IOStream库的其余部分一样,它并不完美,它非常冗长,速度非常慢,等等,但它确实有效,而且通常它足够好.它可以处理所有大小的整数,浮点值,C和C++字符串以及定义运算符<<的任何其他对象.

编辑:此外,我听说许多其他可用于C++的库对STL进行了大量的增强和扩展.那么库是否支持这些功能?

Boost有一个boost::lexical_cast包装std::stringstream.使用该功能,您可以将上面的内容写成:

U out = boost::lexical_cast<U>(in);
Run Code Online (Sandbox Code Playgroud)

  • 我一直觉得没有很好的C++方法将字符串转换为整数.Streams带有很多机器,实例化一个流对象很慢.在我看来,一个好的全球功能会更好.提升词法强制转换在语法上很好,但每次调用它时都会实例化一个新的stringstream对象. (7认同)

Joh*_*itb 7

即使在C语言中,使用atoi对于转换用户输入也不是一件好事.它根本不提供错误检查.提供它的C++版本并不是那么有用 - 考虑到它不会抛出任何东西,你可以传递.c_str()给它并使用它.

相反,你应该使用strtolC代码,它确实进行错误检查.在C++ 03中,你可以使用stringstreams来做同样的事情,但是它们的使用容易出错:你究竟需要检查什么?.bad(),.fail().eof()?你怎么吃剩余的空白?格式化标志怎么样?这样的问题不应该打扰普通用户,只想转换他的字符串.boost::lexical_cast确实做得很好,但顺便说一下,C++ 0x添加了实用程序函数,以便通过C++包装器来实现快速安全的转换,如果转换失败则可以抛出:

int stoi(const string& str, size_t *idx = 0, int base = 10);
long stol(const string& str, size_t *idx = 0, int base = 10);
unsigned long stoul(const string& str, size_t *idx = 0, int base = 10);
long long stoll(const string& str, size_t *idx = 0, int base = 10);
unsigned long long stoull(const string& str, size_t *idx = 0, int base = 10);
Run Code Online (Sandbox Code Playgroud)

效果:在第一个两个函数调用strtol(str.c_str(), ptr, base),而最后三个函数调用strtoul(str.c_str(), ptr, base),strtoll(str.c_str(), ptr, base)strtoull(str.c_str(), ptr, base)分别.每个函数返回转换后的结果(如果有).该参数ptr指定一个指向函数内部对象的指针,该对象用于确定要存储的内容*idx.如果函数没有抛出异常idx != 0,则函数存储在*idxstr的第一个未转换元素的索引中.

返回:转换后的结果.

抛出:invalid_argument如果strtol,strtoul,strtoll,或者strtoull没有转换可以进行报告.out_of_range如果转换后的值超出返回类型的可表示值范围,则抛出此异常.

  • @UncleBens,你能详细说明吗?`atoi`的参数类型为`const char*`,并不修改指向存储的内容. (3认同)

Dou*_* T. 5

没有好办法知道atoi是否失败.它总是返回一个整数.该整数是有效转换吗?或者是0或-1或其他表示错误的?是的,它可能会抛出异常,但这会改变原始合同,并且您必须更新所有代码以捕获异常(这是OP所抱怨的).

如果翻译太耗费时间,请编写自己的atoi:

int atoi(const std::string& str)
{
    std::istringstream stream(str);
    int ret = 0;
    stream >> ret;
    return ret;
}
Run Code Online (Sandbox Code Playgroud)