cin.ignore()?
Only a string input will take off the newline character from the input stream. You prolly have a newline on the input stream, causing the first question to process that newline, making it look like you went to the second question.
[Resolved] Basic I/O problem in C++
i tryed using cin.ignore() but that doesnt do what i want it to
its defo something todo with getline
is there an altenative to getline?
its defo something todo with getline
is there an altenative to getline?
getting a line means getting a character string until finding a newline character, so, as KulSeran points out, you need to find how that \n character gets in places where you don't want it to be. Happend hell a lot of times to me while doing very very simple programs at university.
std::getline(std::istream &, std::string &) is most certainly not the problem. Can you post a compilable, minimal example where getline fails to do what you want it to do?
@wlw_wl: i tryed using cin.ignore(256,'\n'); but all i got was having to press enter twice and then when it looped i still got nothing from enter name
@rip-off: here is my full code listing
main.cpp
io.h
struct.h
hope that helps
@rip-off: here is my full code listing
main.cpp
#include <iostream>#include <fstream>#include <string>#include "struct.h"#include "io.h"using namespace std;int main(){ person custDetails; bool cont; ofstream dbFile("C:\\Users\\James\\Desktop\\customers.dat",ios::out); do { custDetails.name = getString("Enter Name: ",false); custDetails.address = getString("Enter Address: ",false); custDetails.phoneNum = getInput<int>("Enter Phone Number: "); custDetails.dob = getDate("Enter D.O.B: ",false); cont = getInput<bool>("Continue? "); dbFile << custDetails.name << endl << custDetails.address << endl << custDetails.phoneNum << endl; dbFile << custDetails.dob.day << " " << custDetails.dob.month << " " << custDetails.dob.year << endl; } while(cont == true); dbFile.close(); return 0;}
io.h
#ifndef IO_H#define IO_H #include <iostream> #include <fstream> #include <string> #include "struct.h" using namespace std; template <class tInput,class tSInput> tInput getInput(tSInput prompt) { tInput usrInput; cout << prompt; cin >> usrInput; //getline(cin,usrInput); //cin.ignore(256,'\n'); return usrInput; } string getString(string prompt,bool newLine) { string usrString; prompt.append(newLine?"\n":""); cout << prompt; getline(cin,usrString); return usrString; } date getDate(string prompt,bool newLine) { date usrDate; prompt.append(newLine?"\n":""); cout << prompt; cin >> usrDate.day; cin >> usrDate.month; cin >> usrDate.year; return usrDate; }#endif
struct.h
#ifndef STRUCT_H#define STRUCT_H #include <iostream> #include <fstream> #include <string> #include "io.h" using namespace std; struct date{ int day,month,year; }; struct person{ string name,address; int phoneNum; date dob; }; #endif
hope that helps
really all I see is that possibly something is left in the buffer,
try using ostream& flush ( ostream& os ); (before attempting to read name)
as referenced here:
http://www.cplusplus.com/reference/iostream/manipulators/flush.html
try using ostream& flush ( ostream& os ); (before attempting to read name)
as referenced here:
http://www.cplusplus.com/reference/iostream/manipulators/flush.html
Quote:Original post by wlw_wl
really all I see is that possibly something is left in the buffer,
try using ostream& flush ( ostream& os ); (before attempting to read name)
as referenced here:
http://www.cplusplus.com/reference/iostream/manipulators/flush.html
i tryed using cout.flush(); in lots of different places but its not changing a single thing i still dont get a chance to input data for the name anytime after the first itteration of the loop
Mixing std::getline() with non-getline input can be confusing. std::getline() removes the newline from the stream, while other input methods will parse up to the newline, and the next call skips the newline.
Here is how I would write your program:
Here is how I would write your program:
// struct.h#ifndef STRUCT_H#define STRUCT_H// only include files that are necessary for this header to compile//#include <iostream>//#include <fstream>#include <string>#include <iosfwd>// Don't use "using" directives in header files// using namespace std;// While this is not universal:// A common naming convention for types is to make the first letter in every word// uppercase. This makes it easy to find a name for a variable of that type.// Just make the first letter lowercase// Example: class Foo -> variable name "foo"// class Date -> variable name "date"// class QuiteLong -> variable name "quiteLong"struct Date{ int day, month, year;};// These functions allow us to write and read "Date" instances from streamsstd::ostream &operator<<(std::ostream &, const Date &);std::istream &operator>>(std::istream &, Date &);struct Person{ std::string name, address; int phoneNum; Date dob;};std::ostream &operator<<(std::ostream &, const Person &);std::istream &operator>>(std::istream &, Person &); #endif// struct.cpp#include "struct.h"std::ostream &operator<<(std::ostream &out, const Date &date){ return out << date.day << ' ' << date.month << ' ' << date.year;}std::istream &operator>>(std::istream &in, Date &date){ return in >> date.day >> date.month >> date.year;}std::ostream &operator<<(std::ostream &out, const Person &person){ return out << person.name << ' ' << person.address << ' ' << person.phoneNum << ' ' << person.dob;}std::istream &operator>>(std::istream &in, Person &person){ return in >> person.name >> person.address >> person.phoneNum >> person.dob;}// io.h#ifndef IO_H#define IO_H#include <string>#include <sstream>#include <iostream>#include <stdexcept>// Use meaningful type names// What is a tSInput?// Also, the "t" prefix is pointless.// The function is so small that the use is obvious.// Finally, now that we have fully templated this// and overloaded operator >> for Date// We no longer need getDate() or getString()// Also, the "newline" boolean argument isn't (IMO) required.// The caller has control over the prompt, they can specify the newline there if they want.// I think that getInput<int>("Enter a number\n"); is more intuitive than// getInput<int>("Enter a number",true);template <class Result, class Prompt>Result getInput(const Prompt &prompt){ // A std::stream object, used in a boolean context will // evaluate to true while it hasn't had an error // Examples of errors are failed reads // e.g. std::cin >> integer and the user inputs "abc" // Or the end of the stream was reached. while(std::cin) { std::cout << prompt; Result result; std::string line; std::getline(std::cin,line); // stringstream does exactly what it says // It is a std::stream, but backed by a memory buffer (a string) // We construct it with the line we just read. // Alternatively, we could have done this: // std::stringstream stream; // stream << stuff; // This works even when "stuff" isn't a std::string std::stringstream stream(line); // Again, we are testing a stream in a boolean context. // Remember operator>>(std::istream &, Foo &) returns the stream it was passed. if( stream >> result ) { return result; } else { std::cerr << "Please try again.\n"; } } // if we get here, std::cin has failed // We can't really return an error, because not all "Result" types // would have a state that is an error. throw std::runtime_error("std::cin failed");}#endif// main.cpp#include <iostream>#include <fstream>#include <string>#include "struct.h"#include "io.h"int main(){ bool cont; std::ofstream file("data.txt"); do { // simpler names are better and easier to parse visually // So "person", not "custDetails". // Also, scope variables as tightly as possible Person person; // We could just use std::cin >> person, because we defined that operator. // But then we can't provide the nice promts. // However, because that function is implemented it will save us time when // we go to read the file later... person.name = getInput<std::string>("Enter Name: "); person.address = getInput<std::string>("Enter Address: "); person.phoneNum = getInput<int>("Enter Phone Number: "); person.dob = getInput<Date>("Enter D.O.B (dd mm yy): "); file << person << '\n'; // only use "endl" when you really want the stream *flushed* // Otherwise just use '\n' // //dbFile << person.name << endl << person.address << endl << person.phoneNum << endl; //dbFile << person.dob.day << " " << person.dob.month << " " << person.dob.year << endl; // getInput<bool>: not intuitive char c = getInput<char>("Continue? (y/n) "); // This is shorter than // if(c == 'y') // { // cont = true; // } // else // { // cont = false; // } cont = (c == 'y'); } while(cont == true); // std::fstream's close themselves on destruction // dbFile.close(); // main() is special: it doesn't need to explicitly return a value. // It will act as though you write return 0; unless you specify otherwise. // return 0;}
This topic is closed to new replies.
Advertisement
Popular Topics
Advertisement