I've got a file that looks like this:
C 0484758654 95
C 0428473483 121
T 0494569848
C 0494569848 121
//.. 30 or so more entries
I want to store each "person" (represented by their phone number) into an object. I know I'll need a structure to store this in so I used a Vector:
using namespace std;
int main()
{
ifstream fin;
fin.open("test.txt");
vector<MonthlyPhoneBill> bill;
MonthlyPhoneBill temp;
while (fin >> temp.code>> temp.phoneNumber >> temp.data)
{
bill.push_back(temp);
}
for (const auto& temp : bill) {
cout << temp.code << ' ' << temp.phoneNumber << ' ' << temp.data << endl;
}
return 0;
}
Class:
class MonthlyPhoneBill {
public:
MonthlyPhoneBill();
int data;
int phoneNumber;
std::string code;
int totalBill;
};
I have a couple of problems however, the first problem is when I'm printing the file contents out it only prints the first line.
My second problem is that I have no idea how to manipulate the data now that it's stored in the vector. For example I'm wanting to calculate a bill for each individual person. I'm not sure how to access the contents of the vector and do calculations accordingly. From the file an individual person could come up multiple times and I'm not sure how to add the total cost each time they were to come up.
struct MonthPhoneBill {
int data;
int phoneNumber;
std::string code;
int totalBill;
};
int main () {
std::vector<MonthPhoneBill> dataEntry;
....
....
MonthPhoneBill temp;
// After Putting data into vector, one can simply access the data by.
while (fin >> temp.code>> temp.phoneNumber >> temp.data >> temp.totalBill) {
bill.push_back(temp);
}
Please keep in mind the content of file should be also in that format like in while loop and you have to stream all the content of that structure. you cannot miss it, if happened all the other entry will be garbage or could lead to code crash
auto temp0 = dataEntry[1].data;
auto temp1 = dataEntry[1].phoneNumber;
auto temp2 = dataEntry[1].code;
....
}
you can simply manipulate the data and access it.
Like #Sam Varshavchik said, look what's different about the third line, because indeed it is different - it's missing the last value, the data member. This causes the while to exit as it encounters no data when executing the last part of while (fin >> temp.code>> temp.phoneNumber >> temp.data), i.e. the >> temp.data.
As for the second question, again like #Sam Varshvchik said - consult your C++ book. You can manipulate the vector of your class entries in any operation, just like you did when printing contents.
To compute the total bill for each person seems to me that your program would need to undergo some changes. Since your users are repeated in the main vector, one way would be to iterate through it and group the repetitions into a single class object per user with summed bills. The other way would be to sort the main vector by phone numbers, i.e. users. Once sorted you could use approaches similar to ones in Chapter 7 of Lippman's C++ Primer.
Related
I am trying to solve the following question:
Write a program, which will get from the user
the Number of flights (N)
the destination of train (city)
the train number for certain destination (number)
the name of the wanted destination city, for which we are searching possible trains.
The program should find and display all numbers of trains, which go to wanted destination. If there is no such train, the program must display "Unreachable city!".
Now the problem is that I wrote a code which finds such train number, but not numbers of all trains, it cannot display all the train numbers going to wanted destination point.
I.e. if I input following data:
3
Chicago I-789
Chicago J-159
Chicago A-465
Chicago
It shows me only last train number A-465, whereas the right answer would be: I-789 J-159 A-465
#include <iostream>
#include <string>
using namespace std;
class MyClass {
public:
string city;
string number;
};
int main() {
int N;
cin >> N;
MyClass myObj;
for (int i=0; i<N; i++){
cin>>myObj.city;
cin>>myObj.number;
}
string destination;
cin >> destination;
if(myObj.city==destination){
cout << myObj.number;
}
else{
cout << "Unreachable city!";
}
return 0;
}
On your comment:
C++ is much harder than python.
Programming languages are just tools. You use them to solve a problem. If you don't know how to use a tool, you can't solve the problem. Your computer is a tool, if you don't know how to operate it, you can't do your homework. That doesn't mean computers are difficult to use. Similarly, C++ is a tool, if you don't know it, it doesn't mean it's difficult.
Let's get to the problem.
The problem
The program should find and display all numbers of trains, which go to wanted destination. If there is no such train, the program must display "Unreachable city!".
Let's break it down
Reading the problem carefully, we can see that there is not just "one" train but multiple 'trains'.
We have to take input from the user (wanted destination)
Then we have to find "all" the "trains" that go that city.
If no train was found, we print "Unreachable city!"
The problem with your code
The problem with your code is that there is only "one train":
MyClass myObj; //one object only
You keep overwriting it's values every time you take input from the user.
Learning the tool
So, What can you do to fix this? In programming when we want to store multiple values of the same object we usually create an array. An array is just a collection of values of one type. Example:
int myarray[5]; //can store 5 "int" values
//size is given inside the [] (square brackets)
Array indexes start from 0. We can store values in array like following:
cin >> myarray[0]; //take input from user and store it into the "first" place in our array
cin >> myarray[1]; //store in the "second" place
cin >> myarray[4]; //store in the "last" place
cin >> myarray[5]; //WRONG! Don't do this. It will result in errors and bugs!! (Undefined Behaviour)
You can also store values directly:
int myarray[5] = {1, 2, 3, 4, 5};
cout << myarray[3]; // prints "4"
That's all nice and fine however there is a small problem with arrays. We have to know the "size" of the array before we create it.
int N;
cin >> N;
int array[N]; //WRONG, even it works, this is wrong.
So, what should we do? We can't know the number of objects we want always. Worry not, because C++ provides us with a nice container: std::vector which can be used to solve this issue.
#include <vector> // you need this for vector
int N;
cin >> N;
std::vector <int> myvector(N); //vector of size N
//access the values as you would with the array
myvector[0] = 10;
myvector[5] = 9; //WRONG.
Solving your problem
Note, that I will not give you the solution directly, but I will show you the way and give you the tools. It's your problem, it's your challenge, and if you try, it's pretty easy to solve the problem.
So we learned about vectors and arrays. Next, you may be wondering how to create vector for your type. Simple:
//create a vector, with size = N
vector <MyClass> Trains (N);
//take input from user
for (int i=0; i<N; i++){
cin >> Trains[i].city;
cin >> Trains[i].number;
}
The last part, will be quite similar. You need a loop, then go over all the values in the vector to find the "destinations" you want.
Side note
You should start with naming your objects and variables in a way that it is easy and natural for you to think about your problem. For example:
class MyClass
This doesn't tell anyone, anything about your class or what you want to do with it. What could be a better name for it? Looking at the problem, I suggest the name Train:
class Train {};
The problem also tells us that each train has a "destination city" and a "train number". We can refactor our Train class to contain the following:
class Train {
public:
string destination;
string number;
};
First, myObj is not a good name, let's change it to an empty list of destinations.
#include <vector>
...
vector <MyClass> destinations;
Next, push each new value into the vector. For this it would be better to have a constructor that sets the values. Constructing a destination with no values is pointless.
MyClass(string _c, string _n) : city(_c), number(_n) {};
...
string city, number;
cin >> city;
cin >> number;
destinations.pushback(MyClass(city, number));
Now you can write your loops to go through the vector looking for the data you need.
#include <iostream>
#include <string>
using namespace std;
#include <vector> // you need this for vector
class Train {
public:
string city;
string number;
};
int main(){
int N;
cin >> N;
string dest;
vector <Train> Trains (N);
int i;
//take input from user
for (i=0; i<N; i++){
cin >> Trains[i].city;
cin >> Trains[i].number;
}
cin >> dest;
for(i=0; i<Trains.size(); i++){
if(Trains[i].city==dest){
cout << Trains[i].number <<" ";
}
else{
cout << "Unreachable city!";
}
}
}
Now it is always printing Unreachable city next to right results :(
I suppose before even requesting help, I should mention that this one of the various exercises in my Computer Science course to help us further understand how to pull inputs from files and such. Any help is appreciated, whether it's direct "give it all away" answers or pseudocode-type responses. So, here's the prompt.
Write a C++ program that reads lists from a file and reports the name, size, mean if appropriate, and second largest number if appropriate for each list; and reports the list name and sum of the list with the largest sum. The file to be read consists of: a file sentinel, a number not equal to any of the list sentinels... then zero or more of: a list sentinel, a number not equal to any value in this list; the list name, readable as a C++ STL string; zero or more list values separated by whitespace; the list sentinel then the file sentinel.
It includes an example, and here's what the example shows.
31 17.3 FIRST 26.2 -11.2 8.1 17.3 0.0 SECOND 0.0 31
EXPECTED OUTPUT:
First size is 3, mean is 7.7, second largest value is 8.1. Second size is 0. First has the largest sum of the list(s) with 23.1.
Sorry, I know it's all sort of confusing. I'm pretty confused myself, but that's a college course for ya. So, anyways, here is what I've got so far!
#include <iostream>
#include <string>
#include <fstream>
using namespace std;
int main()
{
// loop once per file
// stop if filename string is "end" or "done"
while (true) {
string filename;
cout << "Enter filename or \"end\" to quit: ";
cin >> filename;
if (filename == "end" || filename == "done")
{
break;
}
// open the file
ifstream infile(filename);
cout << "Processing " << filename << ", please wait...\n";
// processing just if file is opened
if (infile)
{
// count the number of lists
int numLists = 0;
int x = 0;
infile >> x;
while (!infile.fail())
{
++numLists;
// read one list
while (x != 31)
{
infile >> x;
}
infile >> x;
}
cout << filename << " contains " << numLists << " lists.\n";
}
}
}
So, my output is working so far concerning determining how many lists are in each file, however, I've tried several things to get the sum and the mean of the lists, but I just don't know how to store the values per list, per file. I've thought about arrays, or vectors, but I just really don't know. I'd appreciate any help anyone could offer. Please!
Here's some code to read the lists in the way the questions asks. I have not tested this code, so apologies for any mistakes, but it does correspond to the question.
ifstream in(filename);
// read the file sentinel first
double file_sentinel;
in >> file_sentinel;
for (;;)
{
// read next sentinel
int sentinel;
in >> sentinel;
// if it's a file sentinel then we are done
if (sentinel == file_sentinel)
break;
// it must be a list sentinel so read the list starting with the name
string name;
in >> name;
// start of list processing
...
for (;;)
{
// read the next item in the list
double item;
in >> item;
// check if the item is actually the list sentinel, if so the we're done with this list
if (item == sentinel)
break;
// now process list item
...
}
// now process whole list
...
}
There's no error checking (not sure if that is necessary) and I've left some blanks for the processing the question asks you to do. Hopefully it will give you a start.
I am having trouble of understanding how to create an array of pointers to structures. I tried to look up similar examples and threads in the forum but I still cannot get my code to work! As a result, I believe I have written an ugly piece of code that I do not know where it is wrong and how to fix it.
Here is the code:
#include <iostream>
#include <fstream>
#include <string>
using namespace std;
struct Movie
{
string name;
int numawards;
int nomination;
int year;
};
void *readfile(ifstream &infile, int &n);
int main()
{
ifstream infile;
int n = 0;
infile.open("old_movies.txt");
Movie *oldmovies;
oldmovies = readfile (infile, n);
return 0;
}
//*function documentation//
void *readfile (ifstream &infile, int &n)
{
infile >> n;
Movie *movies;
movies = new Movie[n];
for (int i = 0 ; i < n ; i++)
{
infile >> movies[i]->year >> movies[i]->numawards >> movies[i]->nomination;
infile.ignore();
infile.ignore();
getline(infile, movies[i]->name);
cout << movies[i]->year << " " << movies[i]->numawards << " " << movies[i]->nomination << " " << endl << movies[i]->name<< endl; //the cout here is to test and see if the code works.
}
return movies;
}
The purpose of this code is to read a txt file that contains the movie name, how many awards, how may nominations, and what year it is produced, and then print it out using pointers. Here is what the file looks like:
2
1935 1 3
The Dark Angel
1935 4 6
The Informer
1935 1 8
the first 4 digits represents the year, the second one represents number of awards it has gotten, and the last digit represents the number of times it has been nominated to an award.
Anyway, I am stuck at this part and I am really clueless about what to do here. I just hope that this code is not that bad to a point where there are numerous things to be changed. Any help or advice would be greatly appreciated.
Let's look at what you have here:
Movie *movies;
movies = new Movie[n];
This allocates an array of Movie instances. To allocate an array of pointers dynamically, you need to change this to
Movie** movies;
movies = new Movie*[n];
Now inside the for loop, you need to allocate each Movie instance:
movies[i] = new Movie();
You should also change the readfile() to return a Movie** rather than a void* so that you don't have to use any casts later.
But do you really need an array of pointers? Why not just use an array of structs. This would avoid the extra level of indirection and make your code a little simpler.
So I have a file with six columns, the first being date, and the rest being different sorts of stock information. (i.e., open, close, volume traded, etc.) I'm trying to sort each column into an array. Here's my function to do so:
void load_file(istream& fin, string date[], double open[], double high[],
double low[], double close[], int vol[], int& day)
{
day = 0;
while (day < MAX_TRADING_DAYS)
{
fin >> date[day] >> open[day] >> high[day]
>> low[day] >> close[day] >> vol[day];
day++;
}
}
Here's how a typical line (262 total, corresponding to max_trading_days) from the file looks:
3-Mar-14 1206.75 1207.84 1192.14 1202.69 2108720
When I'm outputting analysis of the stock information into another file, I'm getting completely garbage values so I'm guessing the issue is with how the information is being seen into the arrays in the first place. What would be the best way to accomplish this?
When I do try to display one of the arrays, XCode displays several differnt
Also, the file originally has a title row at the very beginning with the title of each column. I deleted this to try to figure out if this code would work or not. How could I ignore that first row when taking in information from the file?
Thanks!
Edit: When I do try to display one of the arrays after calling the function, XCode displays several different issues that I'm unsure how to navigate.
_LIBCPP_INLINE_VISIBILITY
bool __is_long() const _NOEXCEPT
{return bool(__r_.first().__s.__size_ & __short_mask);}
_LIBCPP_INLINE_VISIBILITY size_type size() const _NOEXCEPT
{return __is_long() ? __get_long_size() : __get_short_size();}
Next to each of these it says "Thread 1: EXC_BAD_ACCESS (code=1, address=0x7fff5fcbdd78)"
You are modifying copies of your parameters.
In C++, parameters are passed by value. This means that a copy of the content in the original variable is passed to the function. So if you modify parameters, you are modifying a copy, not the original.
You can around this in two ways: 1) Pass by reference or 2) Pass by pointer. The first method allows you to modify or access the original variable without making a copy. The second method allows you to change the content of the original variable because you know its location. Pointers are nasty, prefer references.
So the compiler may be complaining that you are writing to copies of the variables or the variables are passed as read-only variables.
Edit 1: Simplification Suggestion
You can simplify your function signature by making a structure or class to model a row in your text file. Pass an instance, by reference, to your input function or pass a std::vector by reference to input more than one row.
Also, you should overload operator>> in your structure to simplify to input loop:
struct Data_Row
{
friend std::istream& operator>>(std::istream& input, Data_Row& d);
};
std::istream& operator>>(std::istream& input, Data_Row& d)
{
// read members of 'd' from 'input'
return input;
}
//.. your input loop
Data_Row dr;
std::vector<Data_Row> container;
while (input_file >> dr)
{
container.push_back(dr);
}
If there is a problem in your code, it is likely elsewhere (for example, in how you allocate memory). Here is a working example, using your code, which correctly reads input in the format you specify.
#include <iostream>
#include <fstream>
#include <string>
#include <limits>
#define MAX_TRADING_DAYS 262
using namespace std;
void load_file(istream& fin, string date[], double open[], double high[],
double low[], double close[], int vol[], int& day)
{
// Ignore the header row
fin.ignore(std::numeric_limits<std::streamsize>::max(), '\n');
// Start reading
day = 0;
while (day < MAX_TRADING_DAYS)
{
fin >> date[day] >> open[day] >> high[day]
>> low[day] >> close[day] >> vol[day];
day++;
if (fin.eof()) break;
}
// We will not detect EOF until an extra line has been read, so we compensate.
day--;
}
// A small function verify that we read correctly.
void dump_file(string* date, double* open, double* high,
double* low, double* close, int* vol, int& day) {
for (int i = 0; i < day; i++)
cout << date[i] << "\t"
<< open[i] << "\t"
<< high[i] << "\t"
<< low[i] << "\t"
<< close[i] << "\t"
<< vol[i] << endl;
}
int main(){
ifstream mystream("Trade.in", std::ifstream::in);
string* date = new string[MAX_TRADING_DAYS];
double* open = new double[MAX_TRADING_DAYS];
double* high = new double[MAX_TRADING_DAYS];
double* low = new double[MAX_TRADING_DAYS];
double* close = new double[MAX_TRADING_DAYS];
int* vol = new int[MAX_TRADING_DAYS];
int day;
load_file(mystream, date,open,high,low,close,vol,day);
dump_file(date,open,high,low,close,vol,day);
}
Hi guys i am new to c++, I just wrote this code to find min/max of a array of numbers.
I just want to know how can I make the no. of entries flexible(I mean the user should be able to enter as many entries as possible without specifying how many in the starting)
Here's the code, but its not working, can someone please help?
Thanks
code:
#include <iostream>
using namespace std;
int main(){
cout<<"Program to calculate max/min/second max\n";
int *A;
A=new int[5];
bool flag=false;
int x=0,i=0;
cout<<"Enter the numbers\n";
do{
cin>>x;
if(x=='\0'){
flag=true;
}
*(A+i)=x;
i++;
}
while(!flag);
for(int j=0;j<i;j++){
cout<<*(A+j)<<"\n";
}
return 0;
}
You are confused that pressing enter will just give you the null terminator. It will not. Depending on your platform it will give you a carriage return/line-feed (\r\n in Win, \n in *ix). The best way to do this is to just have them use a letter like 'q' for quit or a number like -1, and then compare on that.
Dynamic Memory Allocation is a bit of a tricky subject for a beginning programmer (in C and C++ in any case.) The easiest way is to have the user specify how many entries, but you don't want this.
Otherwise using the vector class over an array is probably a better (and easier to grapple with than directly using pointers.)
http://www.cplusplus.com/reference/stl/vector/ is a good place to start. Look at the syntax for creating the vector and the push_back() member function to accomplish your task.
Good Luck,
SegFaults McGee
You will have to use some sort of variable length datastructure and Vector is the best choice for this since you are working in C++. Therefore, instead of your fixed length array:
int *A;
A=new int[5];
use a vector like this:
std::vector<int> input;
And then to add values to this, use the following:
input.push_back(10);
There is an example on this page about using vectors.
mean the user should be able to enter as many entries as possible without specifying how many in the starting
With the above requirement and with the code you have, you can enter no more than 5 elements to an array.
do{
cin>>x;
if(x=='\0'){
flag=true;
}
*(A+i)=x;
i++;
}while(!flag);
Use std::vector instead for the requirement where it implicitly manages memory for you.
If you use
std::vector<int> a;
then the input becomes simply
while (std::cin >> x)
a.push_back(x);
Then the user can press ^D (Unix/Linux/etc) or ^Z (DOS/Win) when they've entered all the numbers, or use the program as in:
echo 1 4 22 | program
program < input_file
If you want to have an empty line denote the end of input, then with input validation:
std::string line;
while (getline(std::cin, line))
{
char c;
std::istringstream iss(line);
int x;
if (iss >> x)
{
a.push_back(x);
char c;
if (iss >> c)
{
std::cerr << "unexpected character '" << c << "' in line '" << line << "', terminating\n";
exit(EXIT_FAILURE);
}
}
else if (!iss.eof())
break; // empty line...
else
{
std::cerr << "unexpected characters in line '" << line << "', terminating\n";
exit(EXIT_FAILURE);
}
}