PDA

View Full Version : C++ new hand problem please help




chunhohuen
Apr 18, 2011, 10:53 AM
Dear alls
I am a extremely new hand of c++ user.
Thus, I wish I can get some help in here.:)


I am writing a program to input a name and save in a file.
However, my problem is I want to write a function to find the worlds and show it inside the file.

For example:
I input some data like Peter, May and Joe.
Then after write and read, when the user input Peter and run the function find(), it can search the file and show Peter if Peter is existed, else run the function setuser() and let the user input the name.

My problem is I do not know how to write the function find() by using if else.....:(

Thank you for all the attentions!:)

Here is my program:
#include <iostream>
#include <fstream>
#include <string.h>
using namespace std;


char inputusername[99];// let the user to input the user name

void find();


void setuser() //function of set the username
{
cout<<"Enter the username: "<<endl;
cin>>inputusername;
int score=0;
}


void read() //read the file and show the details
{
cout<<endl;
ifstream fin("file.cpp");
char ch;
while (fin.get(ch))
cout<<ch;
fin.close();
}



void write() //read the input to the file
{
ofstream fout ("file.cpp",ios::app);
fout<<inputusername<<endl;
fout.close();
}



void find()// find the input either is match the file
// if yes, cout the data
// if not, run the function setuser()
{
ifstream fin("file.cpp");
char *search;

}


int main()
{

int choice=0, number=0;

bool entered=false;
do {
cout <<endl;
cout << "Please choose an option below:\n\n";
cout << "1. input\n";
cout << "2. write\n";
cout << "3. read\n";
cout << "4. find\n";
cout << "5. Quit\n";
cin >> choice;


switch(choice) {
case (1) : { setuser();break;}


case (2) : {write(); break; }


case (3) : { read(); break; }


case (4) : { find(); break; }


case (5) : { break; }




}
}
while(choice != 5);

return 0;
}



subsonix
Apr 18, 2011, 11:24 AM
Although it is possible to search "on the disk" what you want is to read in all data in memory and do the search there because disk i/o is slow and hard to manage. So, read in all data into a data structure like a vector. Then you can iterate through the vector linearly and compare each index to the search term, if it's found return, else report not found.

Hope I got the question BTW, not sure.

chunhohuen
Apr 19, 2011, 05:30 AM
Although it is possible to search "on the disk" what you want is to read in all data in memory and do the search there because disk i/o is slow and hard to manage. So, read in all data into a data structure like a vector. Then you can iterate through the vector linearly and compare each index to the search term, if it's found return, else report not found.

Hope I got the question BTW, not sure.

Thank you for answering me:)
I am sorry, I dont' know how to compare each index to the search term....:(.....

Sander
Apr 19, 2011, 06:35 AM
Don't call your data file "file.cpp" - it's not a C++ file. From the fact you mention "score" in your code, I think you're trying to make a high-score list? Subsonix is right; unless your data is really big, just load the entire thing in memory and perform the search there.

If it is indeed a high score list, look into the std::map data structure, which you could use to store the name-score pairs. It's really simple to look things up in there as well.

Not spelling out the solution for you in case this is a homework assignment :)

ehoui
Apr 19, 2011, 08:08 AM
Although it is possible to search "on the disk" what you want is to read in all data in memory and do the search there because disk i/o is slow and hard to manage. So, read in all data into a data structure like a vector. Then you can iterate through the vector linearly and compare each index to the search term, if it's found return, else report not found.

Hope I got the question BTW, not sure.

While that may be true, that approach doesn't scale for large files, but in any event, I think your recommended approach may not be the simplest method which the OP should try first before moving onto more advanced concepts like indices.

OP: based on your write() command, your file structure is essentially user names appearing on a single line in a text file. E.g.,
John
Mark
Amy
...
Mark
Mark

A couple of problems with your write(), as illustrated by the last two lines above, is that it appears possible to write the same user name multiple times in your file. I don't know if that is unintentional or not. In any case, your find will need to do this:


while file still has unread lines:
read a line
compare the read line with the inputted line
if they are the same, print it


I didn't write the code, because I assume you'd be interested in learning how to do each of those above. You'll find plenty of examples online on how to read a text file in line-by-line and you'll find plenty of examples on how to compare strings. I think you'll be able to construct your find() command by referring to those examples, writing the code, and debugging it until it works.

subsonix
Apr 19, 2011, 08:21 AM
While that may be true, that approach doesn't scale for large files, but in any event, I think your recommended approach may not be the simplest method which the OP should try first before moving onto more advanced concepts like indices.


I does if you read in data in chunks: "if not found in current chunk" move on to the next etc.

Although, one could say that even if you are reading "one line at a time" from the file, your reading from a buffer, so in effect you are searching in memory but in a harder to manage way.

What I mean is, you need to consider things like flush, sync and rewind operations, not to mention if you want to add functionality like the ability to remove items from the file, sort it etc.

BTW, one benefit of using a map that was mentioned, is that it has a find function. :D

ehoui
Apr 19, 2011, 11:15 AM
BTW, one benefit of using a map that was mentioned, is that it has a find function. :D

How about the OP first try to read and compare one line at a time and then progress to a map if s/he is successful?

subsonix
Apr 19, 2011, 11:29 AM
How about the OP first try to read and compare one line at a time and then progress to a map if s/he is successful?

What is the most simple depends on if this is just names or key/value pairs like in a high score list that was mentioned. Doing this by hand, parsing strings, validating them, search a data structure manually, seems harder than using a pre-defined function in STL.

I agree that reading a line at a time from a file is the most simple if that is all. But here there seems to be a menu involved, with ability to add, and search for items. So, open the file in append mode, add item, flush the buffer to disk, rewind, or (file.seekg(0, ios::beg);) before searching.

ehoui
Apr 19, 2011, 11:39 AM
What is the most simple depends on if this is just names or key/value pairs like in a high score list that was mentioned. Doing this by hand, parsing strings, validating them, search a data structure manually, seems harder than using a pre-defined function in STL.

I agree that reading a line at a time from a file is the most simple if that is all. But here there seems to be a menu involved, with ability to add, and search for items. So, open the file in append mode, add item, flush the buffer to disk, rewind, or (file.seekg(0, ios::beg);) before searching.

Look at the OP's code. The OP needs to start simple. I'm not going to debate you with your suggested improvements. But if the OP can't read a file one line at a time and compare, s/he can't read a file into a map and use the find method.

Why not have the OP link in a btree library or store and retrieve info from a DB (e.g., sqlite) and use that...? Because s/he probably can't at this stage and leading them down this path will result in frustration and further confusion.

subsonix
Apr 19, 2011, 11:52 AM
Ok it's a valid and good point. Then store the search term in a string, read one line at a time into a temporary string and compare them.

The string class has a compare() function which returns 0 on a match.

http://www.cplusplus.com/reference/string/string/compare/

And a fstream object can be used like this:


while( file >> string ) {
// compare here, break if found
}


Which will effectively read from the file one line at the time, until there is nothing more to read.

chunhohuen
Apr 21, 2011, 10:43 AM
THX all the reply!:)

Now
I write the find function as:

void find()
{
string str1 (file.txt);
string str2 (inputusername);

if (str1.compare(str2) != 0)
cout << str1;
}

However, it can not run:(.....

What I want to do are:

1.Set str1 as the file.txt
2.Set str2 as inputusername
3. Use a if statement to find the inputerusername information in the file.txt
4.cout the match content of file.txt

subsonix
Apr 21, 2011, 11:02 AM
Just like in your first version of find() in your first post, you need to open the file for reading. That is, the file.txt should be opened for reading.

You then need to ask for a search term (in your case a user name).


ifstream file;
file.open("file.txt);

string inputusername;
string input_line;

cout << "What name do you want to search for? ";
cin >> inputusername;

while( file >> input_line ) {
if( input_line.compare(inputusername) == 0 ) {
cout << "The name " << input_line << " was found in file.\n";
break;
}
}

file.close();

chunhohuen
Apr 21, 2011, 12:13 PM
Just like in your first version of find() in your first post, you need to open the file for reading. That is, the file.txt should be opened for reading.

You then need to ask for a search term (in your case a user name).


ifstream file;
file.open("file.txt);

string inputusername;
string input_line;

cout << "What name do you want to search for? ";
cin >> inputusername;

while( file >> input_line ) {
if( input_line.compare(inputusername) == 0 ) {
cout << "The name " << input_line << " was found in file.\n";
break;
}
}

file.close();


Thank you very much!:):rolleyes:

I can do the search now and learn a lot but I rewrite the function and there is a problem.

for example the txt file is included:
peter
may
joe


1.The user selects 1.setuser() and input peter. Then select 4.find(), it can show peter on the screen.

2.When the user selects 1 again and input may.

3.Use find() cannot show may but the not found message (I write else statement to test the function.

The problem is :How to search all the content in the txt file?


The code:

void find()

{

ifstream file;
file.open("file.txt");

string input=inputusername;
string input_line;

while( file >> input_line ) {
if( input_line.compare(input) == 0 ) {
cout << "The name " << input_line << " was found in file.\n";
break;
}

else // Testing the name is existed or not.
cout<<"The name cannot found"<<endl;
break;

}

subsonix
Apr 21, 2011, 12:38 PM
1.The user selects 1.setuser() and input peter. Then select 4.find(), it can show peter on the screen.

2.When the user selects 1 again and input may.

3.Use find() cannot show may but the not found message (I write else statement to test the function.

The problem is :How to search all the content in the txt file?


The code:

void find()

{

ifstream file;
file.open("file.txt");

string input=inputusername;
string input_line;

while( file >> input_line ) {
if( input_line.compare(input) == 0 ) {
cout << "The name " << input_line << " was found in file.\n";
break;
}
else { // Testing the name is existed or not.
cout<<"The name cannot found"<<endl;
break;
}
}




That will not work, as that part will be executed every time the lines doesn't match. So, all lines that doesn't match will trigger the else part. (I added braces { } BTW)

What you need to do is to use a flag, that you set to true if found, then after the loop, test if found == false, if so print the message.


ifstream file;
file.open("file.txt");

string input=inputusername;
string input_line;
bool found = false;

while( file >> input_line ) {
if( input_line.compare(input) == 0 ) {
cout << "The name " << input_line << " was found in file.\n";
found = true;
break;
}
}

if( found == false ) {
cout << "The name " << inputusername << " wasn't found in file.\n";
}

file.close();



Edit:

BTW I see that inputusername is a global variable, that is also a char array. It's better to declare it as string, as it's supported by C++. And preferably it shouldn't be a global variable. Now your find() function takes no arguments, it's better to take a string as argument, (the search term) so you would declare it like this:


void find(string search_term) {
// use the search_term that you supply when calling find.
}

// Then in main when you use your function you can call it like this

find("John");

// Or use a variable like userinputname or something else.

chunhohuen
Apr 22, 2011, 01:43 AM
That will not work, as that part will be executed every time the lines doesn't match. So, all lines that doesn't match will trigger the else part. (I added braces { } BTW)

What you need to do is to use a flag, that you set to true if found, then after the loop, test if found == false, if so print the message.


ifstream file;
file.open("file.txt");

string input=inputusername;
string input_line;
bool found = false;

while( file >> input_line ) {
if( input_line.compare(input) == 0 ) {
cout << "The name " << input_line << " was found in file.\n";
found = true;
break;
}
}

if( found == false ) {
cout << "The name " << inputusername << " wasn't found in file.\n";
}

file.close();



Edit:

BTW I see that inputusername is a global variable, that is also a char array. It's better to declare it as string, as it's supported by C++. And preferably it shouldn't be a global variable. Now your find() function takes no arguments, it's better to take a string as argument, (the search term) so you would declare it like this:


void find(string search_term) {
// use the search_term that you supply when calling find.
}

// Then in main when you use your function you can call it like this

find("John");

// Or use a variable like userinputname or something else.


Thankyou very much!:)
I learn a lot and I can use the function now.