wejście std :: cin ze spacjami?


144
#include <string>

std::string input;
std::cin >> input;

Użytkownik chce wpisać „Hello World”. Ale cinzawodzi w odstępie między dwoma słowami. Jak mogę cinwziąć w całości Hello World?

Właściwie robię to ze strukturami i cin.getlinewydaje się, że nie działa. Oto mój kod:

struct cd
{
    std::string CDTitle[50];
    std::string Artist[50];
    int number_of_songs[50];
};

std::cin.getline(library.number_of_songs[libNumber], 250);

To powoduje błąd. Jakieś pomysły?


27
Nie powinieneś edytować swoich pytań, aby zadawać takie nowe pytania. Powodem jest to, że ludzie już udzielili odpowiedzi na twoje pierwotne pytanie, a teraz te odpowiedzi wydają się wyrwać z kontekstu. Jeśli na Twoje oryginalne pytanie została już udzielona odpowiedź, zacznij nowe pytanie, aby uniknąć nieporozumień.
Pete,

Jest to widoczne po krótkim badaniu, ale czy mógłbyś dodać deklarację dla zmiennej library, aby było jasne, że jest tego typucd
chandsie

przepraszam chłopaki, zrobiono to w pośpiechu, opublikuję to ponownie.
cytryna

1
Jeśli zamierzasz go ponownie opublikować w celu zastąpienia, oflaguj pytanie do usunięcia przez mod.
Wyścigi lekkości na orbicie

2
W swojej aktualizacji próbujesz getlineotworzyć plik int. Oczywiście to zawodzi.
Ben Voigt

Odpowiedzi:


102

Musisz użyć cin.getline():

char input[100];
cin.getline(input,sizeof(input));

7
@Kevin Meh, zdarza się. C ++ nie jest tak intuicyjny, jak byśmy chcieli.
Pete

61
Ew; po co używać char-buffers? Jest rok 2011.
Wyścigi lekkości na orbicie

3
A dlaczego nie używać cin.getline(input, sizeof(input));? Nie powinieneś też sprawdzać statusu zwrotu?
Jonathan Leffler

2
@JonathanLeffler W czasie, gdy to powstawało, była to odpowiedź, jaką miałem na pierwotnie zadane pytanie (spójrz na pierwszy komentarz dotyczący rzeczywistego pytania, a zobaczysz, że kontekst zmienił się w wyniku edycji przez OP). Tak czy inaczej, jeśli uważasz, że odpowiedź jest okropna, odrzuć ją. Przyznaję, że może to nie jest „najlepsze” rozwiązanie, ale nie mniej. Zamiast pytać, dlaczego czegoś nie użyłem, możesz nam powiedzieć wszystkim, dlaczego powinniśmy to zrobić po swojemu.
Pete

7
Twoja odpowiedź nie jest straszna i nie wymaga odrzucenia. Myślę, że dwie małe zmiany by to poprawiły. Zmiana 1 byłaby używana sizeof(input)zamiast 100 w wezwaniu do cin.getline(); oznaczałoby to, że możesz zmienić rozmiar bufora wejściowego i zmienić tylko jedną linię zamiast dwóch. Zmiana 2 polegałaby na przetestowaniu wyniku cin.getline()za pomocą, na przykład, if (!cin.getline(input, sizeof(input))) { ...handle EOF or error... }lub czegoś podobnego, aby przypomnieć OP, że w szczególności operacje wejściowe są podatne na nieoczekiwane zachowanie. Inne odpowiedzi też tego potrzebują.
Jonathan Leffler

215

To nie „zawodzi”; po prostu przestaje czytać. Widzi leksykalny token jako „ciąg znaków”.

Zastosowanie std::getline:

int main()
{
   std::string name, title;

   std::cout << "Enter your name: ";
   std::getline(std::cin, name);

   std::cout << "Enter your favourite movie: ";
   std::getline(std::cin, title);

   std::cout << name << "'s favourite movie is " << title;
}

Zauważ, że to nie to samo std::istream::getline, co, które działa z charbuforami w stylu C, a nie z std::strings.

Aktualizacja

Twoje zredagowane pytanie ma niewielkie podobieństwo do oryginału.

Próbowałeś getlinewejść do intbufora, a nie do bufora łańcuchowego lub znakowego. Operacje formatowania strumieni działają tylko z operator<<i operator>>. Albo użyj jednego z nich (i odpowiednio dostosuj dla wprowadzania wielowyrazowego) lub użyj getlinei leksykalnie przekonwertuj na intpóźniej.


2
Ta odpowiedź podoba mi się znacznie bardziej niż zaakceptowana, ponieważ nie muszę określać długości znaków.
TheWanderer,

1
@TheWanderer Rzeczywiście, to znacząca korzyść.
Wyścigi lekkości na orbicie,

Pamiętaj, aby dołączyć sstream: #include <sstream>
GilbertS

@LightnessRacesinOrbit, czy możesz pomóc? To daje mi dodatkowy znak nowej linii bez powodu podczas drukowania mojego wyniku.
Anshuman Kumar

@AnshumanKumar Myślę, że getlinemoże zawierać kończący znak nowej linii w zwracanym ciągu. Jeśli tak, to do Ciebie należy usunięcie go.
Mark Ransom

31

Biblioteka standardowa udostępnia funkcję wejściową o nazwie ws, która zużywa białe znaki ze strumienia wejściowego. Możesz go używać w ten sposób:

std::string s;
std::getline(std::cin >> std::ws, s);

4
Myślę, że to jak dotąd najlepsza odpowiedź. Mogę to połączyć z powyższym std :: cin >>.
Andra

1
Jak dotąd najlepsza odpowiedź. Podczas korzystania std::getline(std::cin, s)dostałbym bardzo niechlujny i powiedziałbym, że przerwane wejście podczas oczekiwania na wejścia w pętli while/ for. Ta opcja rozwiązała mój problem!
omerowitz

Uwzględnij sstream: #include <sstream>
GilbertS

24

Posługiwać się :

getline(cin, input);

funkcję można znaleźć w

#include <string>

2
+1 To jedyna odpowiedź, która faktycznie zadziałała dla mnie. Reszta odpowiedzi mówi, że używam cin.getline (), ale to spowodowało błąd, mówiąc, że funkcja nie istnieje.
blembo

7
@blembo: Naprawdę? Ponieważ moja odpowiedź, opublikowana ponad trzy lata przed tą, mówi dokładnie to samo (w przeciwieństwie do tego, co twierdzisz).
Wyścigi lekkości na orbicie

@blembo: A jeśli cin.getlinenie istnieje w twoim systemie, zrobiłeś coś bardzo złego. Najprawdopodobniej przekazałeś złe argumenty. Lepiej nie winić innych za swoje błędy ...
Wyścigi lekkości na orbicie

13

Chcesz użyć funkcji .getline w cin.

#include <iostream>
using namespace std;

int main () {
  char name[256], title[256];

  cout << "Enter your name: ";
  cin.getline (name,256);

  cout << "Enter your favourite movie: ";
  cin.getline (title,256);

  cout << name << "'s favourite movie is " << title;

  return 0;
}

Wziąłem przykład stąd . Sprawdź to, aby uzyskać więcej informacji i przykładów.


12
W rzeczywistości rzadko chcesz używać member- getline. To przestarzałe. getlineZamiast tego użyj bezpłatnego , którego można używać z std::string. [BTW, cplusplus.com nie jest zalecanym źródłem]
Lightness Races in Orbit

1
@Tomalak Dlaczego cplusplus.com nie jest polecany? Używam go cały czas: P
lemon,

6
@KevinDuke: Samouczki mogą być mylące i niedokładne, a odniesienie zawiera wiele błędów. To są dobre zasoby.
Wyścigi lekkości na orbicie

1
@NickSweeting: Tak; użyj tego zamiast tego .
Wyścigi lekkości na orbicie

1
W przypadku linków do dokumentacji, cppreference.com jest skutecznym zamiennikiem dla cplusplus.com (obie są nieoficjalnymi parafrazami)
Ben Voigt

4

DROGA C

Możesz użyć getsfunkcji znajdującej się w cstdio (stdio.h in c):

#include<cstdio>
int main(){

char name[256];
gets(name); // for input
puts(name);// for printing 
}

SPOSÓB C ++

gets został usunięty w C ++ 11.

[Zalecane]: Możesz użyć getline (cin, nazwa), która znajduje się w, string.h lub cin.getline (nazwa, 256), która jest iostreamsama w sobie.

#include<iostream>
#include<string>
using namespace std;
int main(){

char name1[256];
string name2;
cin.getline(name1,256); // for input
getline(cin,name2); // for input
cout<<name1<<"\n"<<name2;// for printing
}

10
Bardzo zła rada, getsnie można jej bezpiecznie używać. Został nawet całkowicie usunięty w C11.
Mat

1

Wolę użyć następującej metody, aby uzyskać dane wejściowe:

#include <iostream>
#include <string>

using namespace std;

int main(void) {
    string name;

    cout << "Hello, Input your name please: ";
    getline(cin, name);

    return 0;
}

W rzeczywistości jest bardzo łatwy w użyciu, zamiast definiować całkowitą długość tablicy dla ciągu zawierającego znak spacji.

Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.