Panel użytkownika
Nazwa użytkownika:
Hasło:
Nie masz jeszcze konta?

funkcje get() i getline()

Ostatnio zmodyfikowano 2011-02-27 09:25
Autor Wiadomość
neke
Temat założony przez niniejszego użytkownika
funkcje get() i getline()
» 2011-02-26 15:37:44
Kolejny dzień przerabiania kursu- kolejne problemy :)

Po lekturze rozdziału o ciągi znaków- łańcuchy zrodziły się we mnie pewne wątpliwości odnośnie samego strumienia cin lecz zanim o tym, to celem usystematyzowania informacji z kursu (proszę mnie poprawić w razie złej interpretacji):

1. get() oraz getline() są metodami strumienia cin i znajdują zastosowanie tylko do tablic- zmienna musi być tablicą.

2. metoda get() oraz getline() służą do wczytania całego wiersza znaków, włącznie ze znakami białymi.

3. metoda get() nie przechowuje znaku końca linii (ENTER) lecz go zwraca, w pierwszej kolejności natychmiast przy ponownym jej użyciu. Dlatego też w poniższym kodzie nie jest możliwe podanie swojego nazwiska (w pierwszej kolejności ładowany jest z pamięci strumienia cin znak "ENTER", który kończy zarazem wykonywanie strumienia cin, odpowiedzialnego za podanie nazwiska.
C/C++
#include <iostream>
#include <conio.h>
int main()
{
    using namespace std;
    const short rozmiar = 50;
    char ciag_znak[ rozmiar ];
    char lancuch[ rozmiar ];
   
    cout << "Podaj swoje 2 imiona ";
   
    cin.get( ciag_znak, rozmiar );
    cout << "Podaj swoje nazwisko ";
   
    cin.get( lancuch, rozmiar );
    cout << endl << endl;
   
    cout << ciag_znak << endl;
    cout << lancuch << endl;
   
    return 0;
}

4. metoda getline() również zwraca (w pierwszej kolejności) z pamięci cin znak końca strony. Usuwa ona ponad to znak końca linii z podanego przed nią łańcucha znaków. Dlatego też w poniższym kodzie jest możliwe podanie swojego nazwiska.
C/C++
#include <iostream>
#include <conio.h>
int main()
{
    using namespace std;
    const short rozmiar = 50;
    char ciag_znak[ rozmiar ];
    char lancuch[ rozmiar ];
   
    cout << "Podaj swoje 2 imiona ";
   
    cin.getline( ciag_znak, rozmiar );
    cout << "Podaj swoje nazwisko ";
   
    cin.getline( lancuch, rozmiar );
    cout << endl << endl;
   
    cout << ciag_znak << endl;
    cout << lancuch << endl;
   
    return 0;
}


Problem pojawia się przy analizie poniższego kodu:
C/C++
//miks liczby i ciagi--------------------------
#include <iostream>
#include <conio.h>
int main()
{
    using namespace std;
    const short rozmiar = 50;
    char lancuch[ rozmiar ];
    int rok;
   
    cout << "W ktorym roku dostales komputer?"
    << endl;
    cin >> rok;
    cout << "Jak sie nazywala ulubiona gra?\n";
    cin.getline( lancuch, rozmiar );
   
    cout << "Komputer dostales w " << rok
    << " roku." << endl;
    cout << "Ulubiona gra to " << lancuch
    << "." << endl;
   
    getch();
    return( 0 );
}

Wynika bowiem z tego, że strumień cin zapamiętuje znak końca linii natomiast go nie zwraca przy ponownym użyciu tegoż strumienia. Gdyby go zwracał to niemożliwe było by podanie nazwiska w poniższym przykładzie.
C/C++
//miks liczby i ciagi--------------------------
#include <iostream>
#include <conio.h>
int main()
{
    using namespace std;
    char a;
    char b;
   
    cout << "Podaj imie"
    << endl;
    cin >> a;
    cout << "Podaj nazwisko";
    cin >> b;
   
    cout << "Twoje imie to " << a << endl;
    cout << "Twoje nazwisko to " << b << endl;
   
    getch();
    return( 0 );
}
 
Znak końca linii jest natomiast zwracany przez metodę get() lub getline(), gdy wystąpi ona po wcześniej wprowadzonym strumieniu cin.
C/C++
cout << "W ktorym roku dostales komputer?"
<< endl;
cin >> rok;
cout << "Jak sie nazywala ulubiona gra?\n";
cin.getline( lancuch, rozmiar );

Wynika więc z tego ze get() nie zapamiętuje żadnego znaku końca lini, gdyż jest on zapamiętywany przez cin. Get() jak i getline() służą więc tylko do tego, żeby wczytać ciąg znaków z uwzględnieniem znaków białych (np. spacja), co jest nie możliwe przy zastosowaniu samego cin. Getline () ponad to usuwa z cin wprowadzony znak końca lini.

I tu się pojawia problem, bowiem jeżeli getline () usuwa znak końca lini ze strumienia cin to dlaczego w powyższym kodzie tego nie robi? Czy to dlatego, że w pierwszej kolejności getline() zwraca niesiony w pamięci cin znak końca strony a dopiero następnie usuwa ten znak ze strumienia stojącego za getline()?
P-28630
DejaVu
» 2011-02-26 18:42:22
Dużo za długi wywód żeby go całego czytać. W przykładzie, który wkleiłeś wczytujesz jeden znak, a nie ciąg znaków.
P-28634
malan
» 2011-02-26 22:27:10
1.
istream::get
 oraz
istream::getline
 są metodami klasy
std::istream
.
std::cin
 to po prostu
extern istream cin;
(...)znajdują zastosowanie tylko do tablic- zmienna musi być tablicą
Niekoniecznie.
C/C++
#include <iostream>

int main()
{
    char c;
    std::cin.get( c );
    std::cout << "Wcisnales: " << c;
}
Po dokładny opis zapraszam na cplusplus.com (istream::get).

2. Metodą
istream::get
 wczytasz cały wiersz, aczkolwiek do tego zadania lepiej użyć metody do tego przeznaczonej, czyli
istream::getline
.

(...)włącznie ze znakami białymi.
Zależy co masz na myśli...

3.
(...)metoda get() nie przechowuje znaku końca linii (ENTER) lecz go zwraca, w pierwszej kolejności natychmiast przy ponownym jej użyciu. Dlatego też w poniższym kodzie nie jest możliwe podanie swojego nazwiska (w pierwszej kolejności ładowany jest z pamięci strumienia cin znak "ENTER", który kończy zarazem wykonywanie strumienia cin, odpowiedzialnego za podanie nazwiska.
Nie.

Znak nowej linii przechowywany jest w buforze.
istream::get
 kończy pracę kiedy pojawi się tam (domyślnie) znak nowej linii. Przy drugim wywołaniu
istream::get
 metoda odczytuje dane z bufora- widząc, że zalega tam
'\n'
 kończy pracę.

Poprawny kod:
C/C++
#include <iostream>

int main()
{
    const int SIZE = 50;
   
    char names[ SIZE ];
    char sername[ SIZE ];
   
    std::cout << "Podaj swoje 2 imiona: ";
    std::cin.get( names, SIZE );
   
    std::cin.sync();
   
    std::cout << "Podaj swoje nazwisko: ";
    std::cin.get( sername, SIZE );
   
    std::cout << "Twoje imiona: " << names << std::endl;
    std::cout << "Twoje nazwisko: " << sername;
   
    // Zatrzymanie programu...
    std::cin.sync();
    std::cin.get();
}

4.
metoda getline() również zwraca (w pierwszej kolejności) z pamięci cin znak końca strony. Usuwa ona ponad to znak końca linii z podanego przed nią łańcucha znaków. Dlatego też w poniższym kodzie jest możliwe podanie swojego nazwiska.
Dokładnie mówiąc:
If the delimiter is found, it is extracted and discarded, i.e. it is not stored and the next input operation will begin after it. If you don't want this character to be extracted, you can use member get instead.

Problem pojawia się przy analizie poniższego kodu:(...)
Patrz punkt 3.

Co do Twojego czwartego przykładu-
istream::operator >>
 jest na tyle mądry, że wie, kiedy ma pominąć biały znak, a kiedy nie, bo ma to ustawione - domyślnie pomija wszystkie białe znaki przed wczytaniem czegokolwiek. Czyli, kiedy wywołujesz
istream::operator >>
 drugi raz, on wie, że ma pominąć znak nowej linii zalegający w buforze pozostawiony tam dzięki poprzedniemu wywołaniu.

Mam nadzieję, że trochę pomogłem, odpowiedziałem na Twoje pytania i rozwiałem Twoje wątpliwości :)
P-28637
neke
Temat założony przez niniejszego użytkownika
» 2011-02-27 09:25:53
Dzięki serdeczne za klarowną odpowiedź. Sądzę, że popełnionym przez Ciebie wytłumaczeniem rozwiałeś nie tylko moje wątpliwości co do sposobu działania get, getline i iostreama. Opisując ten problem w Googlach z łatwością można stwierdzić, iż moje wątpliwości podziela wiele innych osób. Teraz każdy będzie mógł zadość uczynić swojej ciekawości :)
P-28646
« 1 »
  Strona 1 z 1