[Resolved] Basic I/O problem in C++

Started by
17 comments, last by OpperationQuak 15 years, 6 months ago
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.
Advertisement
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?
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
#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
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:
// 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;}
i got it fixed
all i had to do was add the following line after code using cin instead of getline

char c = cin.get();

thanks for everyones help with this anyway

This topic is closed to new replies.

Advertisement