这个问题有两个方面:解析和排序。
- 您可以使用正则表达式来检查用户输入的数据类型。
- 您可以使用
cin
来解析数据。
首先:意识到在收到所有用户输入之前,您不一定知道用户输入的类型〜例如:考虑用户名列表:
728278243
390349346
495045594
elizabeth
因此,最好不要假设最了解传入数据(可能导致令人沮丧的用户体验),而是更愿意将所有内容视为潜在的字符串。将所有原始输入存储为字符串,以便您可以以与输入相同的格式输出。您可以使用枚举类型在排序比较器内部进行切换,
或者考虑使用mutliset/multimap
. 在这里,您将构建一个有序集。所以不需要排序。NB:构造一个有序集合的 N 个元素的复杂度,或者对于 N 个未排序的列表元素进行单一排序,其复杂度大致相等 ~> NlogN
对于您手头的任务,这几乎不重要,但实际上取决于列表的使用方式,在性能方面,一种或其他方法将更合适。
如果你已经使用过std::vector
then之类的std::multimap
应该不会太吓人。松散地说,它是一个关联的键值对数组。这里的multi意味着它可以使用相同的键存储多个元素(在这里,你想要)。
在这个例子中,我使用boost regex 库来确定一些时髦的输入数据类型。
(例如sudo apt-get install libboost-regex1.46-dev
:)
这个正则表达式可能看起来晦涩难懂,但 i/web 上有许多示例,几乎适用于所有可以想象的模式。[注意:C++11 正则表达式几乎是 boost 正则表达式的替代品。即:boost regex 应该与新兴的 C++11 标准前向兼容]
废话.cpp:
#include <iostream>
#include <sstream>
#include <string>
#include <list>
#include <map>
#include <set>
#include <boost/regex.hpp>
//NB: GNU gcc added *experimental support for regular expressions in TR1 v 4.3.0.
// compile with: -std=c++0x
using namespace std;
using namespace boost;
//some example input data-types (perhaps notably missing a date!)
const regex re_char("[^0-9]", regex_constants::extended); //non numeric chars
const regex re_digit("[[:digit:]]+", regex_constants::extended); //a string of only digits in range [0..9] ~ie: Z+
const regex re_xdigit("0[xX][[:xdigit:]]+", regex_constants::extended); //support hex iff starts with '0x' or '0X'
const regex re_float("[-+]?[0-9]*\\.?[0-9]+([eE][-+]?[0-9]+)?", regex_constants::extended); //all kinds of numbers
int main(int argc, char** argv)
{
int i, countc=0;
double d;
string str;
int element_count;
do
{
cout << "how many elements will there be? ";
if (cin >> element_count) break;
cin.clear();
cin >> str;
cout << "\033[A\033[2K" << flush;
}
while(13);
cin.ignore(128,'\n');
multimap<double, string> list_num;
multimap<double, string> list_fp;
//NB: below, by way of example, construction using the 'greater<int>' comparison class achieves _descending_ order
multimap<int, string, greater<int> > list_int;
list<string> list_str;
for (int next=0; next < element_count; next++)
{
cout << "\033[A\033[2K" << flush;
cout << "enter next element in list ["<< next+1 << "/" << element_count << "] : ";
getline (cin,str);
if (regex_match(str, re_xdigit))
{
//see all about manipulators here:
//http://www.cplusplus.com/reference/iostream/istream/operator%3E%3E/
stringstream(str) >> hex >> i;
list_int.insert(pair<int, string>(i, str));
list_num.insert(pair<double, string>(i, str));
}
else if (regex_match(str, re_digit))
{
stringstream(str) >> i;
list_int.insert(pair<int, string>(i, str));
list_num.insert(pair<double, string>(i, str));
}
else if (regex_match(str, re_float))
{
stringstream(str) >> d;
list_fp.insert(pair<double, string>(d, str));
list_num.insert(pair<double, string>(d, str));
}
if (regex_match(str, re_char)) countc++;
list_str.push_back(str);
}
cout << "\033[A\033[2K" << flush;
cout << "input: unsorted list:" << endl;
for (list<string>::iterator it=list_str.begin(); it!=list_str.end(); it++)
cout << *it << endl;
if (list_int.size() == element_count)
{
cout << endl << "output: sorted list of Z+ types:" << endl;
for (multimap<int, string>::iterator it=list_int.begin() ; it != list_int.end(); it++ )
cout << (*it).second << endl;
}
else if (list_fp.size() == element_count)
{
cout << endl << "output: sorted list of fp types:" << endl;
for (multimap<double, string>::iterator it=list_fp.begin() ; it != list_fp.end(); it++ )
cout << (*it).second << endl;
}
else if (list_num.size() == element_count)
{
cout << endl << "output: sorted list of numeric types:" << endl;
for (multimap<double, string>::iterator it=list_num.begin() ; it != list_num.end(); it++ )
cout << (*it).second << endl;
}
else //output as sorted strings ~but in _descending_ order, using reverse iterator, by way of example
{
list_str.sort(); //but best to use list_str.sort(greater<string>()); with forward iterators
cout << endl << "output: sorted list of " << (countc == element_count ? "non numeric char" : "string") << " types:" << endl;
for (list<string>::reverse_iterator it=list_str.rbegin(); it!=list_str.rend(); ++it)
cout << *it << endl;
}
return 0;
}
示例在 Ubuntu 上编译和运行。命令行的东西:
$
$ lsb_release -d
Description: Ubuntu 11.10
$ g++ --version
g++ (Ubuntu/Linaro 4.6.1-9ubuntu3) 4.6.1
$ g++ --pedantic -oblah blah.cpp -lboost_regex
$ ./blah
input: unsorted list:
4.77
2.0e+2
-.3
11
0x10
output: sorted list of numeric types:
-.3
4.77
11
0x10
2.0e+2
$
注意:这是示例代码:
- 这里可以进行许多优化。您显然不需要像
stl
我使用的那么多容器。
- 我没有严格处理排序的方向(但展示了几种可能实现的方法)。
- 将特定于类型的功能封装在 C++ 对象中也可能很好;对于您希望支持的每种类型都有一个基类和派生类~但是这个作业对吗?- 所以可能不值得过火;)