getline function

closed account (jGAShbRD)
So my class is taking a full name but for some reason when I use getline(std::cin,name) my program goes into an infinite loop.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
#include<iostream>
#include<fstream>
#include<string>
#include<map>

class acc{
    std::string name;
    static long acc_num;
    long accnum;
    long total;
    public:
    acc();
    acc(std::string name,long total);
    void setdep(long amount);
    void setwith(long amount);
    long getacc();
    long gettotal();
    static void setaccnum(long num);
    friend std::ofstream&operator<<(std::ofstream&o,acc&a);
    friend std::ifstream&operator>>(std::ifstream&i,acc&a);
    friend std::ostream&operator<<(std::ostream&o,acc&a);
};
long acc::acc_num=0;
acc::acc(){
};
acc::acc(std::string name,long total){
    this->name=name;
    this->total=total;
    accnum=++acc_num;
}
void acc::setdep(long amount){
    total+=amount;
}
void acc::setwith(long amount){
    if(total<amount){
        std::cout<<"Insufficent amount.\n";
    }
    else{
        total-=amount;
    }
}
long acc::gettotal(){
    return total;
}
long acc::getacc(){
    return accnum;
}
void acc::setaccnum(long num){
    acc_num=num;

}
std::ofstream&operator<<(std::ofstream&o,acc&a){
    o<<a.name<<std::endl<<a.accnum<<std::endl<<a.total<<std::endl;
    return o;
}
std::ifstream&operator>>(std::ifstream&i,acc&a){
    getline(i,a.name);
    i>>a.accnum>>a.total;
    return i;
}
std::ostream&operator<<(std::ostream&o,acc&a){
    o<<"Name: "<<a.name<<std::endl<<"Account Number: "<<a.accnum<<std::endl<<"Account Total: "<<a.total<<std::endl;
    return o;
}

class bank{
    std::map<long,acc> map;
    public:
    bank();
    void open(std::string name,long amount);
    void with(long accnum,long amount);
    void dep(long accnum,long amount);
    void showacc(long accnum);
    void showall();
    void close(long accnum);
    ~bank();
};

bank::bank(){
    std::ifstream myfile;
    myfile.open("test.txt");
    if(!myfile){
        std::cout<<"File not found."<<std::endl;
    }
    else{
        while(!myfile.eof()){
            acc a;
            myfile>>a;
            map.insert(std::make_pair(a.getacc(),a));
            myfile.ignore();
        }
        myfile.close();
    }
}
void bank::open(std::string name,long amount){
    std::map<long,acc>::reverse_iterator itr=map.rbegin();
    if(!map.empty()){
        acc::setaccnum(itr->first);
        acc a(name,amount);
        map.insert(std::make_pair(a.getacc(),a));
        std::cout<<a;
    }
    else{
        acc::setaccnum(0);
        acc a(name,amount);
        map.insert(std::make_pair(a.getacc(),a));
        std::cout<<a;
    }
}
void bank::with(long accnum,long amount){
    std::map<long,acc>::iterator itr=map.find(accnum);
    if(itr!=map.end()){
        itr->second.setwith(amount);
    }
    else{
        std::cout<<"Account does not exist."<<std::endl;
    }
}
void bank::dep(long accnum,long amount){
    std::map<long,acc>::iterator itr=map.find(accnum);
    if(itr!=map.end()){
        itr->second.setdep(amount);
    }
    else{
        std::cout<<"Account does not exist."<<std::endl;
    }
}
void bank::showacc(long accnum){
    std::map<long,acc>::iterator itr=map.find(accnum);
    if(itr!=map.end()){
        std::cout<<itr->second<<std::endl;
    }
    else{
        std::cout<<"Account does not exist."<<std::endl;
    }
}
void bank::showall(){
    std::map<long,acc>::iterator itr;
    for(itr=map.begin();itr!=map.end();itr++){
        std::cout<<itr->second<<std::endl;
    }
}
void bank::close(long accnum){
    std::map<long,acc>::iterator itr=map.find(accnum);
    if(itr!=map.end()){
        if(itr->second.gettotal()==0){
            map.erase(itr);
        }
        else{
            std::cout<<"Withdraw money."<<std::endl;
        }
    }
    else{
        std::cout<<"Account does not exist."<<std::endl;
    }
}
bank::~bank(){
    std::ofstream myfile;
    myfile.open("test.txt");
    std::map<long,acc>::iterator itr;
    for(itr=std::next(map.begin());itr!=map.end();itr++){
        myfile<<itr->second;
    }
    myfile.close();
}

int main(){
    acc a;
    bank b;
    int x;
    std::cout<<"**************Bank*************"<<std::endl<<std::endl;
    do{
        std::cout<<"\n\n1.Open an Account\n"<<"2.Check Account\n"<<"3.Deposit\n"<<"4.Withdraw\n"<<"5.Close an Account\n"<<"6.Show all Account\n"<<"7.Quit\n\n";
        std::cin>>x;
        switch(x){
            case 1:{
                std::string name;
                long deposit;
                std::cout<<"Enter name: \n";
                std::cin>>name; //getline(std::cin,name)<----- HELP
                std::cout<<"Enter inital deposit: \n";
                std::cin>>deposit;
                std::cout<<"New Account Opened.\n";
                b.open(name,deposit);
            }
            break;
            case 2:{
                long c;
                std::cout<<"Enter account number: \n";
                std::cin>>c;
                b.showacc(c);
            }
            break;
            case 3:{
                long c,y;
                std::cout<<"Enter amount: \n";
                std::cin>>c;
                std::cout<<"Enter account number: \n";
                std::cin>>y;
                b.dep(y,c);
                std::cout<<"Deposit complete.\n";
            }
            break;
            case 4:{
                long c,y;
                std::cout<<"Enter amount: \n";
                std::cin>>c;
                std::cout<<"Enter account number: \n";
                std::cin>>y;
                b.with(y,c);
                std::cout<<"Withdrawal complete.\n";
            }
            break;
            case 5:{
                long c;
                std::cout<<"Enter account number: \n";
                std::cin>>c;
                b.close(c);
                std::cout<<"Account closed.\n";
            }
            break;
            case 6:{
                b.showall();
            }
            break;
            case 7:{
                std::cout<<"Exiting.\n";
                return 0;
            }
        }
    }while(x!=7);
}

Last edited on
Be careful when mixing the extraction operator>> and getline(). The extraction operator leaves the new line character in the input buffer which getline() will extract for it's entry, leaving everything after the new line character in the input buffer for the next operation. Since your next operation is trying to get some numeric value the stream will go into an error state, hence the endless loop.

To fix the problem you must extract and discard the new line character. There are several ways to accomplish this. The method I prefer is to use the std::ws manipulator to extract and discard the remaining whitespace.

1
2
3
4
5
6
7
8
        std::cin >> x >> std::ws;
        switch(x){
            case 1:{
                std::string name;
                long deposit;
                std::cout  << Enter name: ";
                getline(std::cin, name)<----- HELP
 


Don't forget to include the correct header file for the manipulators and that every time you use the extraction operator>> followed by getline() you must take care of that pesky new line character.

I'll start by congratulating you on writing your << and >> operators as a pair. It's always much easier to do them that way.

To elaborate a little on jlb's answer, your << and >> operators should be an exact match. In your case, << writes a newline after printing total, but >> doesn't read it. So the next time you call >>, it tries to read the name, gets an empty newline and things fall apart from there.

A few other points:

std::endl is slow because it flushes the stream. Use '\n' unless you need to flush it.

operator<<(std::ostream&o,acc&a) writes formatted output while operator<<(std::ofstream&o,acc&a) does not. The class shouldn't restrict where it writes formatted vs. unformatted output. So I'd make a separate method to print formatted output and allow either type to go to any type of stream:

1
2
3
4
5
6
7
8
9
std::ostream&operator<<(std::ostream&o,acc&a){
    o<<a.name<<std::endl<<a.accnum<<std::endl<<a.total<<std::endl;
    return o;
}

ostream & acc::format(std::ostream&o) {
    o<<"Name: "<<a.name<<std::endl<<"Account Number: "<<a.accnum<<std::endl<<"Account Total: "<<a.total<<std::endl;
    return o;
}
Topic archived. No new replies allowed.