c ++ ifstream функция и разделители полей - PullRequest
5 голосов
/ 16 ноября 2010

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

A: KT5: 14: стол руководителя:

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

Тогда возникает вопрос, есть ли способ установить разделитель полей с помощью функции ifstream или есть другая стандартная функция ввода-вывода библиотеки, которую я должен использовать?

Спасибо.

Ответы [ 2 ]

5 голосов
/ 16 ноября 2010

@ Стив Таунсенд уже указал на одну возможность.Если вы предпочитаете использовать operator>> вместо std::getline, вы также можете это сделать.istream всегда рассматривает пробел как разделитель.Каждый поток имеет связанный языковой стандарт, и каждый языковой стандарт включает в себя фасет ctype.Этот ctype фасет - это то, что istream использует для определения того, какие входные символы являются пробелами.

В вашем случае вы, очевидно, хотите, чтобы поток обрабатывал только новые строки и двоеточия как "пробел" (то есть, разделители)в то время как фактический символ пробела просто обрабатывается как «нормальный» символ, а не разделитель.

Для этого вы можете создать фасет ctype следующим образом:

struct field_reader: std::ctype<char> {

    field_reader(): std::ctype<char>(get_table()) {}

    static std::ctype_base::mask const* get_table() {
        static std::vector<std::ctype_base::mask> 
            rc(table_size, std::ctype_base::mask());

        rc['\n'] = std::ctype_base::space;
        rc[':'] = std::ctype_base::space;
        return &rc[0];
    }
};

Для использованиядля этого нужно «наполнить» поток локалью, используя этот фасет:

int main() {
    std::stringstream input("A:KT5:14:executive desk:");

    // have the stream use our ctype facet:
    input.imbue(std::locale(std::locale(), new field_reader()));

    // copy fields from the stream to standard output, one per line:
    std::copy(std::istream_iterator<std::string>(input), 
              std::istream_iterator<std::string>(),
              std::ostream_iterator<std::string>(std::cout, "\n"));
    return 0;
}

Однако я первым признаю, что в этом есть некоторые недостатки.Прежде всего, локали и аспекты, как правило, довольно плохо документированы, поэтому большинству программистов на C ++, вероятно, будет трудно это понять (особенно когда вся настоящая работа происходит, так сказать, "под прикрытием").

Другая возможность - использовать Boost Tokenizer .Честно говоря, это небольшая дополнительная работа для использования - вам потребуется что-то вроде чтения строки, а затем ее разбивки по отдельности.В то же время он хорошо документирован, довольно широко известен и достаточно хорошо согласуется с предвзятыми мнениями людей о том, как делать такие вещи, что многим людям, вероятно, будет легче следовать, несмотря на дополнительную сложность.

4 голосов
/ 16 ноября 2010

getline дает вам возможность указать разделитель.Затем вы можете прочитать входные данные из потока в виде последовательности string, разделенной _Delim:

template<class CharType, class Traits, class Allocator>
   basic_istream< CharType, Traits >& getline(
       basic_istream< CharType, Traits >& _Istr,
       basic_string< CharType, Traits, Allocator >& _Str,
       CharType _Delim
   );

Если это данные с однородной структурой, может быть полезно определить структуру, которая будет содержать их, и реализоватьoperator>> для загрузки каждого экземпляра из потока, используя вышеуказанную функцию, внутреннюю для кода оператора.

Если вам нужно обработать несколько строк (так, чтобы символ новой строки был разделителем записей и: разделителем полей), загрузитекаждая строка в свою очередь превращается в stringstream, используя basic_istream::getline, а затем обрабатывает строку в поля, как показано.

...