Читать весь ASCII-файл в C ++ std :: string [duplicate]

typeof(T).Name //would work

Но в зависимости от этого и принятия решений на его основе, вероятно, не очень хорошая идея.

Важным правилом здесь является то, что вы, вероятно, должны использовать FullName, когда это возможно.

Например, в операторах case switch или в блоках if else или в словарных словах.

Имя класса не является идеальной вещью, от которой зависит, поскольку вы потенциально можете иметь одно и то же имя класса в разных Пространства имен. NamespaceA.String и NamespaceB.String вполне возможно ...

546
задан animuson 23 June 2014 в 15:25
поделиться

3 ответа

Обновление: Оказалось, что этот метод, хотя и хорошо следует идиомам STL, на самом деле на удивление неэффективен! Не делайте этого с большими файлами. (См .: http://insanecoding.blogspot.com/2011/11/how-to-read-in-file-in-c.html )

Вы можете сделать итератор streambuf из файл и инициализируйте им строку:

#include <string>
#include <fstream>
#include <streambuf>

std::ifstream t("file.txt");
std::string str((std::istreambuf_iterator<char>(t)),
                 std::istreambuf_iterator<char>());

Не уверен, откуда вы берете синтаксис t.open ("file.txt", "r") . Насколько мне известно, это не метод, который есть в std :: ifstream . Похоже, вы перепутали его с fopen C.

Изменить: Также обратите внимание на дополнительные круглые скобки вокруг первого аргумента конструктора строки. Это очень важно . Они предотвращают проблему, известную как « наиболее неприятный синтаксический анализ », который в этом случае на самом деле не даст вам ошибки компиляции, как обычно, но даст вам интересные (читай: неправильные) результаты.

Следуя замечанию KeithB в комментариях, вот способ сделать это, который выделяет всю память заранее (вместо того, чтобы полагаться на автоматическое перераспределение строкового класса):

#include <string>
#include <fstream>
#include <streambuf>

std::ifstream t("file.txt");
std::string str;

t.seekg(0, std::ios::end);   
str.reserve(t.tellg());
t.seekg(0, std::ios::beg);

str.assign((std::istreambuf_iterator<char>(t)),
            std::istreambuf_iterator<char>());
505
ответ дан 22 November 2019 в 22:13
поделиться

Есть несколько возможностей. Один, который мне нравится, использует в качестве промежуточного звена строковый поток:

std::ifstream t("file.txt");
std::stringstream buffer;
buffer << t.rdbuf();

Теперь содержимое "file.txt" доступно в виде строки как buffer.str () .

Другая возможность (хотя она мне, конечно, тоже не нравится) намного больше похожа на ваш оригинал:

std::ifstream t("file.txt");
t.seekg(0, std::ios::end);
size_t size = t.tellg();
std::string buffer(size, ' ');
t.seekg(0);
t.read(&buffer[0], size); 

Официально это не требуется для работы в соответствии со стандартом C ++ 98 или 03 (строка не требуется для непрерывного хранения данных), но на самом деле он работает со всеми известными реализациями, а для C ++ 11 и более поздних версий требуется непрерывное хранилище, поэтому с ними гарантированно работает.

Что касается того, почему последнее мне тоже не нравится: во-первых, потому что оно длиннее и труднее для чтения. Во-вторых, потому что это требует, чтобы вы инициализировали содержимое строки данными, которые вам не нужны, а затем немедленно записываете эти данные (да, время инициализации обычно тривиально по сравнению с чтением, поэтому, вероятно, это не имеет значения. , но мне это все еще кажется неправильным). В-третьих, в текстовом файле позиция X в файле не обязательно означает, что вы прочитаете X символов, чтобы достичь этой точки - это не обязательно принимать во внимание такие вещи, как переводы конца строки. В реальных системах, которые выполняют такие переводы (например, Windows), переведенная форма короче, чем то, что находится в файле (т. Е. "\ R \ n" в файле становится "\ n" в переведенной строке), поэтому все, что вы сделали зарезервировано немного дополнительного места, которым вы никогда не пользуетесь. Опять же, на самом деле не вызывает серьезных проблем, но все равно кажется немного неправильным.

761
ответ дан 22 November 2019 в 22:13
поделиться

Я не думаю, что вы можете сделать это без явного или неявного цикла, без считывания сначала массива символов (или другого контейнера) и десяти построения строки. Если вам не нужны другие возможности строки, это можно сделать с помощью vector так же, как вы сейчас используете char * .

-6
ответ дан 22 November 2019 в 22:13
поделиться
Другие вопросы по тегам:

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