终端输入的字符串流可变长度,什么是最好的实现方式

String stream variable length of inputs from terminal, what is the best way to implement

我正在做一项作业,要求我们用值填充 AVL 树。

代码需要从终端获取一行并对树执行添加和删除操作。然后最后按顺序打印AVL树。

来自终端的字符串看起来像这样

A3 A5 A6 D5 D6 print 

字符串可以是 1 - 100 输入长度的任意长度。

我的问题是实现终端 reader 功能的最佳方式是什么,该功能将有效地记录和输入值,甚至初始化输入、删除和打印功能?

我熟悉字符串流和 sstream 库,但正在努力寻找解决此问题的好方法。

我设想的函数的一些伪代码看起来像这样。

void stringReader(string sentence){
    string word;
    stringstream instring(input);

    instring >> word;//word should be a single input ie: "A3" or "D6" 
                     //in the 0th position of the string stream.

    if (word == "print"){
        printAVL(node* treeroot);
        return; 
    }else{
        if(statement to determine if A or D){
              //perform deletion or addition;
        }
    }
    input.removeFirstWord()//some magic function I am yet to find that removes the first input 
                           //and allows me to do this recursively.
    stringReader(input);

}

int main(){
    string input; 
    getline(cin, input);//the raw input line from terminal ie;"A3 A5 A6 D5 D6 print"
    stringReader(input);
}

我不是 100% 致力于递归方法,也不是一心想使用 sstream 库,非常感谢任何想法或方法。

编辑 - 使用 while 循环并将字符串附加到向量是我正在研究的另一个想法。

感谢您的帮助

PS - 赋值是判断我们写一个AVL树程序的能力,输入的处理没有标注。我只是想要一个好的方法来使用并有机会进一步发展我的技能。

您不需要递归函数,也不需要一些神奇的 "removeFirstWord" 函数。

如果你在std::istringstream中有数据,你用>>操作符提取它们,那么数据已经是"gone",你不会再读了。 stream 的内部机制会推进一些内部指针。 (这是一个非常简化的解释)。

解决方案是,用一个简单的 while 循环提取 std::istringstream 中的所有单词。提取语句 instring >> word returns 对原始 std::istringstream 的引用,在本例中为 "instring"。并且 streamsbool 运算符被覆盖,它指示是否设置了流的 fail 位。而且,这也被设置,当流 "emptied" 完全 (EOF).

因此,使用命令

while (instring >> word) {

您将阅读 "instring" 中的所有单词。

然后您可以检查有效命令并执行必要的操作。

您可以在下面的示例中看到这一点。请注意:我没有实现 AVL 树。我用 std::set 做了一个模拟。需要自己实现AVL树

示例(许多可能的解决方案之一):

#include <iostream>
#include <string>
#include <set>
#include <sstream>

// A Pseudo AVL. It is a std::set and a Red Black tree
struct PretendToBeAnAVLtree {

    // Data container
    std::set<int> data{};

    // Add function
    void addValue(int value) {
        auto result = data.insert(value);
        if (!result.second) std::cerr << "\n*** Error Add: Value " << value << " is already in tree\n";
    };
    // Delete function
    void deleteValue(int value) {
        auto it = data.find(value);
        if (it == data.end())
            std::cerr << "\n*** Error Delete: Value " << value << " is not in tree\n";
        else
            data.erase(it);
    }
    // Print function
    void print() {
        for (const int i : data) std::cout << i << " ";
        std::cout << "\n\n";
    }
};

// Replace PretendToBeAnAVLtree with your implementation of a real AVL tree
using AVL = PretendToBeAnAVLtree;

// Read some string and execute the commands in the input string
void processInputData(const std::string& input, AVL& avl) {

    // Some debug output
    std::cout << "\nInput data: " << input << "\n";

    // Put the input string into an istringstream for easier word extraction
    std::istringstream instring(input);

    // Now read all words from the istringstream and and consume them
    std::string word{};
    while (instring >> word) {

        // Depending on the command in the word
        // Check for print command
        if (word == "print") {
            avl.print(); 
        } // Check for add command
        else if (word[0] == 'A') {
            try { 
                // Convert string starting at position 1 of the word to an integer
                int value = std::stoi(word.substr(1));
                // Add the value to the tree
                avl.addValue(value); }
            // In case of conversion error 
            catch (...) { std::cerr << "\n*** Error: Invalid add command '" << word << "' in input data\n"; }
        } // Check for Delete
        else if (word[0] == 'D') {
            try {
                // Convert string starting at position 1 of the word to an integer
                int value = std::stoi(word.substr(1));
                // Delete the value from the tree
                avl.deleteValue(value);
            }
            // In case of conversion error 
            catch (...) { std::cerr << "\n*** Error: Invalid delete command '" << word << "' in input data\n"; }
        }
        else {
            // In case of a totaly unknown command
            std::cerr << "\n*** Error: Invalid command '" << word << "' in input data\n";
        }
    }
}

// Driver code
int main() {

    // The AVL
    AVL avl;

    // Some test commands
    processInputData("A3 A5 A6 D5 D6 print", avl);
    processInputData("A1 A2 A4 A5 print A6 A7 A8 A9 print", avl);
    processInputData("A3 A100 print", avl);
    processInputData("D3 D4 D555 print", avl);
    processInputData("A200 X999 A300 print", avl);

    return 0;
}