【问题标题】:C++ Parse string to integer with specific classesC ++将字符串解析为具有特定类的整数
【发布时间】:2011-11-18 03:22:55
【问题描述】:

这听起来可能很愚蠢,但我只是想知道如何在 C++ 中将字符串解析为整数?

这是一个学校项目,解释表说: “仅允许使用iostreamstring 类和system() 函数;禁止使用任何其他类或函数。”

我搜索了一下,但我发现的唯一建议是使用 atoiatof 之类的类。

输入字符串在解析之前已经检查过错误,所以它总是只包含一个整数。

我不介意使用条件手动进行解析,但我认为这不是我的老师(或任何人)的首选方式。

如果您能提供帮助,非常感谢。

【问题讨论】:

  • 你可以使用Boost吗?
  • 我不认为你可以使用 stringstream?
  • 不,说明单上清楚地写着“只允许使用iostream和字符串类和system()函数;禁止使用任何其他类或函数。”
  • 好吧,atoiatof 是函数(不是类)。而且它们不是 .NET 特定的(实际上是 ANSI C)。问问你的老师吧,不过我觉得用起来没什么大不了的
  • stringstreams iostream 类。见cplusplus.com/reference/iostream/stringstream

标签: c++ string parsing integer


【解决方案1】:

那么,你可以使用system(),对吧?看看这个工程杰作:

#include <fstream>

void download_boost() {
    system("wget http://downloads.sourceforge.net/"
           "project/boost/boost/1.47.0/boost_1_47_0.tar.bz2"
           "?r=http%3A%2F%2Fwww.boost.org%2Fusers%2Fhistory%2F"
           "version_1_47_0.html&ts=1316116936&use_mirror=kent"
           " -O boost_1_47_0.tar.bz2");
}

void unpack_boost() {
    system("tar --bzip2 -xf boost_1_47_0.tar.bz2");
}

void write_program() {
    std::ofstream os("blah.cpp");
    os << "#include \"boost/lexical_cast.hpp\"\n"
          "#include <iostream>\n"
          "#include <string>\n"
          "int main() { std::string s; std::cin >> s;"
          "int i = boost::lexical_cast<int>(s);"
          "std::cout << i; }";
}

void compile_program() {
    system("g++ -Iboost_1_47_0 blah.cpp");
}

void run_program() {
    system("./a.out");
}

int main() {
    download_boost();
    unpack_boost();
    write_program();
    compile_program();
    run_program();
}

(我假设安装了一些常用工具的典型 Linux 安装。)

【讨论】:

  • 现在这就是我所说的横向思维!
  • 文字思维。用文字思考。
  • 可爱。但是,您使用了std::ofstream,这是不允许的。
  • @Rob:我认为文本模棱两可,让人怀疑它是否允许 iostream 类、&lt;iostream&gt; 标头中的类或 iostream 库中的类。不过好吧,反正就是个笑话。
  • write_program的末尾,std::cout &gt;&gt; i;不应该是std::cout &lt;&lt; i;吗?
【解决方案2】:
#include <iostream>
#include <string>

int stringToInt(const std::string &text)
{
    int number = 0;

    int powerIndex = 1;

    for (int i = text.length() - 1; i >= 0; i--)
    {
        number += powerIndex * (text.at(i) - '0');

        powerIndex *= 10;
    }

    return number;
}

std::string intToString (int number)
{
    std::string text = "";

    int numberHolder = number;

    while (numberHolder)
    {
        char digit = (numberHolder % 10) + '0';

        text = digit + text;

        numberHolder /= 10;
    }

    return text;

}
int main ()
{
    //Testing...

    int number = stringToInt("123");

    std::string text = intToString(456);

    std::cout << number << "\n" << text << "\n";

    return 0;
}

【讨论】:

  • 通常,像 int (以及 char、short、long、float、double 等)这样的原始类型按值传递,而不是按引用传递。跨度>
【解决方案3】:

stringstreams 最接近您想要做的事情,尽管一开始可能看起来有点麻烦。

例子:

#include <string>
#include <sstream>

// (...)
std::string str = "12345";
std::istringstream ss(str);
int num;
ss >> num;

作为一个函数(并经过优化):

#include <sstream>
#include <string>

int stringToInt(const std::string &str) {
    static std::istringstream ss;
    ss.clear();
    ss.str(str);

    int num;
    ss >> num;

    return num;
}

在这里,我通过应用 static 关键字重用 std::istringstream。我创建了一个非常简单的基准测试,证明这比 not 重用快大约 2 倍:http://pastebin.com/vLSmCyMF

关于线程安全的警告: 正如 рытфолд 在 cmets 中所指出的,stringToInt 的上述实现不是线程安全的。如果您想从多个线程安全地调用此函数,您应该使用thread_local 存储类说明符(从 C++11 开始可用)。

【讨论】:

  • std::ostringstream("1234") 就足够了
  • 我刚刚在我的问题中以粗体字添加了一些额外信息。
  • 谢谢,安迪。我已经修改了代码以证明stringstreams 可以重用,而ostringstreams 不能。确定我的方法是否实际上更快会很有趣。我不确定。
  • @AgentRev:从技术上讲,stringstream 既是 iostream,又是标准库中的字符串类。
  • @SoapBox:我使用 -O3 开关附加了其他结果。似乎在这种特定情况下没有区别。 (或者编译命令有什么问题?)
【解决方案4】:
std::string mystring = "12";

std::ostringstream str(mystring);
int someint;
str >> someint;

【讨论】:

  • std::ostream?可能你的意思是std::ostringstream
  • @Andy T:是的,确实如此!修复它
  • 我很确定 ostringstream 没有运算符>>(只有
  • 我刚刚在我的问题中以粗体字添加了一些额外信息。
  • 记得在使用操作符后测试str.fail()>>.
【解决方案5】:

基本上,给定一个只包含一个整数的std::string mystring: 以int result = 0; 开头。
虽然 mystring 有数字
结果乘以十
添加最大数字(字符串中的第一个)
请记住,字符“0”的值不是 0。
从字符串中删除最大的数字

所以:
如果我有字符串“1543”,结果 = 0
我们将结果乘以十:结果 = 0
我们添加第一个数字:result = 1
从字符串“543”中删除第一个数字
我们将结果乘以十:结果 = 10
我们添加第一个数字:结果 = 15
从字符串“43”中删除第一个数字
我们将结果乘以十:结果 = 150
我们添加第一个数字:result = 154
从字符串“3”中删除第一个数字
我们将结果乘以十:结果 = 1540
我们添加第一个数字:result = 1543
从字符串“”中删除第一个数字
字符串为空,所以我们完成了

我写了代码,但后来想起这是一个家庭作业问题。

【讨论】:

  • 这是假设字符串流是不允许的
猜你喜欢
  • 2012-06-27
  • 2010-10-03
  • 2010-10-16
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-04-11
  • 1970-01-01
相关资源
最近更新 更多