Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Issue with C++ and cin.getline

I'm learning struct in C++ and I don't know how to make it not to jump over the first question.

If I'm using char in the struct it will only copy me the first word, if I'm trying to use string it jumps over the first question (ignoring it).

Could you please guide me?

Later edit: I use Microsoft Visual C++ 2010 express edition, and is there a difference between std::getline and cin.getline?

#include <iostream>
#include <conio.h>
#include <string>


using namespace std;


struct melodie{

char artist[50];
char titlu[50];
int an;
int lungime;

};

void main(){
int repetam;
double rezultat;
cout<<"Cate melodii veti introduce: ";
cin>>repetam;
melodie *pointer = new melodie[repetam];
for(int i = 0; i<repetam; i++){
    cout<<endl;
    cout<<"Introduceti artistul melodiei: ";    
    cin.get(pointer[i].artist);
    cout<<"Introduceti titlul melodiei: ";
    cin.getline(pointer[i].titlu);
    cout<<"Introduceti anul melodiei: ";
    cin>>pointer[i].an;
    cout<<"Introuceti lungea melodiei (in secunde): ";
    cin>>pointer[i].lungime;


}
cout<<"Lista melodiilor introduse este:"<<endl;
for(int i =0; i<repetam; i++){
    cout<<"Artistul melodiei este: "<<pointer[i].artist<<endl
        <<"Titlul melodiei este: "<<pointer[i].titlu<<endl
        <<"Anul melodiei este: "<<pointer[i].an<<endl
        <<"Lungimea melodiei (in secunde) este: "<<pointer[i].lungime<<endl;
    cout<<endl;
}

cout<<"Melodiile care au aparut dupa anul 2000 si au lungimea mai mica de 180 de secunde sunt: "<<endl;
for(int i = 0;i<repetam; i++){
    if(pointer[i].an>2000 && pointer[i].lungime<180){
        cout<<"Artist: "<<pointer[i].artist
            <<endl
            <<"Titlul: "<<pointer[i].titlu<<endl<<endl;

        
    }
}



getch();
}
like image 700
Mircea Mihai Avatar asked Nov 04 '22 07:11

Mircea Mihai


1 Answers

First off, your could shouldn't compile. There are a number of errors:

  • void main() is non-standard. main() always returns an int and the only portable declarations of main() are int main() and int main(int argc, char* argv[]) (or int main(int argc, char** argv) which is identical to the previous one; of course, the names of the two arguments can be freely chosen).
  • The get() and getline() member function you use take at least one additional argument: The size of the available buffer.

For the rest of the answer I'm assuming these errors are fixed.

Of course, the input isn't "jumping over the first question". Instead, it reads input which was already given but which you probably didn't consider as such: The formatted input using >> stops reading immediately when its respective format is completed (or it failed). For example, when reading an integer it stops once a non-digit is encountered. Thus, when reading the int for repetam the input stream stops reading after the last digit when encountering the newline used to finish this input. The call to get() reads a string up to (and including) the first newline. When entering repetam a newline was entered and, thus, this string is the newline where get() stops.

The more general, when mixing formatted input (i.e., using >>) and unformatted input (i.e., using the named functions get(), getline(), read(), etc.) you typically need to remove unwanted characters. In your example you probably want to get rid of the first newline before calling get() (you need to include <limits> to get access to std::numeric_limits):

std::cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n');
std::cin.get(pointer[i].artist, 50);

If your artisti string doesn't start with any space character, you can use

(std::cin >> std::ws).get(pointer[i].artist, 50);

The manipulator std::ws skips all leading whitespace (it would skip spaces, tabs, newlines, etc.) and is somewhat easier to type. Of course, if you need frequently ignore newlines, you can create a manipulator to ignore the characters up to and including the newline as well:

std::istream& skipline(std::istream& in)
{
    return in.ignore(std::numeric_limits<std::streamsize>::max(), '\n');
}
// ...
(std::cin >> skipline).get(pointer[i].artist, 50);

That said, I guess, you didn't really mean to use get() because this function includes the separation character ('\n' by default) into the string. You probably want to use getline() instead. Also, it is easier to deal with std::strings instead of character arrays, i.e., I would use a different definition for the struct:

struct melodi
{
    std::string artist;
    std::string titlu;
    int an;
    int lungime;
};

This way, the strings can be arbitrary size and aren't limited to 49 characters (there needs to be space for a terminating null character in you version). To read a std::string you'd need a non-member function std::getline(), however):

std::getline(std::cin >> skipline, artist);
like image 185
Dietmar Kühl Avatar answered Nov 08 '22 05:11

Dietmar Kühl