CodeGuru Home VC++ / MFC / C++ .NET / C# Visual Basic VB Forums Developer.com
Results 1 to 15 of 15
  1. #1
    Join Date
    Oct 2010
    Posts
    20

    Extracting a line from content in the line

    Hey guys, I'm trying to write an address book program using structs that will give the user three options. They can either add a name, telephone number, and address to the phone book (all of which will appear on the same line, separated by spaces), this part of the problem is easy and I have it done. The next option the user will have is to delete a line in the address book, giving only the telephone number. So in other words, the user types in a telephone number, the program will search the address book text file for that phone number, and delete that phone number as well as the name and address associated with it.

    How can I make it so that I search a text file for a phone number, then delete the whole line containing it?

  2. #2
    Join Date
    Sep 2010
    Posts
    66

    Re: Extracting a line from content in the line

    One possible option is to read the entire file into a vector of type Person, perform the needed operations, and then overwrite the file when the program is exiting. If your input file is huge, this is probably not an efficient option.

    If you try doing this as you are reading the file, things might get hairy. You might have to keep track of where you found the match, close the file, open the file for writing, etc. This sounds like a real mess to me, but that is just my two cents. Maybe someone can comment on a more efficient way to do this.

  3. #3
    Join Date
    Oct 2010
    Posts
    20

    Re: Extracting a line from content in the line

    Quote Originally Posted by ttrz View Post
    One possible option is to read the entire file into a vector of type Person, perform the needed operations, and then overwrite the file when the program is exiting. If your input file is huge, this is probably not an efficient option.

    If you try doing this as you are reading the file, things might get hairy. You might have to keep track of where you found the match, close the file, open the file for writing, etc. This sounds like a real mess to me, but that is just my two cents. Maybe someone can comment on a more efficient way to do this.
    I'm sorry I'm not familiar with the term vector, not sure what you mean by that. I'm assuming there's a simpler option?

    Also how do you tell your program to go back to the beginning, ie, if a user used my program to add someone to the address book, then I want it to bring them back to the main menu of the program?

  4. #4
    Join Date
    Sep 2010
    Posts
    66

    Re: Extracting a line from content in the line

    A vector is similar to an array, except that is grows dynamically. You don't need to know in advance exactly how many elements the vector will hold. Whenever you need to add an element to the vector, you just use the member function push_back().

    The simpler (and more limited) option would be to just use an array. Of course the size must be fixed and it does not grow dynamically:

    Book library[50];

    Obviously in this case there can only be a maximum of 50 books in the library. If you want to read more about vectors, click here.


    You will want to use a loop to bring the user back to the menu. Here is an example of this that I used in an earlier posting:

    Code:
    int main () {
    	string s;
    
    	do {
    		cout << "What would you like today?" << endl;
    		cin >> s;
    
    		switch(toupper(s[0])){
    		case 'W': 
    			cout << "What is the amount?" << endl;
    			//etc
    			break;
    		case 'Q': 
    			cout << "Goodbye";
    			return 0;
    		default: 
    			cout << "Invalid selection. Please try again." << endl;
    			break;
    		};
    	}
    		while(cin);
    
    		return 0;
    }

  5. #5
    Join Date
    Oct 2010
    Posts
    20

    Re: Extracting a line from content in the line

    Quote Originally Posted by ttrz View Post
    A vector is similar to an array, except that is grows dynamically. You don't need to know in advance exactly how many elements the vector will hold. Whenever you need to add an element to the vector, you just use the member function push_back().

    The simpler (and more limited) option would be to just use an array. Of course the size must be fixed and it does not grow dynamically:

    Book library[50];

    Obviously in this case there can only be a maximum of 50 books in the library. If you want to read more about vectors, click here.


    You will want to use a loop to bring the user back to the menu. Here is an example of this that I used in an earlier posting:

    Code:
    int main () {
    	string s;
    
    	do {
    		cout << "What would you like today?" << endl;
    		cin >> s;
    
    		switch(toupper(s[0])){
    		case 'W': 
    			cout << "What is the amount?" << endl;
    			//etc
    			break;
    		case 'Q': 
    			cout << "Goodbye";
    			return 0;
    		default: 
    			cout << "Invalid selection. Please try again." << endl;
    			break;
    		};
    	}
    		while(cin);
    
    		return 0;
    }
    Okay, well how would I extract the line and delete it using arrays???

    And I don't quite understand that loop, the while(cin) part is throwing me, wouldn't that just make the program continue forever? Because the keyboard will always be active? What if I have an option included for exit the program?

  6. #6
    Join Date
    Sep 2010
    Posts
    66

    Re: Extracting a line from content in the line

    Quote Originally Posted by wiec7548 View Post
    And I don't quite understand that loop, the while(cin) part is throwing me, wouldn't that just make the program continue forever? Because the keyboard will always be active? What if I have an option included for exit the program?
    In the above example, notice that if the user enters a word beginning with q (ie, quit) the program returns from main:

    Code:
    		case 'Q': 
    			cout << "Goodbye";
    			return 0;
    As for the while(cin), you can check the state of an input stream like this. The stream will be put in a fail state if the user enters the wrong type of data (ie, if the user enters a character where an int is expected) or if eof is encountered (you can simulate this by pressing control-C in windows).

    As for how to do it, here is one way:

    Code:
    #include <string>
    #include <fstream>
    
    using namespace std;
    
    
    struct Person{
    	string name,
    		number,
    		address;
    };
    
    int main () {
    	Person addressBook[50];
    	Person temp;
    
    	ifstream infile("test.txt");
    
    	if(!infile){
    		cout << "Error opening input file" << endl;
    		return -1;
    	}
    
    	for(int i = 0; infile >> temp.name >> temp.number  && i < 50; i++){
    		infile.ignore(1);
    		if(getline(infile, temp.address, '\n'))
    		addressBook[i] = temp;
    	}
    
    return 0;
    }
    This assumes your input file is like so:

    Code:
    Joe 221-1150 20 Jackall Road
    Tom 225-6699 2051 Lane Drive
    Jospeh 115-1410 2222 Smith Road
    Again this isn't the best because it will only be able to hold at most 50 entries. Anyway, after you have read everything you want into the array, you can then let the user do what they want to do and modify the array when the program is running. Before exiting, open the file by creating an ofstream object using the filename and write the contents of the array to the file.
    Last edited by ttrz; October 31st, 2010 at 09:05 PM.

  7. #7
    Join Date
    Oct 2010
    Posts
    20

    Re: Extracting a line from content in the line

    Quote Originally Posted by ttrz View Post
    In the above example, notice that if the user enters a word beginning with q (ie, quit) the program returns from main:

    Code:
    		case 'Q': 
    			cout << "Goodbye";
    			return 0;
    As for the while(cin), you can check the state of an input stream like this. The stream will be put in a fail state if the user enters the wrong type of data (ie, if the user enters a character where an int is expected) or if eof is encountered (you can simulate this by pressing control-C in windows).

    As for how to do it, here is one way:

    Code:
    #include <string>
    #include <fstream>
    
    using namespace std;
    
    
    struct Person{
    	string name,
    		number,
    		address;
    };
    
    int main () {
    	Person addressBook[50];
    	Person temp;
    
    	ifstream infile("test.txt");
    
    	if(!infile){
    		cout << "Error opening input file" << endl;
    		return -1;
    	}
    
    	for(int i = 0; infile >> temp.name >> temp.number  && i < 50; i++){
    		infile.ignore(1);
    		if(getline(infile, temp.address, '\n'))
    		addressBook[i] = temp;
    	}
    
    return 0;
    }
    This assumes your input file is like so:

    Code:
    Joe 221-1150 20 Jackall Road
    Tom 225-6699 2051 Lane Drive
    Jospeh 115-1410 2222 Smith Road
    Again this isn't the best because it will only be able to hold at most 50 entries. Anyway, after you have read everything you want into the array, you can then let the user do what they want to do and modify the array when the program is running. Before exiting, open the file by creating an ofstream object using the filename and write the contents of the array to the file.
    I don't see how that would do what I want since nowhere in your code do you ask the user to input a phone number, and there seems to be no sign of you deleting any lines in the address book once they're found? And what is the purpose of having temp at all? I'm sorry I'm very new with structs and I seem to be struggling with these simple programs with them that's why I joined this site. Is there a misunderstanding in what I'm asking?
    Last edited by wiec7548; November 1st, 2010 at 12:59 AM.

  8. #8
    Join Date
    Oct 2010
    Posts
    20

    Re: Extracting a line from content in the line

    can anyone help me?

  9. #9
    Join Date
    Sep 2010
    Posts
    66

    Re: Extracting a line from content in the line

    Quote Originally Posted by wiec7548 View Post
    I don't see how that would do what I want since nowhere in your code do you ask the user to input a phone number,
    I'm not trying to write the program, I'm only providing ideas for certain parts. If you design it this way, you could add an element to the array/vector whenever you need to add someone to the address book.

    and there seems to be no sign of you deleting any lines in the address book once they're found?
    As I said above, the idea is to store everything you already have in the array/vector by reading the file from disk. Then let the user add/delete people as they like. Update the array/vector as they do this. Then overwrite the file before the program exits with the contents from the updated array/vector.

    The idea is to read the file when the program starts and overwrite it with updated information when the program exits.

    Code:
    infile.close();
    
    	ofstream outfile("test.txt"); //Use same filename
    
    	if(!outfile){
    		cout << "Error opening output file." << endl;
    		return -1;
    	}
    
    	outfile << "boo "; //Cycle through array/vector and write each person to the file
    
    	outfile.close();
    And what is the purpose of having temp at all?
    I just used temp because that's how it would be done if you were using a vector (you would store the data in a temporary object and then call push_back(temp) on your vector object).

    Using temp above, the data is only copied to the array if all 3 reads are successful. If you chose to read directly into the addressBook, it is possible you could read a name and number and the getline() call to read the address could fail. Then you would be stuck with an entry with a name and number and no address. If this is what you want, then you should make sure to initialize all of the elements in the default constructor.

    Using an array is actually more of a pain than using a vector for a problem like this. But you asked how to do it with an array and it can be done as long as you accept the limitations.

  10. #10
    Join Date
    Oct 2010
    Posts
    20

    Re: Extracting a line from content in the line

    I still don't really understand how you'd do it...i really don't want to use vectors as I'm doing this from a book and don't want to get ahead of myself.

    Here's what I have so far

    Code:
    #include <iostream>
    #include <fstream>
    #include <string>
    using namespace std;
    
    struct AddBook
    	{
    	char Name[25];		
    	char Address[100];
    	char Phone[15];
    	};
    void main()  
    {
    
    	
    	AddBook resident ;
    	char Ans;
    	
    	
    	ofstream outfile;
    	outfile.open("U://address.txt") ;
    
    	do
    	{
    	cout<<endl<<endl<<"Please select one of the following options: "<<endl<<endl;
    	cout<<"A: Add a new person to the address book"<<endl<<endl;
    	cout<<"D: Using a phone number as the key, delete the record of an individual from the address book"<<endl<<endl;
    	cout<<"S:Using a phone number, search and print the name and address of the person, if the phone number is in the address book."<<endl<<endl;
    	cout<<"Q: Quit the program."<<endl<<endl;
    	 cin >> Ans; 
    	 
    	if ( Ans == 'A'| Ans=='a' )
    	{
    		
    		cout<<endl<<"You've chosen to add a person to the address book."<<endl<<" Please enter the person's name: " ;
    		cin.ignore();
    		cin.getline(resident.Name, 25);
    		cout<<endl << "Please enter the person's address " ;
    		cin.getline(resident.Address, 100);
    		cout<<endl << "Please enter the person's phone " ;
    		cin.getline(resident.Phone, 15);
    
    		outfile << resident.Name << "    "  << resident.Address << "    " << resident.Phone << endl << endl;
    
    	}
    	else if (Ans== 'D'| Ans=='d') 
    	{
    		cout<<endl<<"You've chosen to delete a person from the address book. Please enter a phone number: " ;
    
    	}
    	else if (Ans== 'S'| Ans=='s') 
    	{
    		cout<<endl<<"You've chosen to search the address book for an entry. Please enter the phone number of the entry you'd like to find:  " <<endl;
    
    	}
    	else if (Ans== 'Q'| Ans=='q') 
    	{
    		cout <<endl<< "Goodbye"<<endl<<endl;
    			exit(1);
    	}
    	}while(cin);
    
    }
    Last edited by wiec7548; November 1st, 2010 at 02:55 PM.

  11. #11
    Join Date
    Sep 2010
    Posts
    66

    Re: Extracting a line from content in the line

    Well, the easiest way is to probably have a separate string for first and last name:

    Code:
    struct Person{
    	string firstName,
    		lastName,
    		number,
    		address;
    };
    
    int main () {
    	Person a;
    
    	cout << "Enter your first and last name: " << endl;
    	cin >> a.firstName >> a.lastName;
    
    return 0;
    }
    But if you really just wanted to have one name variable, you could use a temp string like so:

    Code:
    struct Person{
    	string name,
    		number,
    		address;
    };
    
    int main () {
    	Person a;
    	string temp;
    
    	cout << "Enter your first and last name: " << endl;
    	cin >> a.name >> temp;
    
    	a.name += " " + temp;
    
    	cout << "Name is: " << a.name;
    
    return 0;
    }
    I think most people would probably just do it the first way, though.

  12. #12
    Join Date
    Oct 2010
    Posts
    20

    Re: Extracting a line from content in the line

    I actually solved that problem, a different way than you however. But I am still stuck trying to search and delete an entry from the address book! Here is my code so far...As you can see I have the adding members to the address book part of it down fine, and I have the program running in a loop. If I can figure out the deleting part, then the searching for and printing an entry part should be easy...Thanks for your help by the way tt, I really appreciate it!

    Code:
    #include <iostream>
    #include <fstream>
    #include <string>
    using namespace std;
    
    struct AddBook
    	{
    	char Name[25];		
    	char Address[100];
    	char Phone[15];
    	};
    void main()  
    {
    
    	
    	AddBook resident ;
    	char Ans;
    	
    	
    	ofstream outfile;
    	outfile.open("U://address.txt") ;
    
    	do
    	{
    	cout<<endl<<endl<<"Please select one of the following options: "<<endl<<endl;
    	cout<<"A: Add a new person to the address book"<<endl<<endl;
    	cout<<"D: Using a phone number as the key, delete the record of an individual from the address book"<<endl<<endl;
    	cout<<"S:Using a phone number, search and print the name and address of the person, if the phone number is in the address book."<<endl<<endl;
    	cout<<"Q: Quit the program."<<endl<<endl;
    	 cin >> Ans; 
    	 
    	if ( Ans == 'A'| Ans=='a' )
    	{
    		
    		cout<<endl<<"You've chosen to add a person to the address book."<<endl<<" Please enter the person's name: " ;
    		cin.ignore();
    		cin.getline(resident.Name, 25);
    		cout<<endl << "Please enter the person's address " ;
    		cin.getline(resident.Address, 100);
    		cout<<endl << "Please enter the person's phone " ;
    		cin.getline(resident.Phone, 15);
    
    		outfile << resident.Name << "    "  << resident.Address << "    " << resident.Phone << endl << endl;
    
    	}
    	else if (Ans== 'D'| Ans=='d') 
    	{
    		cout<<endl<<"You've chosen to delete a person from the address book. Please enter a phone number: " ;
    
    	}
    	else if (Ans== 'S'| Ans=='s') 
    	{
    		cout<<endl<<"You've chosen to search the address book for an entry. Please enter the phone number of the entry you'd like to find:  " <<endl;
    
    	}
    	else if (Ans== 'Q'| Ans=='q') 
    	{
    		cout <<endl<< "Goodbye"<<endl<<endl;
    			exit(1);
    	}
    	}while(cin);
    
    }
    Is there some way I could just use fstream, and use one file, without having to use a temporary storage file and delete it, etcetera? I know this would compromise the format of the address book in that there'd just be spaces where entries are deleted, but that's not a big concern of mine right now.
    Last edited by wiec7548; November 1st, 2010 at 03:06 PM.

  13. #13
    Join Date
    Sep 2010
    Posts
    66

    Re: Extracting a line from content in the line

    Well, if you were going to do it the way I suggested, you wouldn't write to the output file until the user decided to quit.

    Right now you are getting input and then writing directly to the output file.

    Instead of doing that, you could probably make an array (or even better, a vector) of residents and store the input in the array.

    I don't really have time to work through the whole thing right now, but here is a quick example of how it might work.

    Code:
    const int ARRAY_SIZE = 50;
    AddBook resident[ARRAY_SIZE];
    
    int index = 0; //Keep track of how many array slots you are actually using
    
    do {
    cout << "Pick your option.." << endl;
    cin >> Ans;
    
    	if ( Ans == 'A'|| Ans=='a' )
    	{
    		if(index == ARRAY_SIZE){
    			cout << "Address book is full! Please delete an entry to make room!" << endl;
    			continue;
    		}
    
    		
    		cout<<endl<<"You've chosen to add a person to the address book."<<endl<<" Please enter the person's name: " ;
    		cin.ignore();
    		cin.getline(resident[index].Name, 25); //Store the input into the array. Don't write to the output file yet.
    
    		//Get the rest of the input, etc
    
    		index++;
    	}
    	else if (Ans== 'D'|| Ans=='d') 
    	{
    		if(index == 0){
    			cout << "No entries to delete!" << endl;
    			continue;
    		}
    		cout<<endl<<"You've chosen to delete a person from the address book. Please enter a phone number: " ;
    
    		//Some logic here to find out which entry to delete. Let's say you store the index to delete in indexToDelete
    
    		resident[indexToDelete] = resident[index - 1]; //Overwrite whatever was there
    		index--;
    
    	}
    
    	else if (Ans== 'Q'|| Ans=='q') 
    	{
    		cout <<endl<< "Goodbye"<<endl<<endl;
    
    		ofstream outfile("test.txt");
    
    		for(int i = 0; i < index; i++)
    			outfile << resident[index].name << " " << resident[index].number << " " << resident[index].address << endl;
    
    		return 0;
    	}
    
    
    }
    That is to give you an idea of the type of checking you will have to do if you use an array.

    If you use a vector, you can see how it might be easier:

    Code:
    vector<AddBook> residents;
    AddBook temp;
    
    //etc.. 
    //enter do/while loop and print menu etc
    
    	if ( Ans == 'A'|| Ans=='a' )
    	{
    		
    		cout<<endl<<"You've chosen to add a person to the address book."<<endl<<" Please enter the person's name: " ;
    		cin.ignore();
    		cin.getline(temp.Name, 25); //Store the input into temp object. Don't write to the output file yet.
    
    		//Get the rest of the input, etc
    
    		residents.push_back(temp);
    	}
    	else if (Ans== 'D'|| Ans=='d') 
    	{
    		if(residents.empty()){
    			cout << "No entries to delete!" << endl;
    			continue;
    		}
    		cout<<endl<<"You've chosen to delete a person from the address book. Please enter a phone number: " ;
    
    		//Some logic here to find out which entry to delete. Let's say you want to delete the third element.
    		residents.erase(residents.begin() + 2);
    
    	}
    
    	else if (Ans== 'Q'|| Ans=='q') 
    	{
    		cout <<endl<< "Goodbye"<<endl<<endl;
    
    		ofstream outfile("test.txt");
    
    		for(int i = 0; i < residents.size(); i++)
    			outfile << resident[index].name << " " << resident[index].number << " " << resident[index].address << endl;
    
    outfile.close();
    
    		return 0;
    	}
    This is just to give you a general idea. I didn't look at this carefully or try to compile it, but you should have a better idea of what I mean.

    EDIT: It would also probably be better idea to use a string and not a char array. I don't have time to keep checking back on this post so maybe someone else can chime in and offer some advice. Good luck.
    Last edited by ttrz; November 1st, 2010 at 03:39 PM.

  14. #14
    Join Date
    Oct 2010
    Posts
    20

    Re: Extracting a line from content in the line

    Quote Originally Posted by ttrz View Post
    Well, if you were going to do it the way I suggested, you wouldn't write to the output file until the user decided to quit.

    Right now you are getting input and then writing directly to the output file.

    Instead of doing that, you could probably make an array (or even better, a vector) of residents and store the input in the array.

    I don't really have time to work through the whole thing right now, but here is a quick example of how it might work.

    Code:
    const int ARRAY_SIZE = 50;
    AddBook resident[ARRAY_SIZE];
    
    int index = 0; //Keep track of how many array slots you are actually using
    
    do {
    cout << "Pick your option.." << endl;
    cin >> Ans;
    
    	if ( Ans == 'A'|| Ans=='a' )
    	{
    		if(index == ARRAY_SIZE){
    			cout << "Address book is full! Please delete an entry to make room!" << endl;
    			continue;
    		}
    
    		
    		cout<<endl<<"You've chosen to add a person to the address book."<<endl<<" Please enter the person's name: " ;
    		cin.ignore();
    		cin.getline(resident[index].Name, 25); //Store the input into the array. Don't write to the output file yet.
    
    		//Get the rest of the input, etc
    
    		index++;
    	}
    	else if (Ans== 'D'|| Ans=='d') 
    	{
    		if(index == 0){
    			cout << "No entries to delete!" << endl;
    			continue;
    		}
    		cout<<endl<<"You've chosen to delete a person from the address book. Please enter a phone number: " ;
    
    		//Some logic here to find out which entry to delete. Let's say you store the index to delete in indexToDelete
    
    		resident[indexToDelete] = resident[index - 1]; //Overwrite whatever was there
    		index--;
    
    	}
    
    	else if (Ans== 'Q'|| Ans=='q') 
    	{
    		cout <<endl<< "Goodbye"<<endl<<endl;
    
    		ofstream outfile("test.txt");
    
    		for(int i = 0; i < index; i++)
    			outfile << resident[index].name << " " << resident[index].number << " " << resident[index].address << endl;
    
    		return 0;
    	}
    
    
    }
    That is to give you an idea of the type of checking you will have to do if you use an array.

    If you use a vector, you can see how it might be easier:

    Code:
    vector<AddBook> residents;
    AddBook temp;
    
    //etc.. 
    //enter do/while loop and print menu etc
    
    	if ( Ans == 'A'|| Ans=='a' )
    	{
    		
    		cout<<endl<<"You've chosen to add a person to the address book."<<endl<<" Please enter the person's name: " ;
    		cin.ignore();
    		cin.getline(temp.Name, 25); //Store the input into temp object. Don't write to the output file yet.
    
    		//Get the rest of the input, etc
    
    		residents.push_back(temp);
    	}
    	else if (Ans== 'D'|| Ans=='d') 
    	{
    		if(residents.empty()){
    			cout << "No entries to delete!" << endl;
    			continue;
    		}
    		cout<<endl<<"You've chosen to delete a person from the address book. Please enter a phone number: " ;
    
    		//Some logic here to find out which entry to delete. Let's say you want to delete the third element.
    		residents.erase(residents.begin() + 2);
    
    	}
    
    	else if (Ans== 'Q'|| Ans=='q') 
    	{
    		cout <<endl<< "Goodbye"<<endl<<endl;
    
    		ofstream outfile("test.txt");
    
    		for(int i = 0; i < residents.size(); i++)
    			outfile << resident[index].name << " " << resident[index].number << " " << resident[index].address << endl;
    
    outfile.close();
    
    		return 0;
    	}
    This is just to give you a general idea. I didn't look at this carefully or try to compile it, but you should have a better idea of what I mean.

    EDIT: It would also probably be better idea to use a string and not a char array. I don't have time to keep checking back on this post so maybe someone else can chime in and offer some advice. Good luck.
    It just seems like my way is way easier, if only I could find a way to extract an entire line given the contents of a line I'd be set!

  15. #15
    Join Date
    Sep 2010
    Posts
    66

    Re: Extracting a line from content in the line

    Quote Originally Posted by wiec7548 View Post
    I actually solved that problem, a different way than you however.
    Yes, you are storing the input in a character array, and designating a maximum number of characters to read in getline(). If the input is larger than the maximum you have specified, you will run into a problem.

    It just seems like my way is way easier, if only I could find a way to extract an entire line given the contents of a line I'd be set!
    So for every search you want to read the input file again? And every time you need to add an entry you will write to the output file on demand?

    I was under the impression that hard disk read/writes likes this were expensive. Perhaps someone more experienced could explain why I am wrong.
    Last edited by ttrz; November 3rd, 2010 at 12:53 AM.

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  





Click Here to Expand Forum to Full Width

Featured