2013-02-20 4 views
1

Я работаю над калькулятором RPN, и сейчас мой main.cpp вместе с этими другими файлами классов должен взять строку алгебраических операций, например. «3 + 4/2.34», который может принимать арифметические операторы и может читать в двойниках, ints, дробях и смешанных фракциях (целое число, одно пространство, а затем дробь).Strange QT Unsigned Int Error

В командной консоли я получаю эту ошибку:

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; 
} 
+0

Почему вы возвращаете 0 и 1 вместо 'false' и' true' в свои функции, которые возвращают 'bool'? –

+2

Ошибка означает, что вы обращаетесь к недопустимому индексу в строке – BeniBela

ответ

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])) 

Реальная ошибка может быть в другом месте не читали весь код, но что-то аналогично, когда вы запускаете конец строки, а затем получаете доступ к символу после него.

Запустите свой код в отладчике и когда он утверждает, где он находится в вашем коде.

+0

Да, пройдя через и проверив эти проверки, проблема решена. Спасибо вам! – BrownBeard93423

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

1

Чтобы вырезать Короче говоря -

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

это в основном означает, что вы работаете по длине строки. Это может быть также эффект ссылки на единичную или свободную область памяти.

Мое лучшее обоснованное предположение заключалось в том, что синтаксический анализатор пытается прочесть длину входной строки, что предполагает, что некоторые условия остановки не выполняются.

Зная это, вам может быть проще выследить проблему с парсером.

Если у вас есть среда, которая позволяет отлаживать (например, затмение), то идите за ней. Если нет, вы можете попробовать вставить различные отладочные операторы printf в разных местах кода (я бы начал с Parser) и посмотреть, где он запущен в ошибке.

Я просмотрел код, но не вижу очевидной проблемы. Удачи!

0

Вот некоторые замечания по поводу вашего кода:

  1. Вы возвращаетесь 0 или 1 вместо false или true функций , которые возвращают 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. Вашего есть- функции можно упростить:

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

  4. Сделайте isDigit более читаемым:

    BOOL Parser :: isDigit (Const QChar & Qch)
    {
    возвращение (Qch> = '0') || (qch < = '9');
    }

Или используйте std::isdigit().

+0

Не требуется isSpace и isDigit, так как уже есть qch.isSpace() и qch.isDigit() – BeniBela

Смежные вопросы