【问题标题】:Wrong output with std::string using stoul, on integer array在整数数组上使用 stoul 的 std::string 错误输出
【发布时间】:2018-05-24 13:20:44
【问题描述】:

嗨,我在尝试将一行数字(例如:100 101 102)转换为(stoul)动态分配的无符号整数时遇到问题;预期的是,我可以在可变长度输入中逐个数字地访问数组。

#include <iostream>
#include <new>
#include <string> //Memset
int console(){
    std::string console_buffer;
    unsigned long int* integersConverted = NULL;
    unsigned int integersNumberOf = 0;
    for( ; ; ){
        std::getline(std::cin, console_buffer);
        integersConverted = console_defaultSyntaxProcessing(console_buffer, &integersNumberOf);

        std::cout << "Found the following integers from conversion: ";
        for(unsigned int debug_tmp0 = 0; debug_tmp0 < integersNumberOf; debug_tmp0++){
            std::cout << integersConverted[debug_tmp0] << " ";
            std::cout << std::endl;
        }

        delete integersConverted;
        integersConverted = NULL;
    }
    return 0;
}

unsigned long int* console_defaultSyntaxProcessing(std::string console_buffer, unsigned int* integersNumberOfUpdate){
    *integersNumberOfUpdate = 0;
    unsigned int integersNumberOf = 0;
    unsigned long int* integersFound = NULL;
    integersFound = new unsigned long int(sizeof(unsigned long int) * 1024);
    std::size_t stringPosition = 0;
    for( ; stringPosition < console_buffer.length() && integersNumberOf < 1024; ){
        integersFound[integersNumberOf] = std::stoul(console_buffer, &stringPosition, 10); //10 = Decimal
        integersNumberOf++;
    }
    *integersNumberOfUpdate = integersNumberOf;
    return integersFound;
}

如果我只输入一个数字,我会得到正确的值,但是如果我输入两个或更多数字并且所有位置都得到第一个整数,则会打印整个 1024 数组。我试图手动将函数 std::string 设置为常量,将 console_buffer.length() 归零,以便找到'\0'等;不幸的是没有工作..

UPDATE --- 主题首次发布后 5 分钟; 正如 Yashas 所回答的,问题在于 console_defaultSyntaxProcessing for 循环; stoul &stringPosition 返回读取的字符数,而不是 std::string 的位置。 使用 stoul 的另一个问题是,如果我输入 100(101,它不起作用,所以遵循固定代码但不应使用。 正如 lamandy 建议的那样,请改用 std::stringstream。

std::size_t stringPosition = 0;
std::size_t stringPositionSum = 0;
for( ; stringPosition < console_buffer.length() && integersNumberOf < 1024; ){
    try{
        integersFound[integersNumberOf] = std::stoul(&console_buffer[stringPositionSum], &stringPosition, 10);
        integersNumberOf++;
        stringPositionSum = stringPositionSum + stringPosition;
    }
    catch(std::exception& exception){
        break;
    } //This catch will be used constantly by this buggy code.

【问题讨论】:

  • 所有的指针都有点吗?然而你通过值传递 std::string。
  • 我试过通过指针传递,它也没有工作。指针: integersNumberOf_Update 是直接在 console() 上更改值,就像 stoul 对 size_t 参数所做的那样。 integersFound 必须动态分配,因为整数的数量可能非常大。 integersConverted 只是接收指向 integersFound 的指针。

标签: c++ string getline size-t


【解决方案1】:
for( ; stringPosition < console_buffer.length() && integersNumberOf < 1024; ){
        integersFound[integersNumberOf] = std::stoul(console_buffer, &stringPosition, 10); //10 = Decimal
        integersNumberOf++;
    }

没有做你想做的事。

您一次又一次地将相同的字符串传递给std::stoul。您的 std::stoul 函数每次都会读取第一个数字。当您只有一个号码时,stringPosition &lt; console_buffer.length() 会导致您的循环停止。当您有多个号码时,stringPosition 永远不会超过 console_buffer.length()

std::stoul的第二个参数不取字符串中从哪里开始读取;它为您提供处理的字符数。

对于您正在处理的任务,stringstream 是您所需要的。

#include <iostream>
#include <sstream>
#include <array>

int main ()
{
     std::istringstream console_buffer("123 345 3 5 2 3 4 5 6 7 7  232 34 332 234 55");

     std::array<unsigned long, 1024> integerArray;
     size_t count = 0;
     while(console_buffer && count < integerArray.size())
         console_buffer >> integerArray[count++];

     for(int i = 0; i < count; i++)
         std::cout<<integerArray[i] << ' ';
     return 0;
}

【讨论】:

  • 天哪!我已经尝试修复代码将近 2 个小时,所以作为您的答案,我已经使用 try-catch 修复了代码;它仍然非常不稳定,因为 stoul 确实没有做我需要的事情,我也没有将它的参数理解为我第一次使用它。主帖将使用固定代码更新,但不得在任何地方使用。
  • 您应该使用字符串流。它们的工作方式类似于 cincout。不同之处在于字符串流在字符串上工作,而您的 cincoutstdinstdout 上工作。还可以考虑将typedef 用于unsigned long
  • 附录:The recently added std::size 将消除对...的需要。你让这种赞扬毫无意义不是吗?
  • @user4581301 我不知道。谢谢。无论如何,我已经用std::array 替换了 C 样式数组。
  • std::array 是正确的方法。只有更好的解决方案可能是std::vector。不过,必须查看更多询问者的用例才能确定。
【解决方案2】:

考虑使用std::vectorstd::stringstream 来减轻您的工作负担。

std::vector<unsigned long int> StringToIntegerVector(const std::string& input)
{
    std::istringstream iss(input);
    unsigned long int temp;
    std::vector<unsigned long int> results;
    while (iss >> temp)
        results.push_back(temp);
    return results;
}

【讨论】:

  • 非常感谢示例代码!我现在会,比我笨重的代码小得多。
猜你喜欢
  • 1970-01-01
  • 2013-07-30
  • 1970-01-01
  • 2010-09-15
  • 2018-05-13
  • 1970-01-01
  • 1970-01-01
  • 2021-07-12
  • 1970-01-01
相关资源
最近更新 更多