Строковый поток переменной длины входов от терминала, что является лучшим способом для реализации - PullRequest
0 голосов
/ 17 апреля 2020

Я работаю над заданием, в котором нас просят заполнить дерево AVL значениями.

Код должен взять строку из терминала и выполнить дополнения к дереву, а также удаления. затем, наконец, распечатайте дерево AVL по порядку.

Строка с терминала будет выглядеть следующим образом

A3 A5 A6 D5 D6 print 

Строка может иметь длину от 1 до 100 входов.

Мой вопрос: каков наилучший способ реализовать функцию считывателя терминала, которая будет эффективно и результативно записывать и вводить значения и даже инициализировать функции ввода, удаления и печати?

Я знаком с потоком строк и библиотекой 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 l oop и добавление строк к вектору - еще одна идея, над которой я работаю.

Спасибо за вашу помощь

PS - Назначение - оценить нашу способность писать программу дерева AVL, обработка входов не отмечена. Я просто хочу использовать хороший метод и возможность развивать свои навыки дальше.

1 Ответ

0 голосов
/ 17 апреля 2020

Вам не нужна рекурсивная функция, а также не нужно использовать магию c Функция "removeFirstWord".

Если у вас есть данные в std::istringstream и вы извлекаете их с помощью оператора >>, тогда Данные уже "пропали", Вы не будете читать их снова. Внутренние механизмы stream будут продвигать некоторый внутренний указатель. (Это очень упрощенное объяснение).

Решение состоит в том, чтобы извлечь все слова в std::istringstream с помощью простого while l oop. Оператор извлечения instring >> word возвращает ссылку на оригинал std::istringstream, в данном случае на "instring". И есть переопределение оператора bool для streams, которое указывает, установлен бит fail потока или нет. И это также устанавливается, когда поток полностью «опустошен» (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;
}
...