Checking a vector for duplicate values
MPD78
11-16-2010, 07:33 AM
Hello all,
When using a vector, is there an STL function that will check for duplicate values in the vector? If not how does one check for this condition?
For example, the user can select from 20 different gases and enter the volume percent of each gas until 100% is achieved.
So we have a vector of volume percents and a vector of the corresponding gas mixture components.
gas_number[0] = 1 and gas_volume_percent[0] = 10
Suppose that gas #1 is CH4 and the user made an error and should have input 20%. Now the user re-enters CH4 and 10%.
The subsequent calculations require the total 20% of CH4 instead of 2 entrys of 10%.
How can this error be detected and how can the components be combined to obtain 20%?
Thanks
Matt
davekw7x
11-17-2010, 09:33 AM
...is there an STL function that will check for duplicate values in the vector?
In a word: no.
If not how does one check
In a loop. Maybe two loops
For example, the user
One way:
As each entry is made by the user you can loop through the stuff that has been entered previously to see whether that gas is already present.
If it is, then add newly entered percent value to previously entered percent value for that gas. Don't put newly entered stuff into the vectors. (See Footnote.)
Or, if you don't want to modify your user input function, you could wait until all entries have been made and then use nested loops to handle any possible duplicates the way that you indicated:
Outer loop: Set index to zero (first vector entry).
Perform the outer loop (incrementing the index each iteration)
until you get to the next-to-last position.
BEGIN OUTER LOOP
Inner loop: Set an index the next element after the outer
loop index. Perform the inner loop (incrementing the index
each iteration) until you get to the last position.
BEGIN INNER LOOP
IF gas name of inner loop position is equal to gas name of
outer loop position THEN
Add percent value of inner loop to the outer loop
percent entry.
vector::erase the gas and percent vector elements
at the inner loop position.
END IF
END INNER LOOP
END OUTER LOOP
Regards,
Dave
Footnote:
Instead of having different vectors for gas and percent, why not have a struct consisting of gas and percent values. Then work on a vector of these structs.
Just a thought.
MPD78
11-17-2010, 10:10 AM
Thanks Dave,
Here is the code I currently have for the input of the gases and their corresponding volume percents.
struct GASS {
// Object for the user input gas composition
// Needed local variables
double vol,total; // volume percent of each component
double temp; // temperature used for calculations, Farenheit
int i;
vector<double> gas_vol; // flow volume percent for each component vector
vector<int> gas_num; // flow component number vector
// Needed functions
void gas_comp_input();
};
void GASS::gas_comp_input(){
// Function used to obtain the primary gas composition.
// Once the user has input a number corresponding to the desired
// gas, the user will be prompted to enter the volume percent of
// the selected gas. This will repeat in a loop until 100% volume
// is achieved.
vol = 0;
total = 0;
i = 0;
cout << "Standard Gases" << endl << endl;
cout << "0. N2" << setw(10) << "7. AIR" << setw(10) << "13. CH4" << setw(10) << "18. HCL" << endl;
cout << "1. O2" << setw(9) << "8. H2" << setw(12) << "14. C2H6" << setw(9) << "19. H2S" << endl;
cout << "2. CO2" << setw(8) << "9. CO" << setw(12) << "15. C3H8" << setw(9) << "" << endl;
cout << "3. H2O" << setw(8) << "10. NO" << setw(13) << "16. C4H10" << setw(8) << "" <<endl;
cout << "4. SO2" << setw(9) << "11. NO2" << setw(12) << "17. C5H12" << setw(8) << "" << endl;
cout << "5. SO3" << setw(9) << "12. NH3" << setw(12) << "" << setw(8) << "" << endl;
cout << "6. CL2" << setw(9) << "" << setw(12) << "" << setw(8) << "" << endl << endl;
while(total != 1.0){
i = get_int(0,19,"\t Gas number ", "Invalid entry");
cout << endl << "\t " << int_to_gas(i) << "\n";
vol = get_int(0,100,"\t Volume percent ", "Invalid entry");
vol = vol/100;
total += vol;
gas_vol.push_back(vol);
gas_num.push_back(i);
if(total > 1.0){
cout << "\t Total volume > 100 You must re-enter your values" << endl;
total = 0;
gas_vol.clear();
gas_num.clear();
}
}
cout << endl;
temp = get_double(0,"Temperature (F) ", "Sorry, invalid entry" );
}
Here are the needed input functions.
void skip_to_int()
{
if(cin.fail()){
cin.clear();
char ch;
while(cin >> ch){
if(isdigit(ch)){
cin.unget();
return;
}
}
}
error("no input");
}
int get_int()
{
double n=0;
while(true){
if(cin >> n) return n;
cout << "Sorry that was not a number; please try again \n";
skip_to_int();
}
}
int get_int(int low, const string& greeting, const string& sorry)
{
cout << greeting << endl;
while(true){
double n = get_int();
if(n > low) return n;
cout << sorry << endl;
}
}
int get_int(int low, int high, const string& greeting, const string& sorry)
{
cout << greeting << " ";
while(true){
int n = get_int();
if( low <= n && n <= high) return n;
cout << sorry << endl;
}
}
double get_double(double low, const string& greeting, const string& sorry)
{
cout << greeting << " ";
while(true){
double n = get_int();
if(low <= n) return n;
cout << sorry << endl;
}
}
Lastly, here are the tables
vector<string> gas_input_tbl;
void init_input_tbl(vector<string>& tbl)
// initialize vector of input representations
{
tbl.push_back("N2");
tbl.push_back("O2");
tbl.push_back("CO2");
tbl.push_back("H2O");
tbl.push_back("SO2");
tbl.push_back("SO3");
tbl.push_back("CL2");
tbl.push_back("AIR");
tbl.push_back("H2");
tbl.push_back("CO");
tbl.push_back("NO");
tbl.push_back("NO2");
tbl.push_back("NH3");
tbl.push_back("CH4");
tbl.push_back("C2H6");
tbl.push_back("C3H8");
tbl.push_back("C4H10");
tbl.push_back("C5H12");
tbl.push_back("HCL");
tbl.push_back("H2S");
}
int gas_to_int(string s)
// is s the name of a gas? If so return its index[0:19] otherwise -1
{
for(int i=0;i<19;++i) if(gas_input_tbl[i] == s) return i;
return -1;
}
vector<string> gas_print_tbl;
void init_print_tbl(vector<string>& tbl)
// initialize vector of output representations
{
tbl.push_back("N2");
tbl.push_back("O2");
tbl.push_back("CO2");
tbl.push_back("H2O");
tbl.push_back("SO2");
tbl.push_back("SO3");
tbl.push_back("CL2");
tbl.push_back("AIR");
tbl.push_back("H2");
tbl.push_back("CO");
tbl.push_back("NO");
tbl.push_back("NO2");
tbl.push_back("NH3");
tbl.push_back("CH4");
tbl.push_back("C2H6");
tbl.push_back("C3H8");
tbl.push_back("C4H10");
tbl.push_back("C5H12");
tbl.push_back("HCL");
tbl.push_back("H2S");
}
string int_to_gas(int i)
// gas [0:19]
{
if(i < 0 || 20 <= i) error("Bad index in gas table");
return gas_print_tbl[i];
}
If you just paste all of that into one file it will compile correctly.
I do have the two vectors located in a struct, if you could help me out with how to check them, that would be great.
Thanks
Matt
davekw7x
11-17-2010, 12:46 PM
Right after you get the gas number and volume, you can do something like the following:
void GASS::gas_comp_input()
{
// Function used to obtain the primary gas composition.
.
.
.
// Print menu and get gas number and volume from user
//
//
total += vol; // Your previous code
unsigned indx; // Beginning of new code
for (indx = 0; indx < gas_num.size(); indx++) {
if (gas_num[indx] == i) { // Found a duplicate
gas_vol[indx] += vol;
// Let the user know what happened.
cout << "Found duplicate gas entry for " << int_to_gas(indx)
<< ". New volume is "
<< fixed << setprecision(2) << gas_vol[indx]
<< endl;
break;
}
}
if (indx == gas_num.size()) { // It's not a duplicate
gas_vol.push_back(vol);
gas_num.push_back(i);
} // End of new code
if (total > 1.0) { // Your previous code
.
.
.
Regards,
Dave
MPD78
11-17-2010, 01:16 PM
Thanks Dave,
It works just as I intended it to.
Thanks
Matt