In my program, I have an empty string vector that gets filled in via user input. The program is meant to take numbers from user input, then sort those numbers in order from smallest to largest (the data type is string to make it easier to check for undesired inputs, such as whitespaces, letters, punctuation marks, etc.). As it is, the program sorts the numbers according to starting digit instead of size. How can I change the program to sort the way I want it to?
#include <iostream>
#include <vector>
#include <algorithm>
#include <limits>
#include <string>
#include <sstream>
using namespace std;
int main()
{
vector<string> vect;
string input;
int intInput;
int entries = 0;
int i = 0;
int x = 0;
while (x < 1)
{
i ;
cout << "Please input an integer. When finished providing numbers to organize,
input any character that isn't an integer:\n";
vect.resize(i 1);
getline(cin, input);
cout << endl;
stringstream ss(input);
if (ss >> intInput)
{
if (ss.eof())
{
vect.push_back(input);
entries ;
}
else
{
cout << "Error: Invalid input.\n\n";
}
}
else if (entries < 1)
{
cout << "Error: Invalid input.\n\n";
i = -1;
continue;
}
else if (entries >= 1)
{
break;
}
}
cout << "All done? Organizing numbers!\n";
sort(vect.begin(), vect.end());
for (int j = 0; j < vect.size(); j )
{
cout << vect[j] << endl;
}
return 0;
}
I've tried various methods to convert string data to int data, such as lexical cast & stoi(), but it didn't work, so I would like to know if there's another way, such as sorting the data without changing the data type.
CodePudding user response:
You can specify a comparision function that returns whether the first argument is "less than" the second argument to the std::sort
function.
While testing, I found that some empty strings, which make std::stoi
throw std::invalid_argument
, are pushed into the vector (it looks like by vect.resize(i 1);
). Therefore, I added some code to detect the error and evaluate the invalid strings as smaller than any valid integers.
sort(vect.begin(), vect.end(), [](const string& a, const string& b) {
bool aError = false, bError = false;
int aInt = 0, bInt = 0;
try {
aInt = stoi(a);
} catch (invalid_argument&) {
aError = true;
}
try {
bInt = stoi(b);
} catch (invalid_argument&) {
bError = true;
}
if (aError && !bError) return true;
if (bError) return false;
return aInt < bInt;
});
#include <stdexcept>
should be added to use std::invalid_argument
.
References:
- std::sort - cppreference.com
- std::stoi, std::stol, std::stoll - cppreference.com
- std::invalid_argument - cppreference.com
CodePudding user response:
The vect has two character at the starting that can not be converted to string. Here is the same code of yours just with added 2.
#include <iostream>
#include <vector>
#include <algorithm>
#include <limits>
#include <string>
#include <sstream>
using namespace std;
int main()
{
vector<string> vect;
string input;
int intInput;
int entries = 0;
int i = 0;
int x = 0;
while (x < 1)
{
i ;
cout << "Please input an integer. When finished providing numbers to organize, input any character that isn't an integer:\n";
vect.resize(i 1);
getline(cin, input);
cout << endl;
stringstream ss(input);
if (ss >> intInput)
{
if (ss.eof())
{
vect.push_back(input);
entries ;
}
else
{
cout << "Error: Invalid input.\n\n";
}
}
else if (entries < 1)
{
cout << "Error: Invalid input.\n\n";
i = -1;
continue;
}
else if (entries >= 1)
{
break;
}
}
cout << "All done? Organizing numbers!\n";
sort(vect.begin() 2, vect.end()); //added 2 here
for (int j = 2; j < vect.size(); j ) //iterating from 2
{
cout << vect[j] << endl;
}
return 0;
}
Its working on my linux, hopfully it works on yours too