Разве getline () не извлекает разделитель? - PullRequest
0 голосов
/ 09 ноября 2018

Итак, я взял несколько целых чисел, а затем взял несколько предложений.

Этот код отлично работает:

#include<bits/stdc++.h>
using namespace std;
main(){
    int c,b,n,i;string s;
    cin>>n>>b>>c;
    for(i=0;i<n;i++){
        cin>>ws;
        getline(cin,s,'\n');
        cout<<s; 
     }
    }

Пример:

3 3 3
This is weird
This is weirdDefinitely makes
Definitely makesNo sense
No sense

Однако, когда я пытаюсь опустить cin >> w внутри forloop, он не работает должным образом, например, этот сегмент кода,

#include<bits/stdc++.h>
using namespace std;
main(){
    int c,b,n,i;string s;
    cin>>n>>b>>c;
    for(i=0;i<n;i++){
            getline(cin,s,'\n');
            cout<<s;
    }
}

Пример:

3 3 3
This is weird
This is weirdDefinitely makes
Definitely makes

.. и заканчивается там вместо того, чтобы брать все три входа. Это почему? cin >> ws извлекает все пробелы из входных данных, но не getline () тоже делает это? Так почему же он не работает должным образом, когда я опускаю cin >> ws в forloop?

Ответы [ 4 ]

0 голосов
/ 09 ноября 2018

Когда вы используете cin >>, он не удаляет пробелы после ввода.Это означает, что символ новой строки, который завершил первые 3 ввода, все еще находится в буфере, ожидая, что его прочитает первый getline.Поскольку до новой строки ничего нет, первая getline доставила пустую строку.Ваш вывод должен был включать новую строку, чтобы вы могли видеть пустую строку, тогда это имело бы смысл.

Первоначально код, который вы разместили, показывал cin >> ws непосредственно перед циклом for, который исключил быэта проблема.

0 голосов
/ 09 ноября 2018

Разделителем по умолчанию для getline () является '\ n', поэтому нет необходимости включать его в вызов getline, однако это не должно изменять функциональность.

См., Например, То же, что и getline (input, str, input.widen ('\ n')), то есть разделителем по умолчанию является символ конца строки.

Изменение форматирования от целочисленного ввода к вводу getline () оставляет некоторое количество пробела (endl) после целого числа, как объяснено @ DietmarKühl.

Вы можете изменить вызов getline (), чтобы исключить разделитель, на

getline(cin,s);

, что заставит getline () использовать '\ n' в качестве разделителя по умолчанию.

Я изменил переменную 'n' для подсчета и удалил другие целые числа, чтобы сделать код немного проще для чтения:

#include <iostream>

int main()
{
    int i;  // index
    int count;  // number of strings to accept
    std::string str;

    std::cout << "Input the number of strings you would like me to process: " << std::endl;
    std::cin >> count;

    if (std::cin >> count >> std::ws) {
        for (i = 0; i < count; i++) {
            if (getline(std::cin, str)) {
                std::cout << "i=" << i << ":'" << str << "'\n";
            }
        }
    }
}
0 голосов
/ 09 ноября 2018

Cin не извлекает все пробелы, он просто получает первое слово до первого пробела. Это как получить getline с пробелом (не совсем, но близко к).

Getline берет всю строку и имеет разделитель по умолчанию '\ n', как упомянуто выше.

Ex:

string a = "Stack Overflow is awesome";

может дать вам стек, а getline даст вам все на этой линии

0 голосов
/ 09 ноября 2018

std::getline() извлекает символы, пока не будет извлечен первый символ разделителя (по умолчанию '\ n'). Разделитель не сохраняется в результате, но он извлекается. Он не извлекает пробел в общем или несколько символов-разделителей.

В качестве отступления: всегда проверьте, работает ли ввод после попытки прочитать значение.

В напечатанном примере проблема заключается в том, что после форматированного ввода, то есть с использованием оператора >>, пробелы не извлекаются. То есть, первые вызовы std::getline() извлекают пустую строку, оканчивающуюся начальной новой строкой. Обычно является необходимым для извлечения конечных пробелов при переключении между форматированным и неформатированным вводом / выводом. То есть вы хотели бы код вроде

if (cin>>n>>b>>c >> std::ws) {
    for(i=0;i<n;i++){
        if (getline(cin,s,'\n')) {
            cout << "i=" << i << ":'" << s << "'\n";
        }
    }
}

Я не могу рекомендовать операции ввода без добавления проверки на успешность. Выходные данные изменены, чтобы было легче увидеть происходящее: попробуйте код с / без этого конкретного std::endl, чтобы увидеть, что происходит.

...