【问题标题】:abnormal behaviour while displaying char array in C++ after object initialization对象初始化后在 C++ 中显示 char 数组时出现异常行为
【发布时间】:2020-05-22 10:06:37
【问题描述】:

main():

char inp[] = "(A+B)/(C*D))";

Infix i;
cout << "In main: " << inp  /* + ')' */  << endl << endl;

这里是Infix构造函数:

Infix() {
        push('(');
        cout << "Element In Stack: " << *returnElement(returnTop()) << endl;
        outputString = "";
        strcpy(operatorArray, "/*-+%");
        cout << "Operator Array: " << operatorArray << endl;

    }

Infix 继承自“Stack”类:

class Stack{
int top = -1;
char arr[100];

public:
    bool push(char);
    char pop();
    char peek();
    bool isEmpty();
    void displayAll();
    char returnTop() { return top;}
    char* returnElement(int i) {
        if(i > 98){
            cout << "StackOutOfIndex";
            return nullptr;
        }
        return &arr[i];
    }

};

当我在 main 中运行代码时,它显示异常输出:

Element In Stack: (
Operator Array: /*-+%
In main: +%


Stack Object Destroyed!

但是,在 main 中,如果注释声明“中缀”对象声明的行,则代码运行正常:

In main: (A+B)/(C*D))

编辑:

堆栈类

#include<iostream>

using namespace std;

class Stack{
    int top = -1;
    char arr[100];

    public:
        bool push(char);
        char pop();
        char peek();
        bool isEmpty();
        void displayAll();
        char returnTop() { return top;}
        char* returnElement(int i) {
            if(i > 98){
                cout << "StackOutOfIndex";
                return nullptr;
            }
            return &arr[i];
        }

};

bool Stack:: push(char elementToPush) {
    if(top > 98) {
        cout << "\nStack Overflow!!";
        return false;
    } else {
        arr[++top] = elementToPush;
        return true;
    }
}

char Stack:: pop() {
    if(top <= -1) {
        cout << "\nStack Underflow!!";
        return ' ';
    } else {
        return (arr[top--]);
    }
}

char Stack:: peek() {
    if(top > 98) {
        cout << "\nStack Overflow!!";
        return ' ';
    } else {
        return arr[top];
    }
}

bool Stack:: isEmpty() {
    return (top <= 0);
}

void Stack:: displayAll() {
    if(top <= -1) {
        cout << "null";
        return;
    }
    int i = top;
    while (i >= 0) {
        cout << arr[i] << " ";
        --i;
    }
    cout << "\n";
}

中缀类

#include<iostream>
#include<cstring>
#include<D:\Programs\11Stack.cpp>

using namespace std;

class Infix : public Stack {
    string outputString;
    char operatorArray[];
    public:
        Infix() {
            push('(');
            cout << "Element In Stack: " << *returnElement(returnTop()) << endl;
            outputString = "";
            strcpy(operatorArray, "/*-+%");
            cout << "Operator Array: " << operatorArray << endl;

        }

        string infixToPostfix(char *, int);
        bool manupulateOperator(char, int); 
        int checkPrecedence(char);

        ~Infix() {
            cout << "\nStack Object Destroyed!" << endl;
        }
};

string Infix:: infixToPostfix(char *str, int size) {
    cout << "\nGiven String: " << str << endl;
    int x;
    for(int i = 0; i < size; ++size) {
        x = str[i];
        if(x != ' ') {
            if(x == ')') {
                while(returnTop() != '(') {
                    cout << pop() << " popped!\n";
                }

                    cout << pop() << " popped!\n";
            } else if(isalpha(x)) {
                cout << x;
        } /* else{ // scanned character is an operator
            if(manupulateOperator(x, i)) {

            } else {
                return " ";
                }
            } */
        }
    }

    return outputString;
}

bool Infix::manupulateOperator(char c, int position) {
    try {
        char topElement = *returnElement(returnTop());
        if(checkPrecedence(c) == -1) {
            cout << "\nErr\n";
        }else if((checkPrecedence(c) > checkPrecedence(topElement)) || returnTop() == 0) {
            push(c);
            cout << c << " pushed!\n";
        }
    } catch(std::exception e) {
        std::cerr << e.what() << '\n';
        return false;
    } catch (char* Ce) {
        cout << Ce << endl;
    }

    return true;
}

int Infix::checkPrecedence(char c) {
    /* 
        + -> 1
        - -> 1
        * -> 2
        / -> 2
        % -> 2
    */
    switch(c) {
        case '+':
            return 1;

        case '-':
            return 1;

        case '*':
            return 2;

        case '/':
            return 2;

        case '%':
            return 2;

        default:
            // throw "Illegal Operator Detected!";
            cout << "Illegal Operator Detected: " << c << endl;
            return -1;

    }
}

int main() {
    cout << endl;
    int x = 1;

    char inp[] = "(A+B)/(C*D))";

    //Infix i;
    cout << "In main: " << inp  /* + ')' */  << endl << endl;

    // cout << i.infixToPostfix(input + ')', sizeof(input));
/*     for(int i = 0; i < strlen(inp); ++i) {
        cout << inp[i];
    }
 */
    return 0;
}

【问题讨论】:

  • 你为什么不使用std::string
  • 好吧,我想在 C++ 中尝试一下 char 数组
  • 有什么理由不使用std::string
  • 好吧,没有具体的说!

标签: c++ arrays class oop pointers


【解决方案1】:

char operatorArray[]; 在标准 C++ 中是不允许的。

如果您没有看到错误消息,那么我建议您调整编译器设置以遵循该语言的标准形式,这将为您节省大量时间。

【讨论】:

    【解决方案2】:

    您将operatorArray 声明为char 的数组,但您没有为其分配任何内存!因此,当您随后在 Infix 构造函数中调用 strcpy(operatorArray, "/*-+%"); 时,您会通过尝试将给定的字符串常量复制到尚未分配的内存来导致 undefined behavior - 这似乎是覆盖在main 中声明的inp[] 数组。

    要解决此问题,我建议为您的 operatorArray 成员指定一个特定大小,该大小足以容纳您要复制到其中的任何字符串 - 在您提供的示例代码中可以使用 8 个字符:

    class Infix : public Stack {
        string outputString;
        char operatorArray[8]; // Make this member a REAL array of characters.
        //..
    

    【讨论】:

    • 非常感谢兄弟!我已经尝试找到这个错误 2 天了。很高兴你的帮助!但是,为什么编译器没有警告我呢?
    • @ShivamJha 这取决于您的编译器和您使用的设置(是否启用所有警告)。在带有 MSVC 编译器的 Visual Studio 2019 中,我得到:警告 C4200:使用了非标准扩展:结构/联合中的零大小数组
    【解决方案3】:

    当你的构造函数被调用时,你的变量char operatorArray[] 没有分配内存。当您使用strcpy 时,您写入的内容是您在内存中没有权限的地方,因此是其他信息。
    要查找此类错误,我建议使用valgrind

    【讨论】:

    • 是的,和 Adrain 一样 谢谢你的帮助,兄弟!去看看你的 valgrind
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-05-13
    • 1970-01-01
    • 2017-05-02
    • 1970-01-01
    • 2013-09-12
    相关资源
    最近更新 更多