Компьютерный форум
Правила
Вернуться   Компьютерный форум > Форум программистов > Программирование под Windows > Visual C++
Перезагрузить страницу Использование в работе функции getline
Закрытая тема
 
Опции темы Опции просмотра
  (#1 (permalink)) Старый
Godim Godim вне форума
Member
 
Сообщений: 15
Сказал(а) спасибо: 0
Поблагодарили 0 раз(а) в 0 сообщениях
Регистрация: 01.08.2003
По умолчанию Использование в работе функции getline - 26.08.2003, 02:47

У меня возник вопрос по поводу использования функции
string &getline(istream& ins, string& strVar);
Если читать строку из стандартного потока ввода cin
т.е. getline(cin,str);
то после ввода строки программа ждёт ещё одного нажатия enter
т.е. я ввожу строку, нажимаю enter. Далее программа ожидает
ещё одного нажатия кнопки enter. Можно ввести ещё одну строку,
но после нажатия enter программа продолжает работу, при
этом полностью игнорируя вторую строку. Мне интересно
почему нужно вводить символ конца строки именно два раза,
а не один как должно быть. ОС Windows XP.
Заранее благодарен.
  (#2 (permalink)) Старый
Shunix Shunix вне форума
Member
 
Сообщений: 1,355
Сказал(а) спасибо: 0
Поблагодарили 0 раз(а) в 0 сообщениях
Регистрация: 07.06.2002
По умолчанию 28.08.2003, 20:48

Странно.
Вот тестовый код:
Код:
#include <iostream>
#include <string>

int _tmain(int argc, _TCHAR* argv[])
{
    std::string str;
    std::getline(std::cin, str);

    std::cout << '[' << str << ']';
    return 0;
}
Сценарий работы:
Цитата:
111ENTER
[111]
Т.е. наблюдаем выход (как и должно быть на самом деле!) после первого (и единственного!) ENTER.

А у тебя что за код? Мне кажется, что причина именно в особенностях твоего кода, а не реализации std::getline.
  (#3 (permalink)) Старый
Godim Godim вне форума
Member
 
Сообщений: 15
Сказал(а) спасибо: 0
Поблагодарили 0 раз(а) в 0 сообщениях
Регистрация: 01.08.2003
По умолчанию 29.08.2003, 00:20

Естесственно я так и подумал, но решил проверить.
Написал простейшую вешь:
Код:
#include <iostream>
#include <string>
using namespace std;
int main()
{
    string str;
    char ch;
    getline(cin,str);
    cin.get(sh);       
    cout << str << endl;
    return 0;
}
и она требует два нажатия enter,
при этом полностью игнорируя вторую строку,
если в ней что-то было.
А ещё, если можно, вопрос: в чём преимущество
использования вместо using...
квалифицированных имён
Код:
std::string str; 
std::getline(std::cin, str);
  (#4 (permalink)) Старый
Vladimir the Red Sunny Vladimir the Red Sunny вне форума
Member
 
Сообщений: 4,232
Сказал(а) спасибо: 0
Поблагодарили 0 раз(а) в 0 сообщениях
Регистрация: 15.05.2003
По умолчанию 29.08.2003, 12:36

Shunix:
Я скопировал твой код и скомпилировал, работает в точности как пишет Godim. Нюанс: оно не игнорирует вторую строку, просто ввод строки как бы "отстает" от клавиатуры на один "ентер" - это хорошо видно, если запустить ввод строки в цикле...
  (#5 (permalink)) Старый
Vladimir the Red Sunny Vladimir the Red Sunny вне форума
Member
 
Сообщений: 4,232
Сказал(а) спасибо: 0
Поблагодарили 0 раз(а) в 0 сообщениях
Регистрация: 15.05.2003
По умолчанию 29.08.2003, 12:37

Т.е., если перед вторым нажатием enter ввести еще текст, то он и попадет во вторую строку.
Ads.
  (#6 (permalink)) Старый
Shunix Shunix вне форума
Member
 
Сообщений: 1,355
Сказал(а) спасибо: 0
Поблагодарили 0 раз(а) в 0 сообщениях
Регистрация: 07.06.2002
По умолчанию 29.08.2003, 20:05

Ну, что, народ, Вы думаете, я Вас обманываю?
У меня такое ощущение, что std::getline претерпел определенные изменения, прежде чем попасть в string.h для VC++ 7.0. Именно эту среду я использую для компиляции кода (ОС XP тут не при чем!).
Придется ведь еще и VC++ 6.0. ставить, чтобы разобраться с проблемой (если она, конечно, имеет место быть!).

Ну ладно, с этим разберемся позже - возможно, у них там баг. Может быть, причина в другом.

Что касается квалификатора using - в данном случае применение его вполне оправданно (в твоем коде). В больших проектах использование using может быть не всегда оправдано в связи с тем, что возможно пересечение (и, соответственно, конфлик) имен. Скажем, у тебя есть такой код:
Код:
namespace MyNamespace
{
    void SomeFunc()
    {
    }
}

void SomeFunc()
{
}

using namespace MyNamespace;

int main() 
{ 
    SomeFunc();
    return 0; 
}
Этот код не скомпилируется - из-за неоднозначности. Б. Страуструп не советует просто так "засорять" пространства - а он плохому не научит.
В крайнем случае, можно использовать using локально - по месту. Например, так:
Код:
#include <iostream> 
#include <string> 

int main() 
{ 
    using namespace std;

    string str; 
    getline(cin,str); 
    cout << '[' << str << ']'<< endl; 
    return 0; 
}
И последнее - я не использую в коде cin.get(ch), потому что можно проект запускать при помощи CTRL+F5. Правда, это не всегда бывает удобным - ну, это так, информация к размышлению больше.
  (#7 (permalink)) Старый
Vladimir the Red Sunny Vladimir the Red Sunny вне форума
Member
 
Сообщений: 4,232
Сказал(а) спасибо: 0
Поблагодарили 0 раз(а) в 0 сообщениях
Регистрация: 15.05.2003
По умолчанию 29.08.2003, 20:40

Да, в VC.NET все ок, только в 6-й эта странность....
  (#8 (permalink)) Старый
Shunix Shunix вне форума
Member
 
Сообщений: 1,355
Сказал(а) спасибо: 0
Поблагодарили 0 раз(а) в 0 сообщениях
Регистрация: 07.06.2002
По умолчанию 29.08.2003, 22:44

Забавный факт.
Вот код из getline VC++ 6.0:
Код:
   
            ...     
            for (;; _C = _I.rdbuf()->snextc())
            if (_Tr::eq_int_type(_Tr::eof(), _C))
                {_St |= ios_base::eofbit;
                break; }
            else if (_Tr::eq((_E)_C, _D))
                {_Chg = true;
                _I.rdbuf()->snextc(); // !!! посмотрите сюда !!!
                break; }
            else if (_X.max_size() <= _X.size())
                {_St |= ios_base::failbit;
                break; }
            else
                _X += _Tr::to_char_type(_C), _Chg = true;
            ...
А теперь тотже кусок getline из VC++ 7.0:
Код:
    ...
    for (;; _Meta = _Istr.rdbuf()->snextc())
  if (_Traits::eq_int_type(_Traits::eof(), _Meta))
      {    // end of file, quit
      _State |= ios_base::eofbit;
      break;
      }
  else if (_Traits::eq_int_type(_Meta, _Metadelim))
      {    // got a delimiter, discard it and quit
      _Changed = true;
      _Istr.rdbuf()->sbumpc(); // !!! посмотрите сюда !!!
      break;
      }
  else if (_Str.max_size() <= _Str.size())
      {    // string too large, quit
      _State |= ios_base::failbit;
      break;
      }
  else
      {    // got a character, add it to string
      _Str += _Traits::to_char_type(_Meta);
      _Changed = true;
      }
    ...
Причем эти функции (sbumpc() и snextc()) присутствуют в обеих версиях исходников. Значит, баг был именно в этом (?).

Кстати, вот такой код работает правильно и в 6.0.:
Код:
    ...
    ifstream is("test.txt");
    string str; 

    while (is.good())
    {
  getline(is, str);
  std::cout << '[' << str << ']' << std::endl; 
    }
    ...
Т.е. считываются данные построчно из файла, как и должно быть.

И еще один интересный момент.
Код:
    ...
    string s1;
    getline(cin, s1, ' '); // using <space> as delimeter!
    cout << "You entered: " << s1 << endl;
    ...
Этот пример из MSDN работает правильно. Т.е. при вводе что-нибудь в виде "111 222 333". Мы получим строку "111".
  (#9 (permalink)) Старый
Godim Godim вне форума
Member
 
Сообщений: 15
Сказал(а) спасибо: 0
Поблагодарили 0 раз(а) в 0 сообщениях
Регистрация: 01.08.2003
По умолчанию 30.08.2003, 17:45

Благодарность и respect всем участникам форума !
Большое спасибо за помошь и участие
в разрешении этого маленького нюанса !
Я думаю, что с этим всё понятно:
в функции небольшой глюк в VC++ 6.0 при вводе
из cin (она нормально работает при чтении из файла,
как было показано выше);
у getline так же есть третий аргумент по-умолчанию delimiter='n',
выступающий в роли ограничителя, до которого считывается строка.

По поводу using тоже всё ясно. Я ещё знаю, что
можно предоставить доступ только к конкретной функции
из пространства: using имя_пространства::имя_функции;
правда, я не вижу этому особо большое практическое применение.

Думаю, что если всё ясно, то тему нужно закрыть.
Ads
Закрытая тема

Опции темы
Опции просмотра

Ваши права в разделе
Вы не можете создавать новые темы
Вы не можете отвечать в темах
Вы не можете прикреплять вложения
Вы не можете редактировать свои сообщения

BB коды Вкл.
Смайлы Вкл.
[IMG] код Вкл.
HTML код Выкл.
Trackbacks are Вкл.
Pingbacks are Вкл.
Refbacks are Выкл.


Похожие темы
Тема Автор Раздел Ответов Последнее сообщение
Использование ifstream from при работе с большими файлами GenCuro Visual C++ 3 20.11.2008 13:22
Использование glut при работе с программой на С++ winamp C++ Builder 6 03.11.2008 20:56
Использование в работе команды Shutdown 1tristan Вопросы начинающих программистов 1 01.08.2008 18:17
Использование ListImage при работе с графикой zagi Visual C++ 0 27.04.2008 23:34
Использование ADO при работе с midas.dll BaRaDeD C++ Builder 6 24.07.2006 19:54
Использование new в работе на С++ kirill_fox Visual C++ 2 10.10.2005 02:06
Классы и их использование в работе sunrize С/С++ 7 19.05.2005 18:22
Использование метода Next при работе с базами данных pa3ot C++ Builder 1 24.03.2005 17:35
Тонкости в работе функции getchar Beamy С/С++ 2 22.03.2005 23:55
Использование функций типа MoveFile, MoveFileEx, RemoveDirectoryпри работе с файлами Mordobil C++ Builder 2 23.09.2004 14:09
Использование image в работе сохранение в базе данных air MSSQL Server 0 05.04.2004 15:37



Powered by vBulletin® Version 3.8.7
Copyright ©2000 - 2018, Jelsoft Enterprises Ltd.
Нardforum.ru - компьютерный форум и программирование, форум программистов