Как поместить символы из файла в двухмерный вектор? - PullRequest
0 голосов
/ 06 июля 2019

Я пытался прочитать символы из внешнего файла, чтобы поместить его в двухмерный вектор типа char.Элементы должны иметь возможность сравниваться с определенными значениями, чтобы перемещаться по лабиринту, указанному в «MazeSample.txt».

Хотя я не смог вставить символы в вектор, я смогчитать и выводить символы с помощью функций get и cout.Следующий код является попыткой прочитать векторы в правильном формате, но в конце выдает ошибку:

//MazeSample.txt
SWWOW
OOOOW
WWWOW
WEOOW

//source.cpp
vector<vector<char>> maze;
ifstream mazeFile;
char token;

mazeFile.open("MazeSample.txt");

while (!mazeFile.eof()) {
    mazeFile.get(token); //reads a single character, goes to next char after loop

    for (int row = 0; row < maze.size(); row++) {
        for (int column = 0; column < maze.at(row).size(); row++) {
            maze.push_back(token);
        }
    }

    //cout << token;
}

mazeFile.close();

Для лабиринта, указанного в "MazeSample.txt", я ожидал бы maze вектор для чтения каждого символа строка за строкой, имитирующий формат образца лабиринта.

В вышеприведенном коде сообщается с ошибкой в ​​maze.push_back(token): «нет экземпляра перегруженной функции» std :: vector<_Ty, _Alloc> :: push_back ... "соответствует списку аргументов" "типы аргументов: (char)" "тип объекта: std :: vector>, std :: allocator >>>"

Ответы [ 2 ]

2 голосов
/ 06 июля 2019

Вы вставляете char в vector<vector<char>>. Вы должны создать vector<char>, вставить в него значения типа char и затем вставить vector<char> в vector<vector<char>> maze;. Вот исправленная версия вашей программы. Это может быть написано простыми способами, но для вашего понимания я внес исправления поверх вашей программы.

vector<vector<char>> maze;
ifstream mazeFile;
string token;

mazeFile.open("MazeSample.txt");

while (!mazeFile.eof()) {
    std::getline(mazeFile, token); //reads an entire line

    //Copy characters in entire row to vector of char
    vector<char> vecRow;
    vecRow.assign(token.begin(), token.end());

    //Push entire row of characters in a vector
    maze.push_back(vecRow);

}

mazeFile.close();
1 голос
/ 06 июля 2019

Причина вашей проблемы в том, что вы пытаетесь поместить символ в std :: vector из std vector.Таким образом, вы указали неправильный тип.

maze.at(row).push_back(token); сделает это, но тогда не будет строки.Вам также нужно нажать push_back и пустую строку, прежде чем вы сможете записать в нее данные.

Это ваша синтаксическая ошибка.

Тогда ваш код может быть существенно сокращен с помощью алгоритмов C ++.См .:


#include <iostream>
#include <vector>
#include <algorithm>
#include <iterator>
#include <sstream>


std::istringstream testDataFile(
R"#(00000
11111
22222
33333
44444
)#");



// This is a proxy to read a complete line with the extractor operator
struct CompleteLineAsVectorOfChar {
    // Overloaded Extractor Operator
    friend std::istream& operator>>(std::istream& is, CompleteLineAsVectorOfChar& cl) {
        std::string s{}; cl.completeLine.clear();  std::getline(is, s); 
        std::copy(s.begin(), s.end(), std::back_inserter(cl.completeLine));
        return is; }

    operator std::vector<char>() const { return completeLine; }  // Type cast operator for expected value
    std::vector<char> completeLine{};
};


int main()
{
    // Read complete source file into maze, by simply defining the variable and using the range constructor
    std::vector<std::vector<char>> maze { std::istream_iterator<CompleteLineAsVectorOfChar>(testDataFile), std::istream_iterator<CompleteLineAsVectorOfChar>() };

    // Debug output:  Copy all data to std::cout
    std::for_each(maze.begin(), maze.end(), [](const std::vector<char> & l) {std::copy(l.begin(), l.end(), std::ostream_iterator<char>(std::cout, " ")); std::cout << '\n'; });

    return 0;
}

Но это не конец.std::vector<char> не имеет преимущества перед строкой.Вы можете работать практически с теми же функциями, что и std::vector<char>.Это улучшение в дизайне.Код будет выглядеть примерно так:

#include <iostream>
#include <vector>
#include <algorithm>
#include <iterator>
#include <sstream>

std::istringstream testDataFile(
R"#(00000
11111
22222
33333
44444
)#");

int main()
{
    // Read complete source file into maze, by simply defining the variable and using the range constructor
    std::vector<std::string> maze{ std::istream_iterator<std::string>(testDataFile), std::istream_iterator<std::string>() };

    // Debug output:  Copy all data to std::cout
    std::copy(maze.begin(), maze.end(), std::ostream_iterator<std::string>(std::cout, "\n"));

    return 0;
}

Это гораздо более простое решение.И это также будет отвечать вашим потребностям.

Обратите внимание: я использовал istringstream для чтения данных, потому что у меня нет файла на SO.Но это так же, как и использование любого другого потока (например, ifstream).

EDIT

Первое решение - прочитать исходный код и поместить его непосредственно в std::vector<std::vector<char>>:

2-е решение помещает все в a std::vector<std::vector<std::string>>, которое является наиболее эффективным решением.Также std::string - это почти std::vector<std::vector<char>>.

ОП запросил 3-е решение, в котором мы используем 2-е решение, а затем скопируйте std::vector<std::vector<std::string>> в std::vector<std::vector<char>>.

Пожалуйстасм. ниже


#include <iostream>
#include <vector>
#include <algorithm>
#include <iterator>
#include <sstream>

std::istringstream testDataFile(
    R"#(00000
11111
22222
33333
44444
)#");

int main()
{
    // Read complete source file into maze, by simply defining the variable and using the range constructor
    std::vector<std::string> maze{ std::istream_iterator<std::string>(testDataFile), std::istream_iterator<std::string>() };

    // Debug output:  Copy all data to std::cout
    std::copy(maze.begin(), maze.end(), std::ostream_iterator<std::string>(std::cout, "\n"));


    // Edit: Copy into a std::vector<std::vector<char> -------------------------------------------------------
    std::cout << "\n\n\nSolution 3:\n\n";

    // Define the new variable with number of lines from the first maze
    std::vector<std::vector<char>> mazeChar(maze.size());

    // Copy the data from the original maze
    std::transform(
        maze.begin(),               // Source
        maze.end(), 
        mazeChar.begin(),           // Destination
        [](const std::string & s) {
            std::vector<char>vc;    // Copy columns
            std::copy(s.begin(), s.end(), std::back_inserter(vc)); 
            return vc; 
        }
    );

    // Debug Output
    std::for_each(
        mazeChar.begin(),
        mazeChar.end(),
        [](const std::vector<char> & vc) {
            std::copy(vc.begin(), vc.end(), std::ostream_iterator<char>(std::cout));
            std::cout << '\n';
        }
    );

    return 0;
}

Надеюсь, это поможет.,.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...