2016-02-27 63 views
1

我想弄清楚如何alphabetize包含單詞和數字的單個字符串。正如你在下面看到的,我試過使用isdigit,但其中一些數字是負數,所以我的代碼總是錯的。此外,我的代碼將字符串拆分爲字母串分開的子字符串,但我不知道如何分別字母化所有單詞,將它們放回到它們在矢量中的位置,然後單獨將所有數字字母化,然後放回進入他們的位置。有人可以幫忙嗎?Alphabetize字符串與文字和數字

編輯:

樣品輸入#1:

4 dog 1 -3 0 cat 3 

示例輸出#1:

-3 cat 0 1 3 dog 4 

樣品輸入#2:

tom 4 0 9 kid pie 1 

示例輸出#2 :

kid 0 1 4 pie tom 9 

到目前爲止,我的代碼如下所示:

vector<string> numbers; 
string str; 
string x;     
getline (cin, str); 
stringstream ss(str); 
while (ss >> x){ 
    numbers.push_back(x); 
} 

if (numbers.size()==1){ 
    cout << numbers[0] << endl; 
    return 0; 
} 

vector<int> results(numbers.size()); 
for (int i=0;i<numbers.size();i++){ 
    char *a=new char[numbers[i].size()+1]; 
    a[numbers[i].size()]=0; 
    memcpy(a,numbers[i].c_str(),numbers[i].size()); 
    if(isdigit(*a)==0) 
    { 
     results[i]=1; 
    } else{ 
     results[i]=0; 
    } 
} 

int j=0; 
while (j<numbers.size()){ 
    int k=j+1; 
    while (k<numbers.size()){ 
     while (results[j]==results[k]){ 
      sort(numbers.begin()+j,numbers.begin()+k+1); 
      k++; 
     } 
     j=k; 
     k=numbers.size(); 
    } 
    if(j==numbers.size()){ 
     for (int i=0; i<numbers.size();i++){ 
      cout << numbers[i] << " "; 
     } 
     j++; 
    } 
} 
+0

請將樣本輸入,預期輸出和觀測輸出。 –

+0

你可以分享樣本輸入輸出嗎?需要確定你正在嘗試做什麼。 –

+0

'char * a = new char [numbers [i] .size()+ 1];'爲什麼? – PaulMcKenzie

回答

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 
} 
+0

感謝您的幫助。我覺得這個代碼是最易讀和最容易遵循的! – Jeremy

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::sort排序的字符串的int std::vector

// include <algorithm> // sort 

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

的其他解決辦法是分裂的兩個vector單獨vector秒。一個字符串和一個數字和他們sperately排序:

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()); 

,如果你想知道每個字符串或數字的原vector位置使用std::map

#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具有comperator功能太:

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; 
} 
+0

感謝您的幫助!我唯一看到的是這個代碼不會將單詞/數字分別放回屬於單詞和數字的位置。 – Jeremy

+0

@Jeremy如果你想知道原始矢量中每個字符串或數字的位置,請使用'std :: map'。看到我答案的最後部分。 – Rabbid76

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'),但如果它不應該的問題,增加了修復程序,很容易。

+0

對不起,但是名爲sorted的向量是從哪裏來的呢? – Jeremy

+0

@Jeremy我意識到我離開了它,我編輯了變量聲明。也許你需要重新加載頁面。 –

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++] << ' '; 
    } 
} 
+0

這種方式看起來更好,但請提一下,如果您無法事先預測元素的數量,我會相應地修改代碼。 – anukul

+0

我無法預測元素的數量 – Jeremy

+0

好的,我已經做出了修改。現在應該工作正常。 – anukul