Hey, Im having some trouble with my code,
it doesn't seem to stop to wait for an answer to the question about modifying the phone list when i input values in above and press Ctrl Z enter, however the code works fine
when i remove the code about inputting information.

#include <iostream>
#include<fstream>
#include<string>
#include <cstdio>
using namespace std;

int main(){ 
	
	ofstream fout("f:\\telr.txt",ios::app);
	
	string ln, fn, tel; //lastname, first name, tele

	cout << "give last name, first name aand tel. no: "
		<< "terminate with Ctrl-Z" << endl;

	while(cin >> ln && cin >> fn && cin >> tel)
		fout << ln << ' ' << fn << ' ' << tel << endl;
	fout.close();
	
	ifstream fin("f:\\telr.txt", ios::in);
	cout << "This is the telephone list:" << endl;
	cout << fin.rdbuf();

	fin.close();
	
	

	string fn_input;
	string yes = "Y";
	string answer;

	cout << "Do You want to modify the phone list (Y/N):";
	cin >> answer;
	cout << answer;
	
	if(yes.compare(answer) == 0){
		cout << "here";
	
	ofstream fnout("temp.txt",ios::app);//creates/opens a temporary file
	ofstream fout("f:\\telr.txt",ios::app);//opens the location of the permanent file
	
	cout << "Enter the first name:" << endl;
	cin >> fn_input;
	
   		if (fout.is_open()){//only continue this subroutine if it has been opened correctly
		ifstream fin("f:\\telr.txt", ios::in);
		fin >> fn  >> ln >> tel;//scans in the first name, last name, tel in that format!
	
			do{
				if (fn.compare(fn_input) == 0){//scans through permanent copy until finds a match (compare function)
				cout << "Name: " << fn << " " << ln<< endl;
				cout << "New number: ";
				cin >> tel;
				fnout << fn << " "  << ln << " " << tel << endl;//outputs the new number and all the name information to the temporary file
				}
				if (fn.compare(fn_input) != 0){//if there is no match, output the data scanned in from the permamnt copy to the temporary file
				fnout << fn << " "  << ln << " " << tel << endl;//and then continue the scanning cycle
				}
				fin >> fn  >> ln >> tel;
			}while(!fin.eof());//continue to scan the document until the end of the file flag is activated

		std::ofstream file("f:\\telr.txt", std::ios::trunc);//clears the permanent copy of all the data inside
		ifstream fitn("temp.txt", ios::in);
		fitn >> fn  >> ln >> tel;
			
			do{//this routine copies all the data from the temporary file to the permamnt one
			fout << fn << " "  << ln << " " << tel << endl;
			fitn >> fn  >> ln >> tel;
			}while(!fitn.eof());

		}
	
	else cout << "Unable to open file";
	
	fout.close();//closing files in use
	fnout.close();
	remove("temp.txt");//removes the temp file 
	return 0;
	}
}

Recommended Answers

All 15 Replies

A couple things:

First, please use [code] ...code tags... [/code] when posting code. It makes it much easier to read. Click the [code] button above your editor and it will insert them for you, then all you have to do is type your code between them.

It'll look like this:

#include <iostream>
using std::cout;
using std::endl;

int main() {
  cout << "Hello World!" << endl;
  return (0);
}

Second, your description is a little vague and difficult to understand. Where exactly does the error occur in the use case and what does it do when the error occurs?

The key combination CTRL+Z puts an end-of-file on the stream which corrupts the stream making it unusable until you reset the stream. I really don't see anything in your code to address this situation. Based on this information, my initial suspicion is that this may be your problem. See the sticky thread "How do I flush the input stream?" for information on correcting this.

Sorry to be vague.

Running the code above produces an error. Once the program starts up the User is prompted to input names and numbers to be put in the database(test file), This works fine. Once the User presses CTRL Z all the names and numbers in the document are printed out.

The user should then be prompted to Decide whether they want to edit any number however there is no pause for a reply after the question has been asked and precedes to the end of the program

#include<iostream>
using namespace std;

Sorry to be vague.

Running the code above produces an error. Once the program starts up the User is prompted to input names and numbers to be put in the database(test file), This works fine. Once the User presses CTRL Z all the names and numbers in the document are printed out.

The user should then be prompted to Decide whether they want to edit any number however there is no pause for a reply after the question has been asked and precedes to the end of the program

This is because the stream is corrupted and the input command used to get the user's answer is not able to function properly. You have to flush and reset the input stream so that the command will behave as expected. Did you read the thread I mentioned in my previous post?

This is because the stream is corrupted and the input command used to get the user's answer is not able to function properly. You have to flush and reset the input stream so that the command will behave as expected. Did you read the thread I mentioned in my previous post?

Yes i have read it however i dont really understand where and how i would apply the processes described in the article to my scenario, i am presuming the location will by after the 'printing' section of the code and before the point where the user is asked if they want to manipulate the database?

Yes i have read it however i dont really understand where and how i would apply the processes described in the article to my scenario, i am presuming the location will by after the 'printing' section of the code and before the point where the user is asked if they want to manipulate the database?

Correct, you would add the required conditionals, etc. anywhere within that section. Ideally, it will be directly after your input loop (looks like about Line 18, another argument for code tags, they add line numbers). Wherever you place it, it must execute before the next input statement executes.

You have name clashes 'fout' and 'fin' is declared twice.You can't open a file for both reading and writing at the same time , you must close one stream and open another.You might need to change the structure of your program.In fact you can open them but you must manually control the file pointer otherwise you won't get the expected results

Correct, you would add the required conditionals, etc. anywhere within that section. Ideally, it will be directly after your input loop (looks like about Line 18, another argument for code tags, they add line numbers). Wherever you place it, it must execute before the next input statement executes.

Im still a bit confused about what to put in, i've read through the article again but im still not too sure.

I don't know if you are familiar with some more advanced concepts like classes or friends but if not you should definitely look into learning about them.So you can start now.When representing a concept such as a phonebook entry it is more efficient to use structures for grouping data.This enforces you to build more complex concepts out of simpler ones.Say you have a pair of trousers and a jacket , you can represent them as a suit , thus it is more efficient to fill say a 'wardrobe' with 'suits' than with trousers and jackets.This is a similar case , you should group a phone number and a name under a tag so that if you ever need to add another feature to a phonebook entry it will be a lot easier to just modify the structure of your class other than the whole program.In c++ you can overload any operator except a few of them to achieve a polymorphic behavior so in your case you can overload the insertion and extraction operators , this will ease your pain a lot.I've baked a simple example for you , it is not complete but you can build on that.

#include <string>
#include <fstream>
#include <iostream>

class PhoneBookEntry  {  //use structures for bundles of data
   std::string Name; 
   int Number;
public:
   PhoneBookEntry () {}
   ~PhoneBookEntry () {}
   PhoneBookEntry (std::string name_,int nb_) : Name(name_), Number(nb_) {} 

       //you can overload the insertion/extraction operators for streams

   friend std::ostream& operator << (std::ostream& o,const PhoneBookEntry& phb)  {
      return o << phb.Name << " " << phb.Number;
      //returns a stream containing a string and an integer
    }

   friend std::istream& operator >> (std::istream& i,PhoneBookEntry& phb)  {      
      return i >> phb.Name >> phb.Number;      
    }   
 };

int main ()  {
   std::ofstream of("qwe.txt",std::ios::app);
   PhoneBookEntry New("me",123);
   of << New; //here the overloaded function is called for insertion 
   of.close();

   std::ifstream f("qwe.txt");
   PhoneBookEntry Tmp;
   f >> Tmp; //and the second overload is called for extraction
   std::cout << Tmp; //works with std::cout also so since the operator is overloaded
                       for type ostream
 }

Also whenever you need input from a user in the form say "Y/N" you should give both options and each should have a consequence.Ex :

char answer;
bool valid_argument=0;
while (!valid_argument)  {
   switch (answer)  {
      case 'Y':
         //do something;
         valid_argument=1; //user answer was valid (Y'N)
         break;
      case 'N':
         //do something else;
         valid_answer=1;
         break;
      default:
         valid_answer=0; //the user entered something else
         //re enter the loop
         break;
     }
  }

Read up on istream::ignore(), ios::good(), and ios::clear()

Then, start by adding a cin.ignore(), and expand from there. If the ignore() is not enough to correct it, add parameters to the ignore:

cin.ignore(80, '\n');

If that's still not sufficient, add a stream check/reset:

if (!cin.good()) {
  cin.clear();
  cin.ignore(80, '\n');
}

That's really all you can do...

I......

Thanks I will look into that but i was just hoping to find a way to get this code working as when i comment out

while(cin >> ln && cin >> fn && cin >> tel)
		fout << ln << ' ' << fn << ' ' << tel << endl;
	fout.close();

It works perfectly, apart from the lack in functionality of being able to input names and number.

That's an infinite loop.I tried to fix your code by still preserving much of it but i couldn't.Anyway that loop is the first thing i took away

...

Thanks for your help, in the end i found this worked perfectly

if (!cin.good()) {
  cin.clear();
  }

That's an infinite loop.I tried to fix your code by still preserving much of it but i couldn't.Anyway that loop is the first thing i took away

It's actually an indeterminate loop. The difference is that it's infinite as long as a sentinel value isn't entered.

In this case, the sentinel value is the key combination CTRL+Z. Input streams return a "true" value as long as they are in a good state. CTRL-Z sets the End-Of-File bit moving the stream into a bad state which is considered "false".

Once the loop is complete, you have to reset the stream's state to good. That's why you need the cin.clear().

EDIT:
@OP
Glad you figured it out. :)

Be a part of the DaniWeb community

We're a friendly, industry-focused community of developers, IT pros, digital marketers, and technology enthusiasts meeting, networking, learning, and sharing knowledge.