How to search in a file the best, easiest way? - c++

Can somebody tell me if this is a good way to search an account by an id, and to output all data about him? If not, which is the best way?
I have this:
void account::showacc() {
ifstream inFile;
inFile.open("account.dat",ios::binary|ios::in|ios::app);
int accnum1,n;
cout<<"Enter account num: ";
cin>>accnum1;
n=test();
for(int i=0;i<n;i++)
{
inFile.read((char*)&acc,sizeof(acc));
if(accnum==accnum1)
{
cout<<"account number is: "<<accnum<<endl;
cout<<"The possesor's name is :"<<name;
}
}
inFile.close();
}
And the test() is:
int account::test()
{
ifstream inFile;
inFile.open("account.dat",ios::binary|ios::in|ios::app);
inFile.seekg(0,ios::end);
int n;
n=inFile.tellg()/sizeof(acc);
inFile.close();
return n;
}

Well, this would work, but it's going to be slow ... depending on how big your file is, and how long your program runs (i.e., if it's a persistent program running in the background or a service of some type), it would be a much better idea to memory-map the file, and/or read the entire file into a std::stringstream, and then scan the stored file in memory. Again, this will all depend on how big your file is, and how persistent the reading program is. If it's a huge file, and your program is only run once and then quit, then yes, your current method is okay.

You could make it much more efficient by changing the for loop. As it is, it looks like you go through the entire file, even if you find the account number. Assuming that there are no duplicate numbers, you should set it up to terminate if it finds the the number.

Depending on your use case, you might be better off using a database engine such as sqlite and let it take care of the searching for you. Sqlite exists as a C++ library that you can use in your program.

Related

C++ Way to make a counter for instances when a variable in a file being read equals a user input

My specific program basically sparses through a csv file and asks for user input in the form of whether they would like to know how many times goods where delivered by Bike, Car, or Foot, all of this information is stored in the file being read. My issue is I don't know how to build a counter for the code so like when it sparse through the file looking for a string that matches the user input (Bike, Car, or Foot) and then counts all occurences and returns that value to display to the user. Here is my counter method right now that only returns zero and I have no clue what the logic i should use here is.
I also think it is important to mention that p is given by a getvariable method so p equals the user input
int transport::counttimes(string p)
{
ifstream inFile;
inFile.open("donationDataFixed.csv");
int c=0;
string s;
string piece;
while(s!=p)
{
stringstream data(s);
getline(data,piece,',');
getline(data,piece,',');
getline(data,piece,',');
getline(data,piece,',');
getline(data,piece,',');
getline(data,piece,',');
getline(data,piece,',');//transportation mode
if (s==p)
{
c=c+1;
}
}
return c;
}
If that is your entire source, then I can tell you that you never assign "s" a string value.
Since "s" never has a string value, your counter never increments, hence you will always return 0.
Also you don't have logic to parse the entire file. There are several ways to do this. You can look at this post for looping the entire file.
How To Parse String File Txt Into Array With C++
There are a plenty of ways parsing csv files. Your choice may depends on the libraries you are using/want to use (std, boost, ...)
A good post with pros and cons and several examples can be found here

Program Almost Runs ,Trouble With File Operation

The program almost runs but i am not sure how to make the .txt file for this , its not giving me an error.
the project asks me to:
" File encryption is the science of writing the contents of a file in a secret code. Your encryption program should work like a filter, reading the contents of one file, modifying
the data into a code, and then writing the coded contents out to a second file.
The second file will be a version of the first file, but written in a secret code. Although there are complex encryption techniques, you should come up with a simple one of your own. For example, you could read the first file one character at a time, and add 10 to the ASCII code of each character before it is written to the second file. "
#include <iostream>
#include <fstream>
using namespace std;
int main()
{
char ch;
fstream fin, fout;
fin.open("testone.txt", ios::in);
fout.open("encrypted.txt", ios::out);
while (!fin.eof())
{
fin.get(ch);
fout.put(ch + 10);
}
fin.close();
fout.close();
system("pause");
return 0;
}
Read this -
Error LNK1561: entry point must be defined
https://social.msdn.microsoft.com/Forums/vstudio/en-US/e1200aa9-34c7-487c-a87e-0d0368fb3bff/error-lnk1561-entry-point-must-be-definedproblem-in-c?forum=vclanguage
Not up on my Visual C, but you may need #include <cstdlib> to get system
LNK1561 means your main function can't be found. Clearly the main function is present, so this should compile. Follow Beta's suggestion and ensure you can compile and run a trivial program.
Putting Compiling issues aside, This code won't work.
Overarching Problem: You are not checking for any errors along the way, so there is no way for your program to tell if anything has gone wrong.
For example, what if the file didn't open? The while (!fin.eof()) becomes an infinite loop. If the file is not open, you can never read EOF. Trying to use EOF as a loop condition is a bad idea anyway. Definitely read the link in #Steephen's comment.
If you fail to read a character with fin.get(ch); then what? The current code tries to use the character anyway. Bad idea.
Testing a stream is pretty simple. if (!fin) does the job. Read up on how streams work to learn why. Thius simple test doesn't tell you what went wrong, but at least you know something went wrong.
To make things easier, most stream functions return the stream. This lets you chain stream operations together and makes if (!fin.get(ch)) an easy way to tell if get worked.
So your IO loop can be as simple as
while (fin.get(ch) && fout.put(ch + 10))
{
}
If get couldn't get ch for any reason--unopened file, end of file, unreadable file--the while loop exits. Afterwards you can query fin to find out why. If EOF, awesome. If not EOF, the output file's probably wrong.
The same applies to put. If put failed, the loop ends. Test for why and decide if you want to keep the file.
I also recommend dropping a quick test at the end of main to print out a check.
fin.open("encrypted.txt", ios::in);
while (fin.get(ch) && std::cout.put(ch - 10))
{
}
A better test would be to read the character, undo the encryption, and compare against the original input.

Taking the contents of a vector and placing them in a text file

I'm working on an assignment for my computer science class, its a first year course as I'm a beginner and I am having trouble with a certain part.
A quick explanation of what my assignment does is:
It takes information from a text file and puts it in a vector while the program is running, and you can add names to it or remove names from it, and once you are done you need it to save the information, which means you have to take the information back out of the vector and replace it into the text file.
I haven't learned of a way to take information out of a vector and back into a text-file, I saw that a classmate of mine posted on here a few times but he was pretty much dismissed so he told me to ask the question for myself.
We were given a bit of the coding for our program and honestly I have got no clue on how to make the function take the information back out of the vector and into the text file updated.
What ive included:
#include <iostream>
#include <string>
#include <vector>
#include <fstream>
here is the function in which it would save into, any help would be greatly appreciated.
void quit_program(string strFileName, vector<string>&vecThisStudent)
{
//write the body of the function
//Hint: this is the function you should write the vector’s content back to the file.
cout<<"Thanks for using the program. Program terminated"<<endl;
}
As you can see we were even given the hint on what the function was supposed to do, but anyone I have spoken to from the class hasnt had a clue on how to get it done (or they dont like me enough to tell me)
If the entire program is needed, I can post it. It looks almost identical to my classmate who posted earlier, but that is just because we were given the majority of the code and we just had to complete a few different things, and I've just been stuck here for the last 10 hours or so.
My read_file
int read_file(string strFileName, vector<string>&vecThisStudent, fstream &inFile)
{
string strFirstName
string strLastName;
inFile.open(strFileName.c_str(), ios::in | ios::out | ios::app);
while (inFile >> strFirstName >> strLastName)
{
vecThisStudent.push_back(strFirstName + " " + strLastName);
}
return 0;
}
Split the problem into sub-problems. Keep splitting to a smaller pieces till each piece is manageable.
In your case sub-problems I would be comfortable working with are "C++ performing action at program exit", "C++ container serialize", "C++ file IO".
The first one will give you C: Doing something when the program exits, the second - ostream iterator usage in c++, and finally the third one - Writing in file C++.
As a final step you just need to combine all three back together.
And Steve, do not blame your professor or your destiny. Being a good programmer is as hard as being a good surgeon, as hard and as rewarding, but requires quite a bit of dedication to grow from mediocrity to a sharp Swiss Army Knife. At your first job interview you'll see how much worse questions can be than ones asked in these assignments.
Seeing your lack of C++ knowledge, I would REALLY suggest watching some tutorials about C++. If you don't know what a for-loop is/how to use it, you will have MAJOR problems with future assignments.
Here are some great series of tutorial.
There's no such thing are taking the contents of a file (or vector) and placing it automatically into a vector (or file).
But to read or write data, take a look at this page.
The general idea of reading a file is:
Iterate though the file and read each input one by one.
Place that input into a vector
The general idea of outputting data to a file is:
Iterate though the data (ex: every element of that vector)
Output that data (ex: that element).
By iterating, I mean running though the data (usually by a for-loop):
int write_file(string strFileName, vector<string>&vecThisStudent, fstream &outFile)
{
outFile.open(strFileName.c_str(), ios::in | ios::out | ios::app);
for (int i = 0 ; i < vecThisStudent.size() ; i++) {
//Use this line to output to console
cout << vecThisStudent[i] << " \n";
//Use this line to output to file
outFile << vecThisStudent[i] << "\n";
}
}
Use ofstream
http://www.cplusplus.com/reference/fstream/ofstream/
Open File..
Write data using << (http://www.cplusplus.com/reference/ostream/ostream/operator%3C%3C/)
Close file..
I am not sure what exactly you stuck with..

Password Manager - Continuing / Long-Term Things

Okay, I know very well how everybody feels about homemade password managers, but I would like help with mine. Not for actual use, just for the sake of learning.
I was wondering, in C++ how to have long-term variables. Or really, have anything long-term.
What do I mean by long-term? Something that is saved or continues upon next run of the .exe. In my case, I want where, the first time you run the program it asks you to enter an access password, so next time you launch the program, you will have to type the password chosen when you first launched.
Currently, I just use an if() statement to check if password is equal to my desired password, and if it is, to run. However, that is far from actually effective and isn't very practical.
Something I thought of was to create a text file somewhere containing the access password, and read it, but that kind of defeats the purpose of a password manager.
Every variable in your program is only in memory and lost at exit. You must store it on your disk and later read it from there.
There are many ways to do that directly or indirectly.
A very simple low level way is to use ofstream and ifstream. E.g.:
#include <iostream>
#include <fstream>
int main() {
using namespace std;
int counter = 0;
// try to load counter from file
{
ifstream myfile("mycounter.txt");
if (myfile.is_open())
{
myfile >> counter;
}
myfile.close();
}
cout << "current counter: " << counter << endl;
// save counter to file
{
ofstream myfile;
myfile.open("mycounter.txt");
myfile << counter << endl;
}
}
You might be more comfortable with the C-functions fopen, fread, fwrite, fclose, etc.
Then, there are databases and there are easy libraries to use such databases. Check out sqlite, you can use it from C++.
You could start a database or save/write the data into files.

C++ filestream problem

I'm making a simple game in C++ and I want the highest score at the end of the game to be written in a text file. I'm using fstream to first read the last saved highscore and compare it to the new highscore. The output in the text file looks like this (0НН) and it shouldn't. I'm realy frustrated with this.
Here's a part of my code.
double score_num=0;
fstream datafile("score.pon"); //Declaration of variables
...
if(SPEED>score_num)
{
score_num=SPEED;
}
//getting the score
...
datafile<<score_num; //Writing it to the file
#include <iostream>
#include <fstream>
using namespace std;
#define SPEED 12
int main()
{
double score_num=0;
ofstream datafile("score.pon"); //Declaration of variables
if(SPEED>score_num)
{
score_num=SPEED;
}
//getting the score
datafile<<score_num; //Writing it to the file
return 0;
}
Replaced fstream by ofstream works like a charm. Perhaps you should show more code? Also, closing the file is good habit:
datafile.flush();
datafile.close();
I'll leave errorhandling to you
Hacky solution - open the file as an ifstream, read existing value, close it, adjust score, open file as an ofstream, write score, close it. Alternatively, investigate the use of the seekp() function, and write the score as a binary value, not as text.
My best guess as to why the original was failing is that when you read the last character from a file, the EOF bit is set. In this state, all read & write operations fail. You can write to a file stream that's reached its end by calling clear first.
// the following doesn't truncate file, or handle other error conditions.
if (datafile.eof()) {
datafile.clear();
}
datafile.seekp(0, std::ios_base::beg);
datafile << score_num;
However, this won't solve all your problems. If you write less to the file than its current length (e.g. the old high score was "1.5" and the new high score is "2"), part of the old data will still be present at the end of the file. As long as scores never have a fractional part (in which case you should probably be using an integer type, such as unsigned long), you won't notice the bug, since a < b ⇒ len(a) ≤ len(b). To handle this properly, you'll need to use unapersson's recommended approaches (which will either truncate the file or always write the same amount of data to the file), or use a different I/O library (such as your platform's C library or boost) which provide a way to truncate files (such as the POSIX ftruncate).