2015-08-28 4 views
-2

Как я также прочитал новую строку с помощью оператора C++ >>?Чтение новой строки с использованием потока C++

ifstream input("doc.txt".c_str()); 
vector<string> contents; 
while (input >> word) { 
    contents.push_back(word); 
} 

Для файла:

hello 
world 
C++ is the best tool 

должен вернуть

hello 
\n 
world 
\n 
C++ 
is 
the 
best 
tool 

P/S: это уменьшенная проблема с побольше. Как я разбираю файл, это приводит к этой проблеме.

+0

Является ли это проблемой XY? – emlai

+2

Ваш выход не соответствует вашему входу. Существует новая строка между приветствием и миром в файле, как вы его показывали. – NathanOliver

+2

перегрузка строки 'operator >>' [не различает новую строку и другие пробелы] (http://en.cppreference.com/w/cpp/string/basic_string/operator_ltltgtgt), если не существует языковой стандарт, который делает это , но 'getline' делает. В любом случае печать '\ n', а не фактическая новая строка должна быть специальным случаем. Рассматривали ли вы получение каждой строки с getline, преобразовывая полученную строку в 'istringstream', вызывая' operator >> 'на этом, а затем печатаете' \ n' в своей собственной строке, когда поток строк полностью разбирается? – jaggedSpire

ответ

2

Вы можете использовать getline и push_back"\n" себя, как было упомянуто jaggedSpire:

ifstream input("doc.txt"); 
vector<string> contents; 
for (string line; getline(input, line);) { 
    istringstream str(line); 
    for (string word; str >> word;) { 
     contents.push_back(word); 
    } 
    contents.push_back("\n"); 
} 
-1

Во-первых, вы уже умирала, как константный символ * в конструкторе потока. Во-вторых, считыватель потоков читает символы не пробелы, так он знает, когда нужно перерезать строки.

Обычно мы читаем двоичный файл, есть символ, известный читателю, который рассказывает, когда мы пропускаем строку знаменитого \ n, но его отличия от платформ (Win, Unix).

0

Попробуйте использовать getline (http://www.cplusplus.com/reference/istream/istream/getline/). getline будет проходить через каждую строку (пока не увидит новый символ строки) и вернет 0, когда достигнет конца файла. Поэтому после каждого вызова getline и печати печатайте \ n. Вот пример вашей проблемы, randFile - это случайный файл с текстом в нем.

1 #include <iostream> 
    2 #include <fstream> 
    3 int main(){ 
    4 
    5 std::ifstream myFile("randFile", std::ifstream::in); 
    6 char s[BUFSIZ]; 
    7 
    8 while(myFile.getline(s, BUFSIZ)){ 
    9  std::cout << s << std::endl; 
10  std::cout << "\\n"<< std::endl; 
11 } 
12 
13 return 0; 
14 } 
1

Если вы хотите использовать специально operator>> и вы технически не должны использовать строки в частности, вы можете просто сделать пользовательский класс с поведением вы хотите, когда он прочитал в из istream. Это может быть (в основном) оболочка для строки, с пользовательским поведением при чтении начальных пробелов.

class StringAndNewline{ 
    std::string str_; 
    friend std::istream& operator>>(std::istream& in, StringAndNewline& str); 
public: 
    StringAndNewline() : str_(){} 
    StringAndNewline(std::string str) : str_(str){} 

    const std::string& str() const noexcept {return str_;} 
    std::string release() {return std::move(str_);} 
}; 

Строка чтения в операторе автоматически игнорирует все preceding whitespace к последовательности непробельных символов, как это определено в настоящей местности. Это поведение, которое вы хотите изменить, и, как оказалось, это легко сделать.

Устранение первоначального пробела обычно выполняется с помощью так называемого сторожевого объекта, который также проверяет, что поток действителен, и устанавливает failbit потока, если он находится в конце файла. Хотя его поведение по умолчанию заключается в том, чтобы потреблять пробелы, пока не встретится с символом без пробелов, он управляется флагом в его конструкторе, поэтому мы можем использовать эту очень красивую инкапсулированную проверку действительности потока, которую она предлагает.

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

Таким образом, окончательное чтение в структуру нашего пользовательского класса пользовательские operator>> будут выглядеть примерно так:

  • сделать непробельную еду сторожевой
  • проверки часового, возвращая отказавший поток, если он недействителен
  • дело с пробелами
  • считываются данные, завернутые строки
  • возвращение потока

Поскольку мы имеем дело только с символами '\ n' в нашем пробеле, это тоже просто: просто зацикливайтесь, пока поток действителен (если у него заканчивается пробел до достижения любого из наших условий, он устанавливает failbit, как мы хотел бы) и выйти из цикла, если одно из двух условий - нетто: мы получаем символ новой строки или получаем символ без пробелов. Опять же, приятно просто:

std::istream& operator>>(std::istream& in, StringAndNewline& str){ 
    std::istream::sentry sentry{in, true}; // make a sentry that doesn't eat whitespace 
    if(!sentry){return in;} // check the sentry 
    std::locale 
     presentLocale{}; // get the present locale 
    char presentChar; 
    while(in.get(presentChar)){ // while the stream is valid 
     if(presentChar == '\n'){ // if we get a newline 
      str.str_ = "\\n"; // set the string to an escaped newline 
      break; // exit the loop 
     } 
     // if we get a non-whitespace character 
     else if(!std::isspace(presentChar, presentLocale)){ 
      in.unget(); // replace the character in the stream 
      in >> str.str_; // take advantage of the existing string operator 
      break; // done with loop 
     } 
    } 
    return in; // return the istream, whatever state it might be in 
} 

Как только это будет сделано, мы создали оператора ostream для удобства печати:

std::ostream& operator<<(std::ostream& out, const StringAndNewline& str){ 
    return out << str.str(); 
} 

и протестировать наш код:

int main(){ 
    std::istringstream file(
     "hello\n" 
     "world\n" 
     "C++ is the best tool" 
    ); 
    StringAndNewline 
     wordOrNewline; 
    while(file >> wordOrNewline){ 
     std::cout << wordOrNewline << '\n'; 
    } 
} 

который печатает этот :

hello 
\n 
world 
\n 
C++ 
is 
the 
best 
tool 

только что как мы и хотели! Live on Coliru

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

Смежные вопросы