Related
This question already has answers here:
What happens when I print an uninitialized variable in C++? [duplicate]
(4 answers)
Closed 1 year ago.
Background: So I basically googled projects for beginners for C++ and one recommendation was currency converter. So I decided to do this, at first I tried to do it by creating a class, objects etc but I got lost with constructors and header files etc but that's a story for another day. I am very new to programming and this is my first "project".
So I decided to go the simple route and did this:
#include <iostream>
int main(){
double euro;
//creating all the variables and conversions
double eur2dol = euro * 1.13;
double eur2pound = euro * 0.84;
double eur2rup = euro * 84.49;
double eur2yuan = euro * 7.2322769;
double eur2btc = euro * 0.0000237;
double eur2eth = euro * 0.00029956;
// creating an array with the name of the currency i am converting to
std::string curname[6] = { " Dollars\n", " Pounds\n", " Rupees\n", " Yuan\n", " Bitcoin\n", " Etherium\n"};
// creating an array with the conversions i want to do
double currencies[6] = { eur2dol, eur2pound, eur2rup, eur2yuan, eur2btc, eur2eth };
//accepting input from the user
std::cout << "Amount in euros: " << std::endl;
std::cin >> euro;
// for loop to loop through every item in the currencies array and the corresponding name of the currency from the curname array
for(int i = 0; i < 5; i++){
std::cout << euro << " Euro is " << currencies[i] << curname[i];
};
return 0;
}
Now, I know there is no point in doing this other than practicing because the values constantly change but I am getting the same result no matter the value I type in and in scientific form.
How can I fix it so i get the correct result and what is the problem?
A typical case of uninitialized variable. Here you are operating on euro variable before asking(cin) value for it, The correct implementation would be something like:
#include <iostream>
int main()
{
double euro = 0; //always put some values beforehand
//accepting input from the user
std::cout << "Amount in euros: " << std::endl;
std::cin >> euro;
//creating all the variables and conversions
double eur2dol = euro * 1.13;
double eur2pound = euro * 0.84;
double eur2rup = euro * 84.49;
double eur2yuan = euro * 7.2322769;
double eur2btc = euro * 0.0000237;
double eur2eth = euro * 0.00029956;
// creating an array with the name of the currency i am converting to
std::string curname[6] = { " Dollars\n", " Pounds\n", " Rupees\n", " Yuan\n", " Bitcoin\n", " Etherium\n"};
// creating an array with the conversions i want to do
double currencies[6] = { eur2dol, eur2pound, eur2rup, eur2yuan, eur2btc, eur2eth };
// for loop to loop through every item in the currencies array and the corresponding name of the currency from the curname array
for(int i = 0; i < 5; i++){
std::cout << euro << " Euro is " << currencies[i] << curname[i];
};
return 0;
}
Note: Uninitiazed variable is a bad practice. If you initialized the variable like double euro = 0; earlier, it will alteast not return arbitrary values even for the wrong code.
You can format your floating-point values with std::fixed and std::setprecision.
Apart from that:
Make sure you don't use euro before reading it.
Try and declare the variables as close to the place where you first use them as possible.
currencies array would probably better be called conversion_rates or something like that.
[Demo]
#include <iomanip> // setprecision
#include <ios> // fixed
#include <iostream>
int main() {
// creating all the variables and conversions
double eur2dol = 1.13;
double eur2pound = 0.84;
double eur2rup = 84.49;
double eur2yuan = 7.2322769;
double eur2btc = 0.0000237;
double eur2eth = 0.00029956;
// creating an array with the name of the currency i am converting to
std::string currency_name[6] = { "Dollar", "Pound", "Rupee", "Yuan", "Bitcoin", "Etherium" };
// creating an array with the conversions i want to do
double conversion_rates[6] = { eur2dol, eur2pound, eur2rup, eur2yuan, eur2btc, eur2eth };
// accepting input from the user
std::cout << "Amount in euros: " << std::endl;
double euro{};
std::cin >> euro;
// for loop to loop through every item in the currencies array and
// the corresponding name of the currency from the curname array
for (int i = 0; i < 6; i++) {
std::cout << std::fixed << std::setprecision(2) << euro << " Euro is "
<< std::setprecision(5) << euro * conversion_rates[i] << " " << currency_name[i] << "\n";
};
return 0;
}
You could as well slightly improve your solution and get started with concepts such as structs and STL containers just by:
defining a Currency struct, where you hold the the currency name and rate conversion from euros,
using a constant vector of currencies,
walking the vector with a range for loop.
[Demo]
#include <iomanip> // setprecision
#include <ios> // fixed
#include <iostream> // cout
#include <string>
#include <vector>
struct Currency
{
std::string name{};
double from_euro_rate{};
};
int main() {
const std::vector<Currency> currencies{
{"Dollar", 1.13},
{"Pound", 0.84},
{"Rupee", 84.49},
{"Yuan", 7.2322769},
{"Bitcoin", 0.0000237},
{"Etherium", 0.00029956}
};
// accepting input from the user
std::cout << "Amount in euros: ";
double euro{};
std::cin >> euro;
std::cout << euro << "\n\n";
// for loop to loop through every item in the currencies array and
// the corresponding name of the currency from the curname array
for (auto& currency : currencies) {
std::cout << std::fixed << std::setprecision(2) << euro << " Euro is "
<< std::setprecision(5) << euro * currency.from_euro_rate << " " << currency.name << "\n";
};
}
I have an structure named "Particle" and I want to create several objects whose names depends on an int.
As I am inside a for loop the name is going to change as follows: part0, part1, part2.
for (int i = 0; i<num_particles; i++)
{
//double sample_x, sample_y, sample_theta;
string name = "part" + std::to_string(i);
Particle name;
name.id = i;
name.x = dist_x(gen);
name.y = dist_y(gen);
name.theta = dist_theta(gen);
cout << "Sample" << " " << name.x << " " << name.y << " " << name.theta << endl;
}
As you can imagine this approach doesn't work, do you have any solution?
I have updated my question, now this is my new approach:
I have created a vector and an int "number of particles":
std::vector<Particle> particles;
And the function code:
void ParticleFilter::init(double x, double y, double theta, double std[]) {
// TODO: Set the number of particles. Initialize all particles to first position (based on estimates of
// x, y, theta and their uncertainties from GPS) and all weights to 1.
// Add random Gaussian noise to each particle.
// NOTE: Consult particle_filter.h for more information about this method (and others in this file).
default_random_engine gen;
normal_distribution<double> dist_x(x, std[0]);
normal_distribution<double> dist_y(y, std[1]);
normal_distribution<double> dist_theta(theta, std[2]);
//for (int i = 0; i<num_particles; i++)
//{
//double sample_x, sample_y, sample_theta;
//string name = "part";
//+ std::to_string(i);
//Particle particles;
particles[num_particles].id =num_particles;
particles[num_particles].x = dist_x(gen);
particles[num_particles].y = dist_y(gen);
particles[num_particles].theta = dist_theta(gen);
num_particles++;
cout << "Sample" << " " << particles[num_particles].x << " " << particles[num_particles].y << " " << particles[num_particles].theta << endl;
//}
}
But it doesn't work yet, it outputs "Segmentation fault".
you can use itoa() function of cstdlib simply in your code.
for (int i = 0; i<10; i++)
{
char a[max];
string pa="part_";
string name = pa + itoa(i,a,i+1) ;
cout << "Sample" << " " << name << endl;
}
}
Sample Output:
Sample part_0
Sample part_1
Sample part_2
Sample part_3
Sample part_4
Sample part_5
Sample part_6
Sample part_7
Sample part_8
Sample part_9
This construct exists in C++, it is called std::vector.
// we want to have a bunch of variables of type Particle
// all named particles[i] for i == 0,1,2....
std::vector<Particle> particles;
// create a new particle variable
particles.emplace_back(x, y, theta);
// print the variable number 42
std::cout << particles[42];
Why do you want to down the messy road of variable naming such as var0, var1, var2 and so on? I'd recommend creating an array or vector.
It's not clear from your code snippet that why you need to create variables with different names. Moreover, your code/usecase doesn't sit right with the concept of variable scoping.
So I am trying to make a rental program that reads in a file with a list of cars ( year, make, model, price, and if available).
I also have to make options such as showing all cars and having the user look at a specific car( for example they type 1, and it will show the top car on the text file). This is where I am confused, I tried making several cars such as car1,car2, etc. But I am having trouble registering the first read car into car1.
This is an example file.
CarData.txt
2014 Toyota Tacoma 115.12 1
2012 Honda CRV 85.10 0
2015 Ford Fusion 90.89 0
2013 GMC Yukon 110.43 0
2009 Dodge Neon 45.25 1
2011 Toyota Rav4 65.02 1
2012 Mazda CX5 86.75 1
2016 Subaru Outback 71.27 0
2015 Ford F150 112.83 1
2010 Toyota Corolla 50.36 1
Source code:
#include <iostream>
#include <fstream>
using namespace std;
struct car
{
int year;
char make[10];
char model[10];
float price;
int available;
}car1[1], car2[1], car3[1], car4[1], car5[1], car6[1], car7[1], car8[1], car9[1], car10[1];
void copy_string(char d[][50], char s[][50]);
int my_strcmp(char *a, char *b);
// Main Function
int main ()
{
// declare variables
int choice;
car carLib[10];
char array[30][50];
char filename[10];
ifstream carInData;
//prompt user for input file
cout << " Enter file name: ";
cin >> filename;
cout << " 1 - Show Cars\n";
cout << " 2 - Rental Cost\n";
cout << " 3 - Most Expensive Car\n";
carInData.open(filename);
cin >> choice;
if(carInData.is_open());
{
int count = 0;
// read list of names into array
for( count; count < 1; count++){
carInData >> car1[count].year >> car1[count].make >> car1[count].model >> car1[count].price >> car1[count].available;
carInData >> car2[count].year >> car2[count].make >> car2[count].model >> car2[count].price >> car2[count].available;
switch (choice){
case 1:
cout << car1[count].year << " " << car1[count].make << " " << car1[count].model << " " << car1[count].price << " " << car1[count].available << " " << "\n";
cout << car2[count].year << " " << car2[count].make << " " << car2[count].model << " " << car2[count].price << " " << car2[count].available << " " << "\n";
break;
}
}
}
return 0;
}
// copy function
void copy_string(char d[], char s[]) {
int c = 0;
while (s[c] != '\0') {
d[c] = s[c];
c++;
}
d[c] = '\0';
}
// string copy
int my_strcmp(char *a, char *b)
{
while (*a && *b && *a == *b) { ++a; ++b; }
return *a - *b;
}
Here is example source, how to work with array of struct type, like car carLib[300];:
#include <iostream>
struct car
{
int year;
char make[10];
char model[10]; // that's only 9 letters for zero-terminated strings
float price;
int available;
};
int main()
{
constexpr size_t maxCarLib = 300;
car carLib[maxCarLib]; // array of memory reserved for several cars
size_t carLibCount = 0; // current allocation of array (zero cars entered)
carLib[carLibCount++] = car {1993, {"Nohda"}, {"XYZ"}, 123.45, 0};
carLib[carLibCount++] = car {1994, {"Frod"}, {"Peon"}, 543.21, 1};
carLib[carLibCount++] = car {1977, {"Nohda"}, {"ABC"}, 3.32, 0};
std::cout << "Cars in library: " << carLibCount << std::endl;
for (size_t carIndex = 0; carIndex < carLibCount; ++carIndex) {
const car & carI = carLib[carIndex];
printf("Car at index %lu: %d %s %s %f %d\n",
carIndex, carI.year, carI.make, carI.model, carI.price, carI.available);
}
// Find most expensive car
float mostExpensivePrice = 0; // most expensive price found
size_t mostExpensiveIndex = carLibCount; // index points beyond array ("no car")
for (size_t carIndex = 0; carIndex < carLibCount; ++carIndex) {
if (carLib[carIndex].price <= mostExpensivePrice) continue;
// the car at carIndex is more expensive than old maximum, remember it
mostExpensivePrice = carLib[carIndex].price;
mostExpensiveIndex = carIndex;
}
if (mostExpensiveIndex == carLibCount) {
std::cout << "Most expensive car not found." << std::endl;
} else {
const car & carI = carLib[mostExpensiveIndex];
printf("Most expensive car at index %lu: %d %s %s %f %d\n",
mostExpensiveIndex, carI.year, carI.make, carI.model, carI.price, carI.available);
}
}
Live demo
Mind you, this is just array indexing example, this "old C" code style is very error prone to index-out-of-bounds code, overwriting memory, or accessing wrong memory. That's why in modern C++ you can use std::vector<car> carLib; instead, which is much better fit for such task.
Vector example:
#include <iostream>
#include <vector>
struct car
{
int year;
char make[10];
char model[10]; // that's only 9 letters for zero-terminated strings
float price;
int available;
};
int main()
{
std::vector<car> carLib;
carLib.push_back(car {1993, {"Nohda"}, {"XYZ"}, 123.45, 0});
carLib.push_back(car {1994, {"Frod"}, {"Peon"}, 543.21, 1});
carLib.push_back(car {1977, {"Nohda"}, {"ABC"}, 3.32, 0});
std::cout << "Cars in library: " << carLib.size() << std::endl;
for (const auto & kar : carLib) {
printf("%d %s %s %f %d\n",
kar.year, kar.make, kar.model, kar.price, kar.available);
}
if (0 < carLib.size()) {
// indexing trough size_t index still possible with vector
std::cout << "Last car price is: " <<
carLib[carLib.size()-1].price << std::endl;
// Last valid index being size()-1, because first index is 0
}
}
But that C-like is good for you to study details about computer memory, also it does introduce you to the "float is not a good variable type for amounts", as the live demo shows. So open it in debugger, and find some memory window, and study how the data are actually laid out in memory, how 10 letter long name of car makes your struct problematic, etc...
The std::vector stores the struct in the same way as the bare array, only having few more helper data around, and reserving the memory dynamically as you need, so understanding the array example (and it's shortcomings) first is just as important.
Here is a minimal example:
// Enable C++11 via this plugin
// [[Rcpp::plugins("cpp11")]]
#include <Rcpp.h>
#include <string>
using namespace Rcpp;
using namespace std;
/**
* Wrapper function for testFunc
*/
// [[Rcpp::export]]
void testFunc(DataFrame vars_ ) {
cout << "Type of vars_ " << TYPEOF(vars_) << endl;
DataFrame vars = clone(vars_);
CharacterVector out(vars_.nrows());
vector<string> varsV(vars_.nrows());
vector<int> varsVInt(vars_.nrows());
//Matrix is filled with input, Types are set to string
for (int i = 0 ; i< vars_.size(); i++){
if(TYPEOF(vars_[i])==STRSXP) {
varsV=Rcpp::as<std::vector<string> > (vars_[i]);
cout << "Type of the column " << i << " of the input data.frame is String." << endl;
for(int j=0; j<vars_.nrows(); j++){
cout << "varsV["<<j<<"] "<<varsV[j] << endl;
}
}
if(TYPEOF(vars_[i])==INTSXP) {
cout << "Type of the column " << i << " of the input data.frame is Int/Factor." << endl;
varsVInt = Rcpp::as<std::vector<int> > (vars_[i]);
if(varsVInt.size()>0)
{
for(int j=0; j<vars_.nrows(); j++){
varsV[j]=to_string(varsVInt[j]);//Copy the vector to the string
cout << "varsV["<<j<<"] "<<varsV[j] << endl;
} // end for
} //end if
} // end if
} // endfor
}
Execute Code:
ID <- c("0","1","2")
NAME2 <- c("Milla", "Milla","Miller")
dfString <-data.frame(ID,NAME2, stringsAsFactors=F)
################# test function
A = testFunc(as.data.frame(dfString[,2],stringsAsFactors=F))
B = testFunc(as.data.frame(dfString[,2]))
Call:
A = testFunc(as.data.frame(dfString[,2],stringsAsFactors=F))
Output:
Type of vars_ 19
Type of the column 0 of the input data.frame is String.
varsV[0] Milla
varsV[1] Milla
varsV[2] Miller
Call:
B = testFunc(as.data.frame(dfString[,2]))
Output:
Type of vars_ 19
Type of the column 0 of the input data.frame is Int/Factor.
varsV[0] 1
varsV[1] 1
varsV[2] 2
In void testFunc(DataFrame vars_ ) I expect an Rcpp::DataFrame, however if I paste a column of a data.frame, which is of class character, then it is also read without throwing an error, since the type seems the same (type 19). This character vector is handled a factor, see output.
Is there a way to force the right type (= Rcpp::DataFrame)? I don't want the user of the function accidentally paste the wrong type.
I'm currently having a real difficult time trying to sort my array (I really need to work on this, I always have trouble sorting data).
So basically I have created a C++ struct that contains a "date" and "snowDepth" element. I have used bubblesort logic to sort the snowDepth element, which is awesome and that's exactly what I need. However, since the elements are separate, the dates don't change. How can I sort a parallel array??
Data should look like this:
Snow Report December 12 - 18
Date Base
13 42.3
12 42.5
14 42.8
15 43.1
18 43.1
16 43.4
17 43.8
and mine looks like this:
SNOW REPORT December 12 - 18
=======================================
DATE DEPTH
12 42.3
13 42.5
14 42.8
15 43.1
16 43.1
17 43.4
18 43.8
Notice how the dates aren't sorted along with the snowDepth element. How can I accomplish this?
Okay, thanks for all the comments guys!! Here is my code:
// Structure
struct Array
{
int date;
double snowDepth;
void SnowData(int d, double sD)
{
date = d;
snowDepth = sD;
}
};
// Main Function
int main()
{
/* *--------------------*
| VARIABLES |
*--------------------* */
// Constant Variables
const int NUM_ELEMENTS = 7;
const int NUM_MONTHS = 12;
// String, Numerical, and Boolean Variables
string month;
int startDate;
int endDate;
int a;
int b;
int flag = 0;
double result;
bool monthMatch = false;
// Array Variables
Array snowData[NUM_ELEMENTS];
string name[NUM_MONTHS] = {"January", "February", "March",
"April", "May", "June",
"July", "August", "September",
"October", "November", "December" };
/* *--------------------*
| USER INSTRUCTIONS |
*--------------------* */
cout << endl;
cout << "This program will keep track of the local snow conditions for 7 days." << endl;
cout << "This program will ask the user for the month, date range (must be 7 days)," << endl;
cout << "and the inches of snow reported on that date. The program will then sort" << endl;
cout << "the data from least amount of snow reported to the most." << endl;
cout << endl;
/* *--------------------*
| USER PROMPT |
*--------------------* */
// Prompt the user for the month
cout << "Enter the full name of the month: ";
cin >> month;
// Prompt the user for the starting date
cout << "Enter the starting date of the 7-day period: ";
cin >> startDate;
snowData[0].date = startDate;
// Once the user enters the start date, run a loop to initialize the rest of the dates in snowData array
for (int x = 1; x < NUM_ELEMENTS; x++)
snowData[x].date = ++startDate;
// Prompt the user for the ending date
cout << "Enter the ending date of the 7-day period: ";
cin >> endDate;
cout << endl;
// If the user does not enter the correct ending date (which is 7 days from the start date), loop will prompt the user again
if (endDate != snowData[NUM_ELEMENTS - 1].date)
{
do
{
cout << "The end date entered is not 7 days from the start date. Try again." << endl;
cout << "Enter the ending date of the 7-day period: ";
cin >> endDate;
cout << endl;
} while (endDate != snowData[NUM_ELEMENTS - 1].date);
int x = 0;
// Once the user enters the correct ending date, prompt the user for the snow depth numbers
for (int y = 0; y < NUM_ELEMENTS; y++)
{
cout << "Enter the depth of snow measured on " << month << " " << snowData[x].date << ": ";
cin >> snowData[y].snowDepth;
x++;
}
}
// Once the user enters the correct ending date, prompt the user for the snow depth numbers
else
{
int x = 0;
for (int y = 0; y < NUM_ELEMENTS; y++)
{
cout << "Enter the depth of snow measured on " << month << " " << snowData[x].date << ": ";
cin >> snowData[y].snowDepth;
x++;
}
}
/* *--------------------*
| SORTING & FORMAT |
*--------------------* */
// Sorting logic in ascending order
for (a = 1; (a <= NUM_ELEMENTS) && flag; a++)
{
flag = 0;
for (b = 0; b < (NUM_ELEMENTS - 1); b++)
{
if (snowData[b + 1].snowDepth < snowData[b].snowDepth)
{
result = snowData[b].snowDepth;
snowData[b].snowDepth = snowData[b + 1].snowDepth;
snowData[b + 1].snowDepth = result;
flag = 1;
}
}
}
// Formatted Output
cout << endl;
cout << " SNOW REPORT ";
cout << month << " " << snowData[0].date << " - " << snowData[6].date << endl;
cout << "=======================================" << endl;
cout << setw(11) << "DATE" << setw(18) << "DEPTH" << endl;
for (int x = 0; x < (NUM_ELEMENTS); x++)
cout << setw(10) << snowData[x].date << setw(18) << snowData[x].snowDepth << endl;
cout << endl;
}
You could create a struct for a single date/snowDepth pair, and keep an array of such pairs. After you could add more fields there, and sort by whatever you like. The data will always be consistent.
By the way: why bubble sort? Quicksort is much faster.
Since both elements is in the same struct, the two elements should move together. Your array should be an array of structs. How do you have it configured now?
Update Added a std::map based example for good measure (see below)
I wouldn't work on sorting as much as on datastructures :)
Here is a sample that I wrote in order to brush-off the dust of my C++ skills :)
Sorry if I threw in more than the kitchen sink.
Also note, that for this 'tivial' datatype you could probably use std::pair as the 'Report' struct and std::map as the container type, requiring substantially less manual coding, but I wanted to show you how things are done if you coded the struct manually:
#include <iostream>
#include <vector>
#include <string>
#include <algorithm>
#include <iterator>
static struct Report
{
int date;
double base;
Report(int d, double b) : date(d), base(b) {}
bool operator<(const Report& rhs) const
{
return (date<rhs.date) || ((date==rhs.date) && (base<rhs.base));
}
friend std::ostream& operator<<(std::ostream& os, const Report& r)
{
os << "Report(" << r.date << ", " << r.base << ")";
}
} theData[] = {
Report( 13, 42.3),
Report( 12, 42.5),
Report( 14, 42.8),
Report( 15, 43.1),
Report( 18, 43.1),
Report( 16, 43.4),
Report( 17, 43.8),
};
int main(int argc, const char* args[])
{
Report *const begin = theData;
Report *const end = theData+(sizeof(theData)/sizeof(*theData));
// simpler container, take a copy for comparison
std::vector<Report> simplerData(begin, end);
// just sort it
std::sort(begin, end);
// VERIFY by printing to console
std::cout << "Verify sorted array: " << std::endl;
std::copy(begin, end, std::ostream_iterator<Report>(std::cout, "\n"));
std::cout << "=====================" << std::endl;
std::cout << "Verify unsorted copy:" << std::endl;
std::copy(simplerData.begin(), simplerData.end(), std::ostream_iterator<Report>(std::cout, "\n"));
std::cout << "=====================" << std::endl;
// Sort that as well - for fun, reversed
std::sort(simplerData.begin(), simplerData.end(), std::not2(std::less<Report>()));
std::cout << "Verify reversed copy:" << std::endl;
std::copy(simplerData.begin(), simplerData.end(), std::ostream_iterator<Report>(std::cout, "\n"));
std::cout << "=====================" << std::endl;
}
Compile and run using:
g++ -o test test.cpp
./test
Output:
Verify sorted array:
Report(12, 42.5)
Report(13, 42.3)
Report(14, 42.8)
Report(15, 43.1)
Report(16, 43.4)
Report(17, 43.8)
Report(18, 43.1)
=====================
Verify unsorted copy:
Report(13, 42.3)
Report(12, 42.5)
Report(14, 42.8)
Report(15, 43.1)
Report(18, 43.1)
Report(16, 43.4)
Report(17, 43.8)
=====================
Verify reversed copy:
Report(18, 43.1)
Report(17, 43.8)
Report(16, 43.4)
Report(15, 43.1)
Report(14, 42.8)
Report(13, 42.3)
Report(12, 42.5)
=====================
For completeness, here's what it would look like when using std::map as I suggested above. Note that ordering by keys is implicit:
namespace std // hacky, google Koenig lookup...
{
template <class K, class V> static std::ostream& operator<<(std::ostream& os, const std::pair<K, V> p)
{ os << "[" << p.first << ", " << p.second << "]"; }
}
void static UsingStdMap()
{
typedef std::map<int, double> Reports;
typedef Reports::value_type Report;
static const Report initializer[] = {Report(13,42.3),Report(12,42.5),Report(14,42.8),Report(15,43.1),Report(18,43.1),Report(16,43.4),Report(17,43.8)};
Reports theMap(initializer, initializer+sizeof(initializer)/sizeof(*initializer));
std::copy(theMap.begin(), theMap.end(), std::ostream_iterator<Report>(std::cout, "\n"));
}
Did I mention I'm a bit lazy? Hence the hack to display the items using stream operator.
To use custom ordering, see here for example
If your homework assignment is specifically about learning to write a sorting algorithm, replace this code:
// Sorting logic in ascending order
...
result = snowData[b].snowDepth;
snowData[b].snowDepth = snowData[b + 1].snowDepth;
snowData[b + 1].snowDepth = result;
...
with this:
// Sorting logic in ascending order
...
Array tmp = snowData[b];
snowData[b] = snowData[b + 1];
snowData[b + 1] = tmp;
...
If your assignment is not about learning to write a sort, use std::sort:
bool Array::operator<(const Array& rhs) const { return this->snowDepth < rhs.snowDepth; }
...
// Sorting logic in ascending order
std::sort(snowData, snowData+NUM_ELEMENTS);
P.s. Your data type Array is misnamed. It doesn't hold an array, it holds a single observation.
Since you've asked this under a C++ tag, here's one way in C++:
typedef std::pair<Date, double> SnowReportItem;
std::vector<SnowReportItem> SnowReport;
struct sort_criteria {
bool operator()(const SnowReportItem &a, const SnowReportItem &b)
{ return a.second < b.second; }
};
SnowReport.push_back(make_pair(Date("12 Feb 2011"), 42.5));
// similar ones for the others ...
std::sort(SnowReport.begin(), SnowReport.end(), sort_criteria);
Also, see this stackoverflow question.
EDIT: std::pair.second is not a function.
You were so close! It's correct that you compare the snowDepth values of the array elements, but you shouldn't just re-arrange those values. Instead, you should re-arrange the entire Array value.
Instead of this:
result = snowData[b].snowDepth;
snowData[b].snowDepth = snowData[b + 1].snowDepth;
snowData[b + 1].snowDepth = result;
Do this:
Array temp = snowData[b];
snowData[b] = snowData[b + 1];
snoData[b + 1] = temp;
That will move both the snowDepth value and the date value (because they're members of the same struct).
You're already storing the data in a struct, so the simplest thing would actually be to just define operator< and swap for your Array type.
struct Array
{
int date;
double snowDepth;
void SnowData(int d, double sD)
{
date = d;
snowDepth = sD;
}
friend bool operator<(const SnowData &a, const SnowData &b)
{
return a.date < b.date;
}
friend void swap(SnowData &a, SnowData &b)
{
using std::swap;
swap(a.date, b.date);
swap(a.snowDepth, b.snowDepth);
}
};
// ...later... sort the array
std::sort(snowData, snowData + NUM_ELEMENTS);