【问题标题】:Passing string iterator to function将字符串迭代器传递给函数
【发布时间】:2014-06-26 11:11:42
【问题描述】:

我有一个函数我想在其他函数中使用,它从字符串中获取数字。 在基本函数中,我创建了std::string::iterator,我想将它传递给其他获取此数字的函数,跳过空格,然后外部函数继续搜索字符串。

当我使用迭代器时,我会执行*strPtr 之类的操作来获取价值,并使用*++strPtr 来获取价值并移动到另一个角色。当我传递指向它的指针时,我需要使用**strPtr 来获取值,但我不知道如何获取值和递增迭代器。 :(

我做了*++*strPtr,它有点工作,但是当它退出内部函数时它崩溃了。

double calculate( char* x ){
std::string formula = x;
ValueStack valueStack;
OperatorStack operatorStack;

std::string::iterator strPtr = formula.begin();

while( *strPtr == ' ' )
{
    strPtr++;
}

if( *strPtr == '-' )
{
    std::string temp;
    temp += *strPtr;

    while( *++strPtr == ' ' );

    while( ((*strPtr <= '9' ) && (*strPtr >= '0' )) || (*strPtr == '.') )
    {
        temp += *strPtr;
        while( *++strPtr == ' ' );
    }

    char** x;
    valueStack.push( strtod( temp.c_str(), x ) );
}

while( strPtr < formula.end() )
{

    if( *strPtr == ' ' )
    {
        while( *++strPtr == ' ' );
    }

    if( operatorStack.isOper( *strPtr ) )
    {   
        if( *strPtr == ')' )
        {
            evaluate( &valueStack, &operatorStack );
            strPtr++;
        }

        else if( *strPtr == '(' )
        {
            operatorStack.push( *strPtr );

            while( *++strPtr == ' ' );

            if( *strPtr == '-' )
            {
                std::string temp;
                temp += *strPtr;

                while( *++strPtr == ' ' );

                while( ((*strPtr <= '9' ) && (*strPtr >= '0' )) || (*strPtr == '.') )
                {
                    temp += *strPtr;
                    while( *++strPtr == ' ' );
                }

                char** x;
                valueStack.push( strtod( temp.c_str(), x ) );
            }
        }

        else if( operatorStack.prior( *strPtr ) <= operatorStack.prior( operatorStack.top() ) )
        {
            evaluate( &valueStack, &operatorStack );
            operatorStack.push( *strPtr++ );
        }

        else operatorStack.push( *strPtr++ );
    }

    else
    {
        std::string temp;
        temp += *strPtr;

        while( *++strPtr == ' ' );

        while( ((*strPtr <= '9' ) && (*strPtr >= '0' )) || (*strPtr == '.') )
        {
            temp += *strPtr;
            while( *++strPtr == ' ' );
        }

        char** x;
        valueStack.push( strtod( temp.c_str(), x ) );
    }
}

evaluate( &valueStack, &operatorStack );

double ret = valueStack.pop();
if( pow(ret, 2) < 0.000000001 ) return 0;
return ret; 
}

为了澄清,我想要这样的函数,并在上面使用它:

void getValue( std::string::iterator strPtr, ValueStack* valueStack )
{
std::string temp;
    temp += *strPtr;

    while( *++strPtr == ' ' );

    while( ((*strPtr <= '9' ) && (*strPtr >= '0' )) || (*strPtr == '.') )
    {
        temp += *strPtr;
        while( *++strPtr == ' ' );
    }

    char** x;
    valueStack->push( strtod( temp.c_str(), x ) );
}

【问题讨论】:

  • 发布您的代码,以便我们准确了解您在做什么
  • 我们不知道evaluate 在做什么。因此,您需要提供所有代码,或者删除对我们不知道的函数的调用并重新创建问题。
  • valueStack.push( strtod( temp.c_str(), x ) ); 正在访问一个未初始化的变量 x。这可能会使您的程序崩溃,因为 strtod 函数也会取消引用 x。阅读strtod的文档,了解如何正确使用。
  • @Matt McNabb 谢谢!它导致了一个问题:)
  • @Pershing 很好;你仍然必须检查你没有点击end()每次你在迭代器上做++。

标签: c++ string pointers iterator


【解决方案1】:

有一种更简单的方法可以遍历 string,例如:

    string str("3+5-4   -  3 / 4");

    for (string::iterator it = str.begin(); it!=str.end();++it)
    {
        if (!(*it == ' ')) {  // Skip spaces.

           if(isdigit(*it))
           {
             // Do your thing with ValueStack.
           }
           else
           {
               // Handle operators here.
               switch(*it)
               {
                   case('-'): break;
                   case('+'): break;
                   case('/'): break;
                   case('*'): break;
               }
           }
        }
    }

另一方面,我建议你看看Boost.Spirit。它将帮助您以更优雅的方式实现您正在尝试做的事情(评估数学表达式)。同样在那个链接中有一个“计算器”的例子,就像你想要的,但使用spirit。

您的算法仅支持一位数字。如果不使用一些外部库(例如Boost.Spirit ;)),很难获得支持的多位数字。

【讨论】:

  • 谢谢。它的目的是计算更复杂的方程,包括负数、浮点数和括号。它以这种形式工作,但我想调用一个函数三到四次,而不是多次编写很长的代码。
  • 那么,如果它工作,evaluate 函数有什么问题?为什么不使用它?
  • 它有效。也许我没有说清楚。我想关闭其他函数中的第二部分并调用它,例如getValue
  • @Pershing - It's purposed to calculate more complexed equations including negatives, floating point, and brackets. 以您编写的方式编写代码的问题在于,您很快就会发疯,试图增强和维护它。您的代码将做各种曲折以跟上。编写此类表达式评估器的正式方式是使用语法/解析器或如前所述的实现此范例的库,而不是以临时方式进行“逐字符”循环。
  • 谢谢大家的回答,我真的很感激,它对我帮助很大。但问题是:我如何将迭代器传递给函数以使其正常工作并且不处理我认为是问题的副本?
【解决方案2】:

我在您的代码中看到的一件事是您假设 std::string 是空终止的。您的大多数循环都没有正确界定。例如:

while( *strPtr == ' ' )
{
    strPtr++;
}

如果整个字符串都是空格怎么办?是什么阻止了这个循环进入未知领域?

std::string 不必以 null 结尾,因此无法保证此循环在到达字符串末尾时会停止。您在代码的其他地方执行相同类型的循环。

如果要这样循环,则需要编写:

while( *strPtr == ' ' && strPtr != formula.end())
    strPtr++;

【讨论】:

  • 这就是为什么我建议使用for 循环for (string::iterator it = str.begin(); it!=str.end();++it) 进行迭代。其实这段代码有很多错误,主要原因是大量使用*和++。没有必要把这些琐碎的工作复杂化。
  • 谢谢。我添加了一些安全功能:)
猜你喜欢
  • 1970-01-01
  • 2020-05-28
  • 2013-06-03
  • 1970-01-01
  • 1970-01-01
  • 2013-09-02
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多