奇怪的QT无符号Int错误

时间:2013-02-20 23:17:19

标签: c++ qt runtime-error

我正在研究一个RPN计算器,现在我的main.cpp和这些其他类文件应该采用一串代数运算,例如“3 + 4 / 2.34”,可以采用算术运算符,可读取双精度,整数,分数和混合分数(整数,单个空格,然后是分数)。

在命令控制台中我收到此错误:

ASSERT: "uint(i) < uint(size())" in file c:\QtSDK\Desktop\Qt\4.8.1\mingw\include
/QtCore/qstring.h, line 701

This application has requested the Runtime to terminate it in an unusual way.
Please contact the application's support team for more information.
Press <RETURN> to close this window...

我不太了解QT能够嗅出这个错误来自哪里,所以除了展示我的代码并希望有人可以帮助我之外我别无其他选择。有很多代码:/我已经排除了Fraction和Mixed类的头文件和源代码,因为那些没有使用qstring.h,这是编译器似乎在抱怨的内容。如果您认为这些是必需的,我可以发布它们。

据我所知,它与将无符号整数与整数进行比较有关,可能尝试将负int分配给uint?这是奇怪的部分,在main.cpp文件中,输入字符串是“1345/43143 - 2”,这会导致错误。此外,“3 + 4”也会导致错误。奇怪的是,如果我将输入字符串设置为“2341 +(23 ^ 4.421)/ 23/321 - 5 6/7”它可以工作,但没有其他输入字符串似乎工作。

Token.h

#ifndef TOKEN_H
#define TOKEN_H

#include "Mixed.h"
#include "Fraction.h"

class Token
{
public:
    Token();
    Token(const QString& Substring);
    void SetIntPart(const QString& Substring);
    void SetDoublePart(const QString& Substring);
    void SetFractionPart(const QString& Substring);
    void SetMixedPart(const QString& Substring);
    void SetOperatorPart(const QString& Substring);

    bool isDouble(const QString& Substring);
    bool isInt(const QString& Substring);
    bool isFraction(const QString& Substring);
    bool isMixed(const QString& Substring);
    bool isOperator(const QString& Substring);
    bool isNumber()
    { return (inttoken || doubletoken || fractiontoken || mixedtoken); }
    bool isLeftParen();
    bool isRightParen();
    bool isOperator();


    int IntPart() { return intpart; }
    double DoublePart() { return doublepart; }
    Fraction FractionPart() { return fractionpart; }
    Mixed MixedPart() { return mixedpart; }
    char OperatorPart() { return operatorpart; }
    bool IntToken() { return inttoken; }
    bool DoubleToken() { return doubletoken; }
    bool FractionToken() { return fractiontoken; }
    bool MixedToken() { return mixedtoken; }
    bool OperatorToken() { return operatortoken; }
    QString toQString();
    void Print(ostream& out) const;
    friend ostream& operator<<(ostream& out, const Token& T);

private:
    int intpart;
    double doublepart;
    Fraction fractionpart;
    Mixed mixedpart;
    char operatorpart;

    bool inttoken;
    bool doubletoken;
    bool fractiontoken;
    bool operatortoken;
    bool mixedtoken;

    void ClearBools();
    void ClearParts();
    void ClearAll() { ClearBools(); ClearParts(); }
};



#endif // TOKEN_H

Parser.h

#ifndef PARSER_H
#define PARSER_H

#include <iostream>
#include <cstdlib>
#include "Fraction.h"
#include "Mixed.h"
#include "Queue.h"
#include "Stack.h"
#include "Token.h"

class Parser
{
public:
    Parser();
    void LoadInputQueue(const QString& QS);
    void LoadOutputQueue();
    void CopyInputToString(QString &QS);
    void CopyOutputToString(QString &QS);
    bool isOperator(const QChar& Qch);
    bool isSpace(const QChar& Qch);
    bool isRightParen(const QChar& Qch);
    bool isLeftParen(const QChar& Qch);
    bool isParen(const QChar& Qch);
    bool isDigit(const QChar& Qch);
    void PrintInputQueue(ostream& out);
    void PrintOutputQueue(ostream& out);
    void PrintOperatorStack(ostream& out);
    int precedence(Token T);

private:
    Queue<Token> InputQueue;
    Queue<Token> OutputQueue;
    Stack<Token> OperatorStack;

    void Tokenize(const QString& InputString, int n);
};

#endif // PARSER_H

的main.cpp

#include <QtCore/QCoreApplication>
#include <cstdlib>
#include <iostream>
#include "Token.h"
#include "Parser.h"

using namespace std;

int main(int argc, char *argv[])
{
    QCoreApplication a(argc, argv);

    /*cout << "Fractiontoken: " << A.FractionToken() << endl;
    cout << "Fraction part: " << A.FractionPart() << endl;
    cout << "Inttoken: " << A.IntToken() << endl;
    cout << "Int part: " << A.IntPart() << endl;
    cout << "Doubletoken: " << A.DoubleToken() << endl;
    cout << "Double part: " << A.DoublePart() << endl;
    cout << "Mixedtoken: " << A.MixedToken() << endl;
    cout << "Mixed part: " << A.MixedPart() << endl;
    cout << "Operatortoken: " << A.OperatorToken() << endl;
    cout << "Operator part: " << A.OperatorPart() << endl;*/

    QString inputstring = "1345/43143 - 2";
    Parser P;
    QString displaystring;

    P.LoadInputQueue(inputstring);
    P.CopyInputToString(displaystring);
    cout << qPrintable(displaystring);
    cout << endl;

    P.LoadOutputQueue();
    P.CopyOutputToString(displaystring);
    cout << qPrintable(displaystring);
    cout << endl;

    return a.exec();
}

parser.cpp

#include "Parser.h"
enum PARENTHESIS_1{P1};
enum PARENTHESIS_2{P2};

bool Parser::isOperator(const QChar& Qch)
{
    char ch = Qch.toAscii();
    if (ch == '+' ||
            ch == '-' ||
            ch == '*' ||
            ch == '/' ||
            ch == '(' ||
            ch == ')' ||
            ch == '^' )
        return 1;
    return 0;
}

bool Parser::isSpace(const QChar& Qch)
{
    if (Qch.toAscii() == ' ')
        return 1;
    return 0;
}

bool Parser::isLeftParen(const QChar& Qch)
{
    char ch = Qch.toAscii();
    if (ch == '(')
        return 1;
    return 0;
}

bool Parser::isRightParen(const QChar& Qch)
{
    char ch = Qch.toAscii();
    if (ch == ')')
        return 1;
    return 0;
}

bool Parser::isParen(const QChar& Qch)
{
    if (isRightParen(Qch) || isLeftParen(Qch))
        return 1;
    return 0;
}

bool Parser::isDigit(const QChar &Qch)
{
    char ch = Qch.toAscii();
    if (ch > 47 && ch < 58)
        return 1;
    return 0;
}


Parser::Parser() : InputQueue(100), OutputQueue(100)
{

}

void Parser::Tokenize(const QString& InputString, int n)
{
    if (n >= InputString.size())
        return;
    else
    {
        if (isOperator(InputString[n]))
        {
            QString temp;
            temp.append(InputString[n]);
            Token temptoken(temp);
            InputQueue.enqueue(temptoken);
            Tokenize(InputString, n+1);
        }
        else if (isSpace(InputString[n]))
            Tokenize(InputString, n+1);
        else
        {
            QString temp;
            while (n < InputString.size() && !isSpace(InputString[n]) && !isParen(InputString[n]))
            {
                temp.append(InputString[n]);
                n++;
            }
            if (isSpace(InputString[n]))
            {
                if (isDigit(InputString[n+1]))
                {
                    temp.append(' ');
                    n++;
                    while (n < InputString.size() && !isSpace(InputString[n]) &&
                                    !isParen(InputString[n]))
                    {
                        temp.append(InputString[n]);
                        n++;
                    }
                    Token temptoken(temp);
                    InputQueue.enqueue(temptoken);
                    Tokenize(InputString, n);
                }
                else if (isOperator(InputString[n+1]))
                {
                    Token temptoken(temp);
                    InputQueue.enqueue(temptoken);
                    Tokenize(InputString, n+1);
                }
            }
            else if (isParen(InputString[n]))
            {
                Token temptoken(temp);
                InputQueue.enqueue(temptoken);
                temp.clear();
                temp.append(InputString[n]);
                Token temptoken2(temp);
                InputQueue.enqueue(temptoken2);
                Tokenize(InputString, n+1);
            }

        }


     }
}

int Parser::precedence(Token T)
{
    if (T.OperatorToken())
    {
        char temp = T.OperatorPart();
        if (temp == '^')
            return 4;
        if (temp == '*' || temp == '/')
            return 3;
        if (temp == '+' || temp == '-')
            return 2;
    }
    return 1;
}

void Parser::LoadOutputQueue()
{
    while (!InputQueue.empty())
    {
        Token temptoken;
        InputQueue.dequeue(temptoken);
        if (temptoken.isNumber())
            OutputQueue.enqueue(temptoken);
        else if (temptoken.isLeftParen())
            OperatorStack.push(temptoken);
        else if (temptoken.isRightParen())
        {
            while (!OperatorStack.empty() && !(OperatorStack.Peek()).isLeftParen())
            {
                Token temp;
                OperatorStack.pop(temp);
                OutputQueue.enqueue(temp);
            }
            if (!OperatorStack.empty() && (OperatorStack.Peek()).isLeftParen())
                OperatorStack.pop(temptoken);
            else if (OperatorStack.empty())
                throw P1;
        }
        else if (temptoken.isOperator())
        {
            while (!OperatorStack.empty() && precedence(temptoken) < precedence(OperatorStack.Peek()))
            {
                Token temp;
                OperatorStack.pop(temp);
                OutputQueue.enqueue(temp);
            }
            OperatorStack.push(temptoken);
        }

    }
    while (!OperatorStack.empty())
    {
        Token temptoken;
        OperatorStack.pop(temptoken);
        if (temptoken.isLeftParen())
            throw P2;
        OutputQueue.enqueue(temptoken);
    }


}

//this function takes a QString (of chars) and from that builds its queue of tokens
void Parser::LoadInputQueue(const QString &QS)
{
    Tokenize(QS,0);
}

void Parser::CopyOutputToString(QString &QS)
{
    QString tempstring;
    Token temptoken;
    for (int i=OutputQueue.Size()-1; i>=0; i--)
    {
        temptoken = OutputQueue.Element(i);
        tempstring.append(temptoken.toQString());
    }
    QS = tempstring;

}

void Parser::CopyInputToString(QString& QS)
{
    QString tempstring;
    Token temptoken;
    for (int i=InputQueue.Size()-1; i>=0; i--)
    {
        temptoken = InputQueue.Element(i);
        tempstring.append(temptoken.toQString());
    }
    QS = tempstring;
}

void Parser::PrintInputQueue(ostream& out)
{
    out << InputQueue << endl;
}

void Parser::PrintOutputQueue(ostream& out)
{
    out << OutputQueue << endl;
}

void Parser::PrintOperatorStack(ostream& out)
{
    out << OperatorStack << endl;
}

token.cpp

#include "Token.h"
#include <QStringList>

enum TOKEN_EXCEPTIONS{UNKNOWN_TOKEN};

Token::Token()
{

}

Token::Token(const QString& Substring)
{
    if (isInt(Substring))
        SetIntPart(Substring);
    else if (isDouble(Substring))
        SetDoublePart(Substring);
    else if (isFraction(Substring))
        SetFractionPart(Substring);
    else if (isMixed(Substring))
        SetMixedPart(Substring);
    else if (isOperator(Substring))
        SetOperatorPart(Substring);
    else
    {
        cout << qPrintable(Substring) << endl;
        throw UNKNOWN_TOKEN;
    }
}

void Token::SetIntPart(const QString& Substring)
{
    ClearAll();
    intpart = Substring.toInt();
    inttoken = 1;
}

void Token::SetDoublePart(const QString& Substring)
{
    ClearAll();
    doublepart = Substring.toDouble();
    doubletoken = 1;

}

void Token::SetFractionPart(const QString& Substring)
{
    ClearAll();
    QStringList Q;
    Q = Substring.split('/');
    Fraction frac(Q[0].toInt(),Q[1].toInt());
    fractionpart = frac;
    fractiontoken = 1;

}

void Token::SetMixedPart(const QString& Substring)
{
    ClearAll();
    QStringList Q1, Q2;
    Q1 = Substring.split(' ');
    QString wholepart = Q1[0];
    Q2 = Q1[1].split('/');
    QString numeratorstring = Q2[0];
    QString denominatorstring = Q2[1];
    Mixed M(wholepart.toInt(),numeratorstring.toInt(),denominatorstring.toInt());
    mixedpart = M;
    mixedtoken = 1;
}

void Token::SetOperatorPart(const QString& Substring)
{
    ClearAll();
    operatorpart = Substring[0].toAscii();
    operatortoken = 1;
}

bool Token::isDouble(const QString& Substring)
{
    int pointcount=0;
    int intcount=0;
    int pointloc=0;

    for (int i=0; i<Substring.size(); i++)
    {
        if (isdigit(Substring[i].toAscii()))
            intcount++;
        if (Substring[i].toAscii() == '.')
        {
            pointcount++;
            pointloc = i;
        }
    }

    if (pointcount != 1)
        return 0;
    if (intcount != Substring.size() - 1)
        return 0;
    return 1;

}

bool Token::isInt(const QString& Substring)
{
    if (Substring[0].toAscii() == '0')
        return 0;

    for (int i=0; i<Substring.size(); i++)
    {
        if (!isdigit(Substring[i].toAscii()))
            return 0;
    }

    return 1;
}

bool Token::isFraction(const QString& Substring)
{
    int slashcount=0;
    int intcount=0;
    int slashloc=0;

    for (int i=0; i<Substring.size(); i++)
    {
        if (Substring[i].toAscii() == '/')
        {
            slashcount++;
            slashloc = i;
        }
        if (isdigit(Substring[i].toAscii()))
            intcount++;
    }

    if (slashcount != 1) // if there is not exactly 1 slash in substring
        return 0;
    if (intcount != Substring.size() - 1) //if the rest of the chars are not integers
        return 0;
    if (slashloc == 0 || slashloc == Substring.size() - 1) //if slash is at wrong location
        return 0;
    if (Substring[slashloc+1].toAscii() == '0' ||
            Substring[0].toAscii() == '0')
        return 0;
    return 1;
}

bool Token::isMixed(const QString& Substring)
{
    if (Substring[0].toAscii() == '0')
        return 0;

    int spacecount=0;
    int slashcount=0;
    int intcount=0;
    int slashloc=0;
    int spaceloc=0;

    for (int i=0; i<Substring.size(); i++)
    {
        if (isspace(Substring[i].toAscii()))
        {
            spacecount++;
            spaceloc = i;
        }
        if (isdigit(Substring[i].toAscii()))
            intcount++;
        if (Substring[i].toAscii() == '/')
        {
            slashcount++;
            slashloc = i;
        }
    }

//    cout << "spacecount: " << spacecount << endl;
//    cout << "slashcount: " << slashcount << endl;
//    cout << "intcount: " << intcount << endl;
//    cout << "slashloc: " << slashloc << endl;
//    cout << "spaceloc: " << spaceloc << endl;

    if (spacecount != 1)
        return 0;
    if (slashcount != 1)
        return 0;
    if (intcount != Substring.size() - 2)
        return 0;
    if (slashloc == 0 || slashloc == Substring.size()-1)
        return 0;
    if (spaceloc == 0 || spaceloc == Substring.size()-1)
        return 0;
    if (slashloc < spaceloc)
        return 0;
    if (!isdigit(Substring[slashloc-1].toAscii()) || !isdigit(Substring[slashloc+1].toAscii()))
        return 0;
    if (!isdigit(Substring[spaceloc-1].toAscii()) || !isdigit(Substring[slashloc+1].toAscii()))
        return 0;
    return 1;

}

bool Token::isOperator(const QString& Substring)
{
    if (Substring.size() != 1)
        return 0;
    if (Substring[0] == '+' ||
            Substring[0] == '-' ||
            Substring[0] == '*' ||
            Substring[0] == '^' ||
            Substring[0] == '/' ||
            Substring[0] == '(' ||
            Substring[0] == ')')
        return 1;
    return 0;

}

void Token::ClearBools()
{
    mixedtoken = 0;
    inttoken = 0;
    doubletoken = 0;
    fractiontoken = 0;
    operatortoken = 0;

}

void Token::ClearParts()
{
    intpart = 0;
    doublepart = 0;
    Fraction f(0);
    fractionpart = f;
    Mixed m(0);
    mixedpart = m;
    operatorpart = NULL;
}

QString Token::toQString()
{
    QString tempstring;
    if (inttoken)
    {
        QString temp;
        temp.setNum(intpart);
        tempstring.append('[');
        tempstring.append(temp);
        tempstring.append(']');
        return tempstring;
    }
    else if (doubletoken)
    {
        QString temp;
        temp.setNum(doublepart);
        tempstring.append('[');
        tempstring.append(temp);
        tempstring.append(']');
        return tempstring;
    }
    else if (fractiontoken)
    {
        Fraction F = fractionpart;
        QString temp;
        tempstring.append('[');
        temp.setNum(F.Numerator());
        tempstring.append(temp);
        tempstring.append('/');
        temp.setNum(F.Denominator());
        tempstring.append(temp);
        tempstring.append(']');
        return tempstring;
    }
    else if (mixedtoken)
    {
        Mixed M = mixedpart;
        QString temp;
        tempstring.append('[');
        temp.setNum(M.WholePart());
        tempstring.append(temp);
        tempstring.append(' ');
        temp.setNum(M.Numerator());
        tempstring.append(temp);
        tempstring.append('/');
        temp.setNum(M.Denominator());
        tempstring.append(temp);
        tempstring.append(']');
        return tempstring;
    }
    else if (operatortoken)
    {
        tempstring.append('[');
        tempstring.append(operatorpart);
        tempstring.append(']');
    }
    else
        throw UNKNOWN_TOKEN;
}

void Token::Print(ostream& out) const
{
    if (inttoken)
    {
        out << intpart;
    }
    else if (doubletoken)
    {
        out << doublepart;
    }
    else if (fractiontoken)
    {
        out << fractionpart;
    }
    else if (mixedtoken)
    {
        out << mixedpart;
    }
    else if (operatortoken)
    {
        out << operatorpart;
    }
    else
        throw 1;

}

ostream& operator<<(ostream& out, const Token& T)
{
    T.Print(out);
    return out;
}

bool Token::isLeftParen()
{
    if (operatortoken && operatorpart == '(')
        return 1;
    return 0;
}

bool Token::isRightParen()
{
    if (operatortoken && operatorpart == ')')
        return 1;
    return 0;
}

bool Token::isOperator()
{
    if (operatortoken)
        return 1;
    return 0;
}

4 个答案:

答案 0 :(得分:1)

我认为这肯定是错误的:

       while (n < InputString.size() && !isSpace(InputString[n]) && !isParen(InputString[n]))
        {
            temp.append(InputString[n]);
            n++;
        }
        if (isSpace(InputString[n]))

应该是:

       while (n < InputString.size() && !isSpace(InputString[n]) && !isParen(InputString[n]))
        {
            temp.append(InputString[n]);
            n++;
        }
        if (n < InputString.size() && isSpace(InputString[n]))

真正的错误可能是在其他地方没有读取所有代码,但类似的地方你运行到字符串结束然后访问后面的字符。

在调试器中运行代码,并在断言时查看代码中的代码。

答案 1 :(得分:1)

短篇小说 -

ASSERT: "uint(i) < uint(size())" in file c:\QtSDK\Desktop\Qt\4.8.1\mingw\include
/QtCore/qstring.h, line 701

这基本上意味着你在字符串长度上运行。它也可以是引用单位化或释放的存储区域的效果。

我最好的猜测是解析器试图读取输入字符串长度,这表明某些停止条件不符合。

了解这一点,你可能更容易找到解析器问题本身。

如果你有一个允许调试的环境(例如eclipse),那就去吧。如果没有,您可以尝试在代码的不同位置插入各种调试printf语句(我将从Parser开始)并查看它遇到错误的位置。

我查看了代码,但没有看到明显的问题。祝你好运!

答案 2 :(得分:0)

有很多地方可以访问字符(或类似的数组条目),而无需先检查索引:

void Parser::Tokenize(const QString& InputString, int n)
            if (isSpace(InputString[n]))
            {
                if (isDigit(InputString[n+1]))
                ...
                else if (isOperator(InputString[n+1]))




void Token::SetFractionPart(const QString& Substring)
    Fraction frac(Q[0].toInt(),Q[1].toInt());


void Token::SetMixedPart(const QString& Substring)
    QString wholepart = Q1[0];
    Q2 = Q1[1].split('/');
    QString numeratorstring = Q2[0];
    QString denominatorstring = Q2[1];


void Token::SetOperatorPart(const QString& Substring)
    operatorpart = Substring[0].toAscii();


bool Token::isInt(const QString& Substring)
    if (Substring[0].toAscii() == '0')

bool Token::isMixed(const QString& Substring)
    if (Substring[0].toAscii() == '0')

通过在调试器中运行并查看stacktrace

,您可以更轻松地找到特定问题

答案 3 :(得分:0)

以下是您的代码的一些观察结果:

  1. 您在函数中返回0或1而不是falsetrue 返回bool
  2. 您可以,而不是与每个操作员角色进行比较 搜索它:

    bool is_operator(char c)
    {
    static const char operators_text[] = "+-/*()^";
    std::string operators_str(operators_text);
    return operators_str.find_first_of(c) != std::string::npos;
    }

  3. 您的 is-a 功能可以简化:

    bool Parser :: isSpace(const QChar&amp; qch)
    {
      return qch =='';
    }

  4. 让您的isDigit更具可读性:

    bool Parser :: isDigit(const Qchar&amp; qch)
    {
      return(qch&gt; ='0')|| (qch&lt; ='9');
    }

  5. 或使用std::isdigit()