How to make an end of file output it's data? - c++

this is my first time asking a question so forgive me if I stumble over anything. I have been working on a project for a suspension system for a car. I needed to make 4 functions for the displacement of the car and tire and the velocity of the car and tire. I feel that I structured the code well but it's simply not outputting the final product. The main purpose is to find the maximum of each function. I tried a lot to try and fix it but I can't seem to come up with a solution.
The main point is. I structured a program with four functions which the data file feeds with the information til it ends. When I try to run it nothing but the header is outputted. I am at a lost to how this is.
The data file has four groups ranging from car A to car D organized like so,
Spring Constant of tire, damp constant of dash-pot, mass of wheel, mass of car, start/end times, increment value
The functions themselves are sort of...Hard to swallow. So I would like to share some sections of code where I believe problems are.
Any help/hints/comments would be most appreciated.
csdatafiles>> total_readings;
csdatafiles >> car_name >> spring_constant_tire >> spring_constant_spring
>> damp_constant >> mass_of_tire >> mass_of_car
>> start_time_value >> end_time_value >> increment_time_value;
//Initialize max min
max_displacement_car=displacement_of_car;
max_displacement_tire=displacement_of_tire;
max_velocity_car=velocity_of_car;
max_velocity_tire=velocity_of_tire;
//Output Header
cout << "\nCar Name Max Tire Displace Max Tire Vel Max Car Displace Max Car Vel \n" << endl;
{
//recall functions
velocity_of_tire= old_new_tire_velocity (variables needed);
velocity_of_car=old_new_car_velocity (variables needed);
displacement_of_car= old_new_car_displacement (variables needed);
//check for max
if (displacement_of_car>max_displacement_car)
max_displacement_car=displacement_of_car;
if (displacement_of_tire>max_displacement_tire)
max_displacement_tire=displacement_of_car;
if (velocity_of_car>max_velocity_car)
max_velocity_car=velocity_of_car;
if (velocity_of_tire>max_velocity_tire)
max_velocity_tire=velocity_of_tire;
total_readings++;
//read rest of data
csdatafiles >> spring_constant_tire >> spring_constant_spring
>> damp_constant >> mass_of_tire >> mass_of_car
>> start_time_value >> end_time_value >> increment_time_value;
} while (!csdatafiles.eof());
//Output
cout << car_name << max_displacement_tire << max_velocity_tire << max_displacement_car << max_velocity_car;

Just going off of the code that you posted, it looks like you tried to put a do-while but forgot the do ...
Instead of
do {
//recall functions
//...
//check for max
//...
//read rest of data
//....
} while (!csdatafiles.eof());
You have
{
//recall functions
//...
//check for max
//...
//read rest of data
//....
} while (!csdatafiles.eof());
which is VERY different! Without the do, your code is equivalent to:
{
//recall functions
//...
//check for max
//...
//read rest of data
//....
}
while (!csdatafiles.eof()) {
;
}
As you can see, there is an infinite loop just before the last cout statement, so you never reach it.

Related

c++ primer - value of variables

I started reading C++ Primer, 5th Edition and I'm having troubles understanding one thing when it comes to std::cin.
The following is the code they present as their example. The idea behind it is that a bookstore is recording its transactions and the program should be able to sum back-to-back transactions as long as they belong to the same book (ie, they have the same isbn).
I haven't included the header file since I believe it isn't relevant to my question. In case it's actually needed, you can find it here.
My issue with the example is that the comments explaining the code say that the first Sales_item object, named total, is used to store the current transaction, while the one named trans is used to 'hold the running sum'. That is, the total.
#include <iostream>
#include "Sales_item.h"
int main()
{
Sales_item total; // variable to hold data for the next transaction
// read the first transaction and ensure that there are data to process
if (std::cin >> total) {
Sales_item trans; // variable to hold the running sum
// read and process the remaining transactions
while (std::cin >> trans) {
// if we're still processing the same book
if (total.isbn() == trans.isbn())
total += trans; // update the running total
else {
// print results for the previous book
std::cout << total << std::endl;
total = trans; // total now refers to the next book
}
}
std::cout << total << std::endl; // print the last transaction
} else {
// no input! warn the user
std::cerr << "No data?!" << std::endl;
return -1; // indicate failure
}
return 0;
}
I've seen various examples with this kind of reasoning, and to me it looks counterintuitive. Shouldn't the first variable be holding the total (since it belongs to a wider scope and it's named, you know, total) while the second holds the current transaction? Did I understand this completely backwards and the second cin is actually holding the total?
I agree, the comments appear to be swapped. They should be:
Sales_item total; // variable to hold the running sum
Sales_item trans; // variable to hold data for the next transaction

Intro to classes (c++) project wants us to create two constructors, but neither of them need any parameters - what should i do here?

I think I'm just confused on the wording to this project, but I'm posting here to make sure I have the basics on classes correct (like I said, we just started learning them).
The beginning of the project prompt is as follows:
Declare and define a class called Odometer. This class will have two private variables, one for the miles driven and the other for the gallons of gas pumped into the car.
The member functions should include:
A constructor that takes initial values for both of the private variables.
A default constructor that sets both values to zero.
Along with more member functions that aren't important for my problem. I understand the default constructor fully, but the other is the one I'm having troubles with. If he (my professor) wants us to gather initial variables, then why would it need any parameters at all? I guess I could pass an empty string into it as a parameter, but I feel like there's something I'm missing here...
To expand on the point of this project, in case it's needed, we are creating a program that allows the user to continually enter (on a menu screen) either miles driven or gallons put into their tank. The program will then find the mpg, when the user requests it. Very simple.
Here's part of the program, which should be enough for someone to help me with this. The second/non-default constructor seems like it would work, except obviously I need some type of parameter. Any suggestions or help is greatly appreciated.
#include <iostream>
using namespace std;
class Odometer{
public:
Odometer(); // sets values to 0
Odometer(WHAT GOES HERE); // gathers initial values
void get_miles();
void get_gallons();
void add_in_trip_miles();
void add_gas();
private:
double milesDriven; // represents the miles the car has driven
double gallonsGas; // represents the number of gallons pumped into car
};
int main() {
Odometer userInfo; // creates object for the user-inputted values
bool quit = false; // true when user wants to quit
int userChoice; // for navigating the menu screen
while(!quit){
cout << "To view total miles, enter 1. To view total gallons, enter 2.\nTo record more miles driven, enter 3. To record gallons pumped into the tank, enter 4.\n To view the average MPG, enter 5. To reset the odometer, enter 6.\n To quit the program, enter 7." << endl;
cin >> userChoice;
if(userChoice == 1) userInfo.get_miles(); // TODO: switch/case statement instead?
if(userChoice == 2) userInfo.get_gallons();
if(userChoice == 3) userInfo.add_in_trip_miles(); // TODO: "function which increases the miles by the amount sent in its parameter
}
cout << "Have a nice day!" <<endl;
return 0;
}
Odometer::Odometer(){ // sets values to 0 (default)
milesDriven = 0;
gallonsGas = 0;
}
Odometer::Odometer(WHAT GOES HERE?){ // gathers initial values
cout << "Please enter an initial value for miles driven." << endl;
cin >> milesDriven;
cout << "Please enter an initial value for how many gallons were put into the car." << endl;
cin >> gallonsGas;
}
Your teacher is asking you to implement the second constructor with parameters so user will be able to initialize the object with the state he wants. I would implement it like this:
Odometer(double milesDriven_, double gallonsGas_) :
milesDriven(milesDriven_),
gallonsGas(gallonsGas_)
{}

C++ algebraic calculation

I had to write a program to ease our burden in finding linear curve fitting for our physics lab works.
My program computes upto sigma xi and sigma (xi^2) correctly. I have used similar code for computing rest few values.
But Afterwards, It is displaying all values as 0.
I couldn't find any mistakes in the remaining part as the same codes i used worked before.
I'm attaching the cpp file.Cpp file here
Sample part giving value 0
float * yl;
yl= new float[N];
cout << "Enter values for Y (total "<<N<<")\n"<<endl;
for(j=1;j<N+1;j++)
{
cin >> yl[i];
}
sigyi=0;
for(o=1;o<N+1;o++)
{
sigyi=sigyi+yl[o];
}
But this one works correctly
float * xl;
xl= new float[N];
cout << "Enter values for X (total "<<N<<")\n"<<endl;
for(i=1;i<N+1;i++)
{
cin >> xl[i];
}
sigxi=0;
for(l=1;l<N+1;l++)
{
sigxi=sigxi+xl[l];
}
Please help me with this.
First off, neither code snippet you posted is correct. The appearance of working is not sufficient. The code is accessing outside the boundaries that are legal, and in C++ that means anything could happen at any time. It might appear to work sometimes and other times it might not.
However the most immediate reason why the first snippet probably doesn't appear to work is because you are incorrectly reusing the index i when you switched the loop declarations to use j:
for(j=1;j<N+1;j++) // <--- j
{
cin >> yl[i]; // <--- i
}
This is one of the reasons that predeclaring the loop indices is a bad practice. You should always declare the loop variable in the loop itself. Had you done this, then there would not have been any i in the outer scope for you to accidentally use in the j loop.

grabbing data sets from a file with an arbitrary amount of spaces

**No direct answers or code examples please, this is my homework which i need to learn from. I'm looking for help concerning the algorithm i need to develop.
I seem to be having a logic error in coming up with a solution for a portion of my class work, the program involves multiple files, but here is the only relevant portion:
I have a file PlayerStats that holds the stats for a basketball player in:
rebounds
points
assists
uniform #
my initial reaction would be to create a while loop and read these into a temporary struct that holds these values, then create a merge function that merges the values of the temp struct with the inital array of records, simple enough?
struct Baller
{
//other information on baller
int rebounds;
int assists;
int uniform;
int points;
void merge(Baller tmp); //merge the data with the array of records
}
//in my read function..
Baller tmp;
int j = 0;
inFile << tmp.uniform << tmp.assists << tmp.points << tmp.rebounds
while(inFile){
ArrayRecords[j].merge(tmp);
j++;
//read in from infile again
}
The catch:
The file can have an arbitrary number of spaces between the identifiers, and the information can be in any order(leaving out the uniform number, that is always first). e.g.
PlayerStats could be
11 p3 a12 r5 //uniform 11, 3 points 12 assists 5 rebounds
//other info
OR
11 p 3 r 5 a 12 //same exact values
What I've come up with
can't seem to think of an algorithm to grab these values from the file in the correct order, i was thinking of something along these lines:
inFile << tmp.uniform; //uniform is ALWAYS first
getline(inFile,str); //get the remaining line
int i = 0;
while(str[i] == " ") //keep going until i find something that isnt space
i++;
if(str[i] == 'p') //heres where i get stuck, how do i find that number now?
else if(str[i] == 'a')
eles if(str[i] = 'r'
If you're only going to check one letter, you could use a switch statement instead of if / else, that would make it easier to read.
You know where the number starts at that point, (hint: str[i+1]), so depending on what type your str[] is, you can either use atoi if its a char array, or std::stringstream if it's an std::string.
I'm tempted to give you some code, but you said not too. If you do want some, let me know and I'll edit the answer with some code.
Instead of using a 'merge' function, try using an std::vector so you can just push_back your structure instead of doing any 'merging'. Besides, your merge function is basically a copy assignment operator, which is created by the compiler by default (you don't need to create a 'merge' function), you just need to use = to copy the data across. If you wanted to do something special in your 'merge' function, then you should overload the copy assignment operator instead of a 'merge' function. Simples.
Do something like that:
int readNumber () {
while isdigit (nextchar) -> collect in numberstring or directly build number
return that number;
}
lineEater () {
Read line
skip over spaces
uniform=readNumber ();
haveNum=false;
haveWhat=false;
Loop until eol {
skip over spaces
if (isdigit)
number=readNumber ();
skip over spaces
haveNum=true;
else
char=nextChar;
haveWhat=true;
if (haveChar and haveNum) {
switch (char) {
case 'p' : points=number; break;
...
}
haveNum=false;
haveWhat=false;
}
}
or, if you are more ambitous, write a grammar for your input and use lex/yacc.

In C++, I want to implement a ring iterator for a deque that contains a personally defined class

I have a function of a "Table" class that should add a player to the table. I decided that if the seat is taken, the function should try and go through all the seats and add the player to the next available seat. How do I implement this in my addPlayer function?
int Table::addPlayer(Player player, int position)
{
deque<Player>::iterator it;
if(playerList[position] != "(empty seat)") {
//What goes here?
}
playerList.put(player,it);
cout >> "Player " >> player.toString >> " sits at position " >> position >> endl;
}
Instead of using position, use the iterator to point to that position, using something like this:
it = playerList.begin() + position;
Then, check if the seat is taken using the iterator.
If the seat is taken, increment the iterator, but check for end, like this:
while (no empty seat found yet)
{
++it;
if (it==playerList.end()) it = playerList.begin();
}
Of course, if all seats have been taken, this will result in an endless loop.
Therefore, also keep the iterator you started from (let's call this itStart), and add a check on it:
while (no empty seat found yet)
{
++it;
if (it==playerList.end()) it = playerList.begin();
if (it==itStart) break; // We tried all seats
}
Maybe you should also take a look at the circular buffer from boost.
http://www.boost.org/doc/libs/1_43_0/libs/circular_buffer/doc/circular_buffer.html
I think it will do what you want, and is quite easy to use.