この質問には、解析と並べ替えという 2 つの側面があります。
- 正規表現を使用して、ユーザー入力のデータ型を確認できます。
- を使用
cin
してデータを解析できます。
最初に:すべてのユーザー入力を受け取るまで、必ずしもユーザー入力のタイプを知ることはできないことを理解してください~eg: ユーザー名のリストを検討してください:
728278243
390349346
495045594
elizabeth
したがって、受信データについて最もよく知っていると仮定しないでください (イライラするユーザーエクスペリエンスにつながる可能性があります)。代わりに、すべてを潜在的な文字列として扱うことを好みます。入力と同じ形式で出力できるように、すべての生の入力を文字列として保存します。たとえば、列挙型を使用して並べ替えコンパレータ内で切り替える
か、mutliset/multimap
. ここでは、順序付きセットを作成します。したがって、並べ替える必要はありません。注意: N 個の要素の順序付けられたセットを構築するための複雑さ、またはN個の並べ替えられていないリスト要素の単一の並べ替えの場合、おおよそ同等です ~> NlogN
手元のタスクではほとんど問題になりませんが、実際には、リストの使用方法に応じて、パフォーマンスの観点から、いずれかのアプローチがはるかに適切になります。
のようなものをすでに使用している場合は、std::vector
それほどstd::multimap
怖くないはずです。大まかに言えば、これはキーと値のペアの関連配列です。ここでのmultiは、同じキーを持つ複数の要素を格納できることを意味します (ここでは必要です)。
この例では、ファンキーな入力データ型
を特定するために、ブースト正規表現ライブラリを使用しています。(例: )
sudo apt-get install libboost-regex1.46-dev
この正規表現は難解に思えるかもしれませんが、考えられるほぼすべてのパターンについて i/web に多くの例があります。[注意: C++11 正規表現は、ほとんどブースト正規表現のドロップイン代替品です。つまり、ブースト正規表現は、新しい 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++ オブジェクトにカプセル化するのもよいでしょう。サポートしたいタイプごとに基本クラスと派生クラスがありますが、この宿題は正しいですか?-そのため、おそらく船外に出る価値はありません;)