I am using Qt 5.2.1 and here is part of a function that I want to use in my program -
while( getline(in,str,':')
{
getline(str,'\n');
int var = atoi(str.c_str());
}
my question is how can I implement this in qt?
I searched the docs a bit and found out about readline and split but I dont know how to use them
any help is much appreciated. :D
Edit - my first getline checks for ':' in the text file and the second one picks up the number (that comes after ':') and converts it into a integer and stores it in a variable.
2 edit :
Here's how my text file looks like...
500 - 1000 : 1
1000 - 1500 : 2
1500 - 2000 : 7
2000 - 2500 : 6
the 1, 2, 7, 6 are the values that I need in my program
I'm not totally sure what you're trying to do. If you're trying to read a file:
QFile file("/path/to/file.whatever");
if (!file.open(QIODevice::ReadOnly | QIODevice::Text) {
// error message here
return;
end
while (!file.atEnd()) {
QString line = in.readLine();
// now, line will be a string of the whole line, if you're trying to read a CSV or something, you can split the string
QStringList list = line.split(",");
// process the line here
}
QFile closes itself when it goes out of scope.
If you're trying to split a string based on the : delimiter you have there, use:
QStringList list = line.split(":");
EDIT:
Now that you defined what you want to do (read a like like this "value:integer"), you can easily do that with QStringList. Example:
QString input = "value:1";
QStringList tokens = input.split(":");
int second = tokens.at(1).toInt();
Of course, you'll need to use your own error checking, but this is an example of what I think you're trying to do.
Related
So I'm trying trying read a file into several objects, and right now I'm practicing by trying to insert a single line into a single object. This the object class I'm trying to insert the file in:
Cust(string name, bool robber, int time, int items)
{
m_name = name;
m_robber = robber;
m_time = time;
m_items = items;
}
After reading the file, I try to insert them into the object and print the object to see if it successfully came out. I know the print function works just fine, so there's no reason to worry about that.
ifstream my_ifile(argv[3]);
string k_name;
bool k_robber;
int k_time;
int k_items;
my_ifile >> k_name;
my_ifile >> k_robber;
my_ifile >> k_time;
my_ifile >> k_items;
Cust k_customer(k_name, k_robber, k_time, k_items);
k_customer.print(cout);
The file I'm putting in has one line.
Robbie true 1 2
And the print function should print "Robbie robber 1 2". Instead this is the output I get:
shopper 638496768 32631
It starts with a space, it's set to shopper instead of robber, the numbers are incorrect, the name is omitted entirely and the file's contents are erased. Does anyone know why this is happening?
Also how would I read through two or more lines? I.e.
Robbie true 1 2
Shaun false 3 4
Thanks for the help!
I am new to file-handling...
I am writing a program that saves data in text-files in the following format:
3740541120991
Syed Waqas Ali
Rawalpindi
Lahore
12-12-2012
23:24
1
1
(Sorry for the bad alignment, it's NOT a part of the program)
Now I'm writing a delete function for the program that would delete a record.
So far this is my code:
void masterSystem::cancelReservation()
{
string line;
string searchfor = "3740541120991";
int i=0;
ifstream myfile("records.txt");
while (getline(myfile, line))
{
cout << line << endl;
if (line==searchfor)
{
// DELETE THIS + THE NEXT 8 LINES
}
}
}
I've done a bit of research and have found out that there is no easy way to access the line of a text file so we have to create another text file.
But the problem arises that how do I COPY the records/data before the record being deleted into the NEW text file?
Open the input file; read one line at a time from the input file. If you decide to want to keep that line, write it to the output file. On the other hand, if you want to 'delete' that line, don't write it to the output file.
You could have a record per line and make even more easy for example:
3740541120991|Syed Waqas Ali|Rawalpindi|Lahore|12-12-2012|23:24|1|1
and the | character saparating each field. This is a well known technic knows as CSV (Comma separated Values)
This way you don't have to worry about reading consecutive lines for erase a record and add a record access the file only once.
So your code becoms into:
void masterSystem::cancelReservation()
{
string line;
string searchfor = "3740541120991";
ifstream myfile("records.txt");
while (getline(myfile, line))
{
// Here each line is a record
// You only hace to decide if you will copy
// this line to the ouput file or not.
}
}
Don't think only about removing a record, there are others operations you will need to do against this file save a new record, read into memory and search.
Think a moment about search, and having your current desing in mind, try to answer this: How many reservations exists for date 12-12-2012 and past 12:00 AM?
In your code you have to access the file 8 times per record even if the other data is irrelevant to the question. But, if you have each record in a line you only have to access file 1 time per record.
With a few reservations the diference is near 0, but it grows exponentially (n^8).
Let's say I write some information in a file, and it writes with n cycles, for example as follows:
a,a,a,a,
b,b,b,b,
c,c,c,c,
a,a,a,a,
b,b,b,b,
c,c,c,c,
.......
a,a,a,a,
b,b,b,b,
c,c,c,c,
Now I want to open the file check the first line, find where it repeats and delete everything after that. For my example case let's say I want to wind where a,a,a,a, meets again, and to delete it, and everything after that, getting the follows instead:
a,a,a,a,
b,b,b,b,
c,c,c,c,
Q: How can I do that?
You can use QTextStream to stream your file (so, do not care about RAM).
Then use readLine() function to read one line at a time to QString, and compare with new line.
Here some code sample:
int lineCounter = 0; //count for line
QFile f(filePath);
if (!f.open(QIODevice::ReadOnly | QIODevice::Text))
return false;
QTextStream stream(&f);
QString line;
// read the first line
line = stream.readLine();
lineCounter++;
QString hash = QString(QCryptographicHash::hash(line.toAscii(), QCryptographicHash::Md5).toHex());
do
{
line = stream.readLine();
if (QString(QCryptographicHash::hash(line.toAscii(), QCryptographicHash::Md5).toHex()).compare(hash) == 0)
{
// Save data from 1st line to "lineCounter" to new file, or do your own works;
// and then break;
}
lineCounter++;
} while (!line.isNull());
You want to remove duplicate lines in a file. If you follow the next steps you will get what you want.
Create a vector that will store the hashes of unique lines ( QVector<QString>) Notice that using QMap would be faster.
Create an ouput file
For every line in the file calculate it's hash. Use QCryptographicHash or qHash (in this case you should have a vector of uints.
If the calculated hash is contained in the vector skip this line
Otherwise add the hash to the vector and print the line to the output file.
At the end the output file should contain only unique instances of the input file.
I'd like to ask your help with my little school project.
The task is to determine a person's gender (using 2 radio buttons) and then pick a random Japanese family name and male/female middlename. And there's the rest of the task, but it's nothing compared to this part :(
Thing is, i have managed to make the 3 .txt files (familynames.txt, malemiddlenames.txt and femalemiddlenames.txt) look like the following:
1,Akiro
2,Sakura
3,etc...
What i'd like to do is create a random number, and read the lines until it arrives to the line with the same number as my random number, then cut the number and the comma off, and display the name on the corresponding label. So far this is what i've got:
void MainWindow::famname()
{
QString familyname;
int famrand =qrand() % 76;
ui->label_2->setText(QString::number(famrand));
int i = 1;
QFile famfile("C:\Users\Ryseth\gyakorlas\_familynames.txt");
QTextStream in(&famfile);
if(famfile.open(QIODevice::ReadOnly)){
while (!in.atEnd()) {
QString line = in.readLine();
i++;
if(i==famrand){
QStringList line2 =line.split(',');
familyname = line2.at(0);
ui->label_2->setText(QString::number(famrand)+" "+QString::number(i));
ui->FamilyLabel->setText(familyname);
}//IF
}//WHILE
}//IF
famfile.close();
}//NGEN
If any of you could think of some sort of solution or if you have ANY suggestions, please don't hasitate to share it with me :D
Thank you, and have a nice day/night : Ruben
I think with Boost::Spirit::Qi you could parse your file into a std::vector< std::string > and do your operation with simple c++ methods.
But to help you with your Qt-Solution:
You never check if int famrand =qrand() % 76; produces a legal number, are there enough entries in your text file ...
int i = 1; This integer is unnecessary, the number is within the text file ...
My solution (untested):
while (!in.atEnd()) {
QString line = in.readLine();
QStringList list = line.split(",", QString::SkipEmptyParts);
bool ok;
int idx = list.at(0).toInt(&ok);
if (ok && idx == famrand) {
familyname = list.at(1).trimmed();
// ... do with your ui whatever you want
}//IF
}//WHILE
Keep in mind you have to do error handling if the conversion of string to int fails and/or the accessors of list throw (list.at(xx))
The positive thing is, you dont need an ordered text file!
I don't really understand what you are managing to do but at this line I guess you are getting the number, not the familyname.
familyname = line2.at(0); // number
familyname = line2.at(1); // family name
I would like to read from a text file and the format of the file is
Method 1
Method 2
Insert 3 "James Tan"
I am currently using ifstream to open the text file and read the items, but when I use >> to read the lines, which is causing the name not to be fully read as "James Tan".
Attached below is the code and the output.
ifstream fileInput;
if(fileInput.is_open()){
while(fileInput.good()){
fileInput >>methondName>>value>>Name;
......
Output
methodName = Method, Method, Insert
value = 1, 2, 3 (must be a usigned integer)
Name = James
What is the better way to process the reading of the lines and the contents.
I was told about getline. But i understand that getline reads fully as a line rather than a single word by single word.
Next is fstream really fast?. cause, I would like to process 500000 lines of data and if ifstream is not fast, what other options do I have.
Please advice on this.
Method 1
Method 2
Insert 3 "James Tan"
I take it you mean that the file consists of several lines. Each line either begins with the word "Method" or the word "Insert", in each case followed by a number. Additionally, lines that begin "Insert" have a multi-word name at the end.
Is that right? If so, try:
ifstream fileInput("input.txt");
std::string methodName;
int value;
while ( fileInput >> methodName >> value ) {
std::string name;
if(methodName == "Insert")
std::getline(fileInput, name);
// Now do whatever you meant to do with the record.
records.push_back(RecordType(methodName, value, name); // for example
}