用字和数字按字母顺序排列的字符串

时间:2016-02-27 06:11:35

标签: c++ string algorithm vector

我正在试图弄清楚如何将包含单词和数字的单个字符串按字母顺序排列。如下所示,我尝试使用 int num; while(cin.good()) //could also use while(cin) { cin >> num; cout << num << endl; } ,但有些数字是否定的,所以我的代码总是错误的。此外,我的代码将字符串拆分为分别按字母顺序排列的子字符串,但我不知道如何分别按字母顺序排列所有单词,将它们放回到向量中的位置,然后将所有数字分别按字母顺序排列,然后将它们放回去进入他们的位置。有人可以帮忙吗?

编辑:

示例输入#1:

isdigit

示例输出#1:

4 dog 1 -3 0 cat 3

示例输入#2:

-3 cat 0 1 3 dog 4

示例输出#2:

tom 4 0 9 kid pie 1

到目前为止,我的代码看起来像这样:

kid 0 1 4 pie tom 9

4 个答案:

答案 0 :(得分:2)

首先,您需要一个函数来确定字符串是否为数字。请使用strtol

#include <stdlib.h> // strtol

bool is_number( const std::string &str, long &num )
{
    char *p;
    num = strtol( str.c_str(), &p, 10 );
    return *p == '\0';
}

在第二个函数中使用此函数,该函数确定字符串a是否小于字符串b

#include <tuple>

bool sortFunc( const std::string &a, const std::string &b )
{ 
    long numA;
    long numB;
    bool is_a_num = is_number( a, numA );
    bool is_b_num = is_number( b, numB );
    return std::make_tuple( !is_a_num, numA, a ) < std::make_tuple( !is_b_num, numB, b );                                      
}

使用std::sortstd::vector

中的字符串进行排序
// include <algorithm> // sort

std::vector< std::string > numbers;
.... 
std::sort( numbers.begin(), numbers.end(), sortFunc );

另一种解决方案是将vector拆分为两个单独的vector。一个用于字符串,一个用于数字,并分别对它们进行排序:

std::vector< std::string > numbers;
....
std::vector< std::string > vStr;
std::vector< long > vNum;
for ( std::string &str: numbers )
{
    long num;
    if ( is_number( str, num )
        vNum.push_back( num );
    else
        vStr.push_back( str);
}
std::sort( vNum.begin(), vNum.end() );
std::sort( vStr.begin(), vStr.end() );

如果您想知道原始std::map中每个字符串或数字的位置,请使用vector

#include <map>

std::vector< std::string > numbers;
....
std::map< std::string, size_t > mapStr; // map string to index of string in vector numbers
std::map< long, size_t > mapNum;        // map number to index of number in vector numbers
for ( size_t index = 0; index < numbers.size(); index ++ )
{
    long num;
    if ( is_number( numbers[index], num ) )
        mapNum.emplace( num, index );
    else
        mapStr.emplace( numbers[index], index );
}

for ( auto & pa : mapNum )
    std::cout << pa.first << " pos " << pa.second << std::endl;
for ( auto & pa : mapStr )
    std::cout << pa.first.c_str() << " pos " << pa.second << std::endl;

当然,你也可以使用一个带有比较器功能的std::map

std::vector< std::string > numbers;
....
std::map< std::string, size_t, bool(*)(const std::string &a, const std::string &b) > mapN( sortFunc );
for ( size_t index = 0; index < numbers.size(); index ++ )
    mapN.emplace( numbers[index], index );

for ( auto & pa : mapN )
    std::cout << pa.first << " pos " << pa.second << std::endl;

您也可以使用std::tuple作为std::map的密钥:

std::vector< std::string > numbers;
....
std::map< std::tuple< bool, long, std::string>, size_t > mapTupleN;
for ( size_t index = 0; index < numbers.size(); index ++ )
{
    long num;
    bool is_num = is_number( numbers[index], num );
    mapTupleN.emplace( std::make_tuple( !is_num, num, numbers[index] ), index );
}
for ( auto & pa : mapTupleN )
{
    if ( !std::get<0>(pa.first) )
        std::cout << std::get<1>(pa.first) << " is number at position " << pa.second << std::endl;
    else
        std::cout << std::get<2>(pa.first).c_str() << " is string at position " << pa.second << std::endl;
}

答案 1 :(得分:0)

在阅读元素时对元素进行排序可能更容易。

std::string input;
std::getline(std::cin, input);
std::stringstream ss(input);
std::vector<std::string> sorted;

while (ss >> input)
{
    bool alpha = 0 < std::isalpha(input[0]); //if it is a word
    for (std::size_t i = 0, e = sorted.size(); i != e; ++i)
    {
        if ((!!std::isalpha(sorted[i][0]) == alpha) && (alpha ? (input < sorted[i]) : (std::stoi(input) < std::stoi(sorted[i])))) //if input is <
            std::swap(sorted[i], input); //exchange places
    }
    sorted.emplace_back(std::move(input)); //insert input at end
}

while循环的每次迭代,它检查第一个字符以查看它是否是一个字母。如果是字母,则必须是单词,否则为数字。然后,对于每个先前扫描的元素,它检查它们是否是相同的类型(字母/字母,数字/数字)。在它们都是单词的情况下,它只是比较它们。如果它们是数字,则使用stoi将它们转换为整数并比较结果。如果比较结果input小于元素,则将元素与input交换。在for循环结束时,input是该类型的最大元素,并且插入后面。

It lives!

此比较中的案例很重要('a' != 'A'),但如果无关紧要,可以轻松添加修复。

答案 2 :(得分:0)

我的2p。

std::string alphabetize(const std::string& s)
{
    // string parts here
    std::vector<std::string> a;

    // integer parts here
    std::vector<int> n;

    // remember the order of the input types (true = integer, false = string)
    std::vector<bool> type_is_int_list;

    // wrap input in a stream for easy parsing
    std::istringstream iss(s);

    // somewhere to read each part into
    std::string item;

    // extract one space-separated part at a time
    while(iss >> item)
    {
        int i;
        if(std::istringstream(item) >> i) // is item an integer?
        {
            n.push_back(i);
            type_is_int_list.push_back(true);
        }
        else
        {
            a.push_back(item);
            type_is_int_list.push_back(false);
        }
    }

    // sort both string and integer vectors
    std::sort(a.begin(), a.end());
    std::sort(n.begin(), n.end());

    // a place to rebuild the output from the input
    std::ostringstream oss;

    // keep track of where we are in each vector
    auto a_iter = a.begin();
    auto n_iter = n.begin();

    // element separator
    std::string sep;

    // scan originally-ordered list of types to rebuild positions
    for(bool type_is_int: type_is_int_list)
    {
        if(type_is_int)
            oss << sep << *n_iter++; // add next sorted number to output
        else
            oss << sep << *a_iter++; // add next sorted string to output

        sep = " "; // after first item need space separator
    }

    return oss.str(); // return the reconstructed string
}

答案 3 :(得分:0)

这个怎么样?

#include "iostream"
#include "algorithm"
#include "string"
#include "vector"
#include "cctype"
#include "unordered_map"
using namespace std;

int main()
{
    vector <string> all, s;
    vector <int> n;
    unordered_map <int, bool> number;
    string x;
    getline(cin, x);
    int prev=0;
    for (int i=0; i<x.length(); i++)
    {
        if (x[i]==' ')
        {
            all.push_back(x.substr(prev, i-prev+1));
            prev=i+1;
        }
    }
    all.push_back(x.substr(prev));
    for (int i=0; i<all.size(); i++)
    {
        if (isdigit(all[i].c_str()[0]) || isdigit(all[i].c_str()[1]))
        {
            n.push_back(atoi(all[i].c_str()));
            number[i]=1;
        }
        else s.push_back(all[i]);
    }
    sort(s.begin(), s.end());
    sort(n.begin(), n.end());
    for (int i=0, j=0, k=0; i<all.size(); i++)
    {
        if (number[i]) cout << n[j++] << ' ';
        else cout << s[k++] << ' ';
    }
}