Вопрос по c++ – Как я могу использовать разделители не по умолчанию при чтении текстового файла с std :: fstream?

16

В моем коде C ++ я хочу читать из текстового файла (* .txt) и маркировать каждую запись. Более конкретно, я хочу иметь возможность читать отдельные слова из файла, такие как «формат», «стек», «Jason», «европа»,etc.

Я решил использоватьfstream чтобы выполнить эту задачу, и я не знаю, как установить разделитель на те, которые я хочу использовать (пробел,\nа также дефисы и даже апострофы, как в «Макдонале» (s). Я вычислил пространство и\n являются разделителями по умолчанию, а дефисы - нет, но я хочу рассматривать их как разделители, чтобы при синтаксическом анализе файла я получал слова в формате «бла-бла-хх животного - кошка»; как просто «бла», «бла», «ххх», «животное», «кошка».

То есть я хочу иметь возможность получить две строки из "переполнения стека", "вы", "etc, и все еще быть в состоянии поддерживать\n и пробел в качестве разделителей одновременно.

Попался! Я отредактировал ваш вопрос, чтобы прояснить ситуацию. Johnsyweb
Я не пытаюсь отфильтровать их; Я пытаюсь читать животное и кошку как два отдельных слова. FrozenLand
GetLine (поток, переменная, разделитель); Trevor Hickey
Вы хотите отфильтровать "животное - кошка" потому что он содержит дефисы? Это не похоже на знак для меня. Johnsyweb

Ваш Ответ

2   ответа
19

использует локаль, чтобы сказать, какие символы являются пробелами. Локаль, в свою очередь, включает в себя ctypefacet это классифицирует типы символов. Такая грань может выглядеть примерно так:

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

class my_ctype : public
std::ctype<char>
{
    mask my_table[table_size];
public:
    my_ctype(size_t refs = 0)  
        : std::ctype<char>(&my_table[0], false, refs)
    {
        std::copy_n(classic_table(), table_size, my_table);
        my_table['-'] = (mask)space;
        my_table['\''] = (mask)space;
    }
};

И небольшая тестовая программа, чтобы показать, что она работает:

int main() {
    std::istringstream input("This is some input from McDonald's and Burger-King.");
    std::locale x(std::locale::classic(), new my_ctype);
    input.imbue(x);

    std::copy(std::istream_iterator<std::string>(input),
        std::istream_iterator<std::string>(),
        std::ostream_iterator<std::string>(std::cout, "\n"));

    return 0;
}

Результат:

This
is
some
input
from
McDonald
s
and
Burger
King.

istream_iterator<string> использования>> читать отдельные строки из потока, поэтому, если вы используете их напрямую, вы должны получить те же результаты. Части, которые вам нужно включить, - это создание локали и использованиеimbue чтобы поток использовал эту локаль.

Error: User Rate Limit ExceededSee it here!
Error: User Rate Limit Exceeded FrozenLand
Error: User Rate Limit Exceededstd::copy(classic_table(), classic_table()+table_size, my_table);Error: User Rate Limit Exceededstd::copy_n.
Error: User Rate Limit Exceededstd::copy_n()Error: User Rate Limit Exceededstd::copy(classic_table(), classic_table() + table_size, my_table);Error: User Rate Limit Exceeded
Error: User Rate Limit ExceededimbueError: User Rate Limit Exceededyour_stream >> your_stringError: User Rate Limit Exceeded,Error: User Rate Limit Exceeded'Error: User Rate Limit Exceeded
1

istream::getline(char* buffer, steamsize maxchars, char delim)

хотя это поддерживает только один разделитель. Для дальнейшего разделения строк на разных разделителях вы можете использовать

char* strtok(char* inString, const char* delims)  

который занимает несколько разделителей. Когда вы используете strtok, вам нужно только передать ему адрес вашего буфера в первый раз - после этого просто передайте нуль, и он выдаст вам следующий токен из последнего, который он вам дал, вернув нулевой указатель, когда нет Больше.

РЕДАКТИРОВАТЬ: конкретная реализация будет что-то вроде

char buffer[120]; //this size is dependent on what you expect the file to contain
while (!myIstream.eofbit) //I may have forgotten the exact syntax of the end bit
{
    myIstream.getline(buffer, 120); //using default delimiter of \n
    char* tokBuffer;
    tokBuffer = strtok(buffer, "'- ");
    while (tokBuffer != null) {
        cout << "token is: " << tokBuffer << "\n";
        tokBuffer = strtok(null, "'- "); //I don't need to pass in the buffer again because it remembers the first time I called it
    }
}
Error: User Rate Limit Exceeded FrozenLand
Error: User Rate Limit Exceeded
Error: User Rate Limit Exceeded FrozenLand
Error: User Rate Limit Exceeded

Похожие вопросы