I'm completely new to C++, so please give me a change to learn!
Assuming I have a text file RoomDB.txt which stores data in the following format :
005:Room 1:Level 1:3-Jul-14:0900:3:Mathematics 101:Julia Lee
006:Room 2:Level 2:2-Jun-14:0800:2:English 101:Jared Loo
007:Room 3:Level 3:15-Apr-14:1800:3:Chinese 101:David Tay
008:Room 4:Level 4:15-Apr-14:1200:3:Science 101:Michelle Choo
How would I selectively display a particular line (or more) of data based on the fourth field (the date), such that it would look like this - (If i want to display only the lines in which the date is 15-Apr-14)
Booking ID Room No. Level No. Time Duration Subject Lecturer
----------------------------------------------------------------------------------------
007 Room 3 Level 3 1800 3 Chinese 101 David Tay
008 Room 4 Level 4 1200 3 Science 101 Michelle Choo
PS : Notice that the date is excluded from the desired output as it will be used as a criteria for choosing what data is to be displayed. My current code is as follows :
int main()
{
cout << "\nBooking ID Room No. Level No. Time Duration Subject Lecturer" << endl;
cout << "-------------------------------------------------------------------------------" << endl;
string array[50]; // creates array to hold names
short loop=0; //short for loop for input
string line; //this will contain the data read from the file
ifstream myfile ("RoomDB.txt"); //opening the file.
if (myfile.is_open()) //if the file is open
{
while (! myfile.eof() ) //while the end of file is NOT reached
{
getline (myfile,line); //get one line from the file
array[loop] = line;
cout << "At element " << loop << ", value is :" << array[loop] << endl;
loop++;
}
myfile.close(); //closing the file
}
else cout << "Unable to open file"; //if the file is not open output
}
This is a CSV like file with delimiter :, you could:
-read the file line by line using std::getline
-spliting the line by : using Boost String Algorithm.
-loading in a structure or collection for processing.
-output necessary info
Related
I have this homework assignment that has me a little lost. I have been working on this assignment writing my code, erasing, rewrite, repeat etc. Here are the instructions:
Step (1)
Associated with this assignment is a data file called prices.txt. It contains details of the prices for items in a
grocery store. The first column is the barcode for the item (http://en.wikipedia.org/wiki/Barcode) the
second column, starting in position 11, is the product name, and the third column, starting in position 37 is
the product price.
Write a function with the signature int loadData() which prompts the user for the location of the data file
on disk and then loads the data from the file into an array of elements. Each element of the array should be
a struct declared as follows:
struct Item {
string code;
string name;
double price;
};
The array itself should be called items and should be declared at file scope as follows:
const int MAX_ITEMS = 100;
Item items[MAX_ITEMS];
Notice that the array has size 100, so you can assume the number of items in the data file is less than 100.
Therefore, when loadData has finished loading the data into the array some elements in the array will be unused. The function loadData returns the number of items actually loaded into the array.
I am unsure on how to attempt the function described in the instructions. My code:
int loadData () {
string inputFileName;
ifstream inputFile;
int numOfItems = 0;
cout << "Please input the name of the backup file: ";
cin >> inputFileName; //read user input for the location of the
//backup file
inputFile.open(inputFileName.c_str()); //open specified document
if (!inputFile.is_open()) { //If the file does not open the errormsg
cout << "Unable to open input file." << endl;
cout << "Press enter to continue...";
getline(cin, reply);
exit(1);
}
//Not sure where to start. I know I need to get each element from
//each newline.
return numOfItems;
}
I wanted to figure this out on my own but that isn't gonna happen. So if I could just get some hints or even suggested pools of knowledge that would guide me or even give me an idea of where to start.
addition: input file:
10001 Apples (bunch) 4.59
10002 Bananas (bunch) 4.99
10003 Pears (bunch) 5.49
20001 White bread (loaf) 2.69
20002 Brown bread (loaf) 2.89
20003 English Muffins (bag) 3.99
30001 Sugar (5 lb bag) 3.99
30002 Tea (box) 4.29
30003 Folger's Coffee (Can) 13.29
This is the entire input file.
Since the input file seems to be using fixed-width columns, it's actually very easy to extract the fields. Just read one line at a time, and for each line get each element as a sub-string, and put into the structure members. And there are functions to convert strings to floating-point values as well.
Don't worry about the possible leading or trailing spaces, there are ways of trimming that.
I am making a program for class that needs to read certain lines from an output file based on what "data set" a person chooses. For example, if a person inputs "1" for the desired data set, I need it to use lines 1 through 8 of the data file (inclusively). If they input "2" for the desired data set, I need the program to use lines 9 through 16 from the data file (inclusively), and if "3", then lines 17 through 24 (inclusively).
Here is the code I have so far-
int main()
{
int latA, latB, latC, latD;
int longA, longB, longC, longD;
int AtoB, BtoC, CtoD, threeFlightTotal, nonStop;
int dataSet;
string cityA, cityB, cityC, cityD;
intro();
cout << "Which data set do you wish to use? 1, 2, or 3? ";
cin >> dataSet;
while(dataSet < 1 || dataSet > 3)
{
cout << "Sorry, that is not a valid choice. Please choose again." << endl;
cin >> dataSet;
}
ifstream dataIn;
dataIn.open("cities.txt");
if (dataIn.fail())
{
cout << "File does not exist " << endl;
system("pause");
exit(1);
}
else
{
cout << "File opened successfully" << endl;
}
dataIn.close();
system("pause");
return 0;
}
Here is my data file-
43.65 79.4
Toronto
40.75 74
New York
33.64 84.43
Atlanta
51.5 0
London
37.78 122.42
San Francisco
47.61 122.33
Seattle
44.88 93.22
Minneapolis
41.88 87.63
Chicago
21.19 157.5
Honolulu
45.31 122.41
Portland
42.2 83.03
Detroit
25.47 80.13
Miami
How would I go about doing this? I've looked at other posts but I am having a hard time understanding how to implement their solutions to mine. Thank you for any help in advance. If I'm not giving enough information let me know.
You can simply skip the unneeded lines:
//here you calculate the amount of lines to skip.
//if dataSet=1 --> linesToSkip=0, if dataSet=2 --> linesToSkip=8...
int linesToSkipt = (dataSet-1) * 8;
//getline Needs a string to load the Content.
//So we don't use the data but wee Need to store it somewhere
std::string helper;
//We use a for Loop to skip the desired amount of lines
for(int i = 0; i < linesToSkip; ++i)
std::getline(dataIn, helper); //Skip the unneeded lines
If you knew the exact length of one line you could simply seek to desired Position. But from your example data set it seems like you don't. So you Need to read the file line by line until you reach the desired Position.
I wanted to ask how can I append strings to the end of fixed number of lines (fixed position). I am trying and searching books and websites for my answer but I couldn't find what I am doing wrong.
My structure :
const int numberofdays=150 ;
const int numberofstudents=2;
struct students
{
char attendance[numberofdays]; int rollno;
char fullname[50],fathersname[50];
}
Creating a text file
ofstream datafile("data.txt", ios::out );
Then I take input from the user and save it to the file.
How I save my data to text files :
datafile <<attendance <<endl<< rollno <<endl<<
fullname <<endl<< fathersname <<endl ;
How it looks like in text files :
p // p for present - 1st line
1 // roll number
Monte Cristo // full name
Black Michael // Fathers name
a // a for absent - 5th line
2 // roll number
Johnson // full name
Nikolas // Fathers name
How I try to update the file. (updating attendance for everyday)
datafile.open("data.txt", ios::ate | ios::out | ios::in);
if (!datafile)
{
cerr <<"File couldn't be opened";
exit (1);
}
for (int i=1 ; i<=numberofstudents ; i++)
{
long int offset = ( (i-1) * sizeof(students) );
system("cls");
cout <<"\t\tPresent : p \n\t\t Absent : a"<<endl;
cout <<"\nRoll #"<<i<<" : ";
cin >> ch1;
if (ch1 != 'p')
ch1 = 'a';
datafile.seekp(offset);
datafile <<ch1;
datafile.seekg(0);
}
I just want to add (append) characters 'p' or 'a' to the first or fifth line, I tried every possible way but I am unable to do it.
What you are doing is fairly common, but as you say it is inefficient if the size of data grows. Two solutions are to have fixed size records and index files.
For fixed-size records, in the file write the exact bytes of your data structure rather than a variable length text. This would mean you don't have a text file any more, but a binary file. You can then calculate the position to seek to easily.
To create an index file, write two files at once, one your variable size record file, and the other write a binary value with either the offset of the data from the start of the file. Since the index is a fixed size, you can seek to the index, read it, then seek to the position in the data file. If the new record will fit, you can update it in place, otherwise fill in with blanks and put the updated record at the end of the data file, then update the index file to point to the new location. This is basically how early PC databases worked.
Fixed size records are rather inflexible, and by the time you've implemented the index file system and tested it, now-a-days you probably would use a in-process database instead.
I came up with my own (easy & inefficient) logic to copy every line (except the line I want to update) to the another file.
I made my text file to be created like this :
=p // p for present - 1st line
1 // roll number
Monte Cristo // full name
Black Michael // Fathers name
=a // a for absent - 5th line
2 // roll number
Johnson // full name
Nikolas // Fathers name
Then I made the following code to update 1st and 5th line :
ifstream datafile("data.txt", ios ::in);
ofstream tempfile("temp.txt" , ios ::out);
string data, ch1;
while (getline(datafile,data))
{
if (data[0]=='=')
{
system("cls");
cout <<"\t\tPresent : p\n\t\tAbsent : a"<<endl;
cout <<"\nRoll #"<<i<<" : ";
cin >> ch1;
++i;
if (ch1 != "p")
ch1 = "a";
data=data+ch1; // Appending (updating) lines.
}
tempfile <<data <<endl; // If it was 1st or 5th line, it got updated
}
datafile.close(); tempfile.close();
remove("data.txt"); rename("temp.txt" , "data.txt");
But as you can see, this logic is inefficient. I will still wait for someone to inform me if I could somehow move my file pointer to exact location (1st and 5th line) and update them.
Cheers!
I am trying to get a value associate with a string inside a file called invoice1.txt
invoice1.txt
hammer#10.00
saw#20.00
So for example, when I lookup "hammer" I would like the expression to evaluate to 10.00.
My code so far
string search;
ifstream inFile;
string line;
double price;
inFile.open("invoice1.txt");
if(!inFile)
{
cout << "Unable to open file" << endl;
return 0;
}
else
{
int pos;
while(inFile.good())
{
getline(inFile,line);
pos=line.find(search);
if(pos!=string::npos)
{
cout<<"The item "<<search<<" costs: "// code to get the price
}
}
}
system("pause");
This is the output I am aiming for:
The item hammer costs: 10.00
The summerise, my question is:
How can I associate values with one another that are read in from a file, so I can get a price for an item without having to reparse the file and find it again?
This is what std::map is for.
What you want to do is break your problem down into multiple stages. Here is a simple set of steps that should help you (there are better ways, but I'm trying to keep things simple here).
I've added some lines to explain how to use std::map, in case you're not familiar.
Read the file line by line.
For each line that is read in, get the value after the '#' character.
Add the value to the map, using the string before '#' as the key...
priceMap[key] = price; // for example, this might evaluate to: myMap["hammer"] = 10.00
When you want to use the value, simple give the map you're key.
std::cout << priceMap["hammer"];
What do you search in line from file? You have to search for character # and split your string into two parts.
getline(inFile,line);
pos=line.find('#');
if(pos!=string::npos)
cout<<"The item "<<line.substr(0,pos)<<" costs: " << line.substr(pos+1,line.size()-1) << endl;// code to get the price
You can save item name and price in different variables if you want. If you want to do something more with a string, read this for further instructions.
AccountNumber Type Amount
15 checking 52.42
23 savings 51.51
11 checking 12.21
is my tab delmited file
i would like to be able to search for rows by the account number. say if i put in 23, i want to get that specific row. how would id do that?
also more advance, if i wanted to change a specific value, say amount 51.51 in account 23. how do i fetch that value and replace it with a new value?
so far im just reading in row by row
string line;
ifstream is("account.txt");
if (is.is_open())
{
while (std::getline(is, line)) // read one line at a time
{
string value;
string parseline;
std::istringstream iss(line);
getline(line, parseline);
cout << parseline << endl; // do something with the value
while (iss >> value) // read one value at at time from the line
{
//cout << line << " "; // do something with the value
}
}
is.close();
}
else
cout << "File cant be opened" << endl;
return 0;
Given that each line is of variable length there is no way to index to particular row without first parsing the entire file.
But I suspect your program will want to manipulate random rows and columns. So I'd start by parsing out the entire file. Put each row into its own data structure in an array, then index that row in the array.
You can use "strtok" to split the input up into rows, and then strtok again to split each row into fields.
If I were to do this, I would first write a few functions that parse the entire file and store the data in an appropriate data structure (such as an array or std::map). Then I would use the data structure for the required operations (such as searching or editing). Finally, I would write the data structure back to a file if there are any modifications.