2010-09-23 101 views
7

我試圖通過維護空格來顛倒句子中的單詞順序,如下所示。C++中的字符串反轉

[this is my test string] ==> [string test my is this] 

我確實在一步步的方式,

[this is my test string] - input string 
[gnirts tset ym si siht] - reverse the whole string - in-place 
[string test my is this] - reverse the words of the string - in-place 
[string test my is this] - string-2 with spaces rearranged 

是否有任何其他的方法來做到這一點?是否有可能在現場做最後一步?

+3

我很想知道這背後的商業邏輯... – jcolebrand 2010-09-23 17:32:23

+0

@drachenstern嗯,你可能呈現雙向文本時需要類似的算法。 – ybungalobill 2010-09-23 17:36:37

+0

你是什麼意思你的「是否也可以做最後一步就地」?你有什麼已經在做一切就地。你在說什麼「最後一步」? – AnT 2010-09-23 17:38:37

回答

5

你的方法很好。但是,或者你也可以這樣做:

  • 請掃描單詞和輸入 空間
  • 如果你找到一個字將其推入堆棧 S
  • 如果您發現空間(S)排隊的 數空格成隊列Q

這樣做會出現在堆棧上N文字和N-1數字在q之後ueue。

While stack not empty do 
print S.pop 
if stack is empty break 
print Q.deque number of spaces 
end-while 
1

爲了從第一至中央的單詞切換單詞n,其中字長 - N的 首先使用分割功能,然後執行切換

-1

我想我正記號化(或strtok函數CString的:: Tokanize)的字符串使用空格字符。將字符串移動到一個矢量中,然後將它們以相反的順序拉回來,並將它們連接在一起。

+0

在找到中間空間的邏輯上稍微清理一下(必須保留原始空間順序)我只想這樣 – jcolebrand 2010-09-23 17:36:20

+0

這會如何保持單詞之間的多個空格,就像他在「test」和「string」之間的示例一樣? – KeithS 2010-09-23 17:38:10

+0

-1:strtok是zomg糟糕,CString不是標準C++ – 2010-09-23 18:22:15

1

此僞代碼假定您不會以空格結束初始字符串,但也可以對其進行適當修改。

1. Get string length; allocate equivalent space for final string; set getText=1 

2. While pointer doesn't reach position 0 of string, 

    i.start from end of string, read character by character... 
     a.if getText=1 
     ...until blank space encountered 
     b.if getText=0 
     ...until not blank space encountered 

    ii.back up pointer to previously pointed character 

    iii.output to final string in reverse 

    iv.toggle getText 

3. Stop 
0

所有strtok解決方案不適用於您的示例,請參閱上文。 試試這個:

char *wordrev(char *s) 
{ 
    char *y=calloc(1,strlen(s)+1); 
    char *p=s+strlen(s); 
    while(p--!=s) 
    if(*p==32) 
     strcat(y,p+1),strcat(y," "),*p=0; 
    strcpy(s,y); 
    free(y); 
    return s; 
} 
+0

需要使用calloc和free來做一些概念上簡單的事情似乎有點瘋狂嗎?你正在修改輸入字符串? – 2010-09-23 18:24:18

+0

是的,我修改它。您不知道之間的區別? – user411313 2010-09-23 19:35:16

+0

-1:不起作用; +0.5它編譯(http://codepad.org/8pQGNta3) - 總計舍入:0 – pmg 2010-09-24 15:28:22

2

這是一種方法。

簡而言之,建立兩個令牌列表:一個用於單詞,另一個用於空格。然後拼湊一個新的字符串,詞語以相反順序排列,空格按正向順序排列。

#include <iostream> 
#include <algorithm> 
#include <vector> 
#include <string> 
#include <sstream> 
using namespace std; 

string test_string = "this is my test string"; 

int main() 
{ 
    // Create 2 vectors of strings. One for words, another for spaces. 
    typedef vector<string> strings; 
    strings words, spaces; 
    // Walk through the input string, and find individual tokens. 
    // A token is either a word or a contigious string of spaces. 
    for(string::size_type pos = 0; pos != string::npos;) 
    { 
     // is this a word token or a space token? 
     bool is_char = test_string[pos] != ' '; 
     string::size_type pos_end_token = string::npos; 

     // find the one-past-the-end index for the end of this token 
     if(is_char) 
      pos_end_token = test_string.find(' ', pos); 
     else 
      pos_end_token = test_string.find_first_not_of(' ', pos); 

     // pull out this token 
     string token = test_string.substr(pos, pos_end_token == string::npos ? string::npos : pos_end_token-pos); 
     // if the token is a word, save it to the list of words. 
     // if it's a space, save it to the list of spaces 
     if(is_char) 
      words.push_back(token); 
     else 
      spaces.push_back(token); 
     // move on to the next token 
     pos = pos_end_token; 
    } 

    // construct the new string using stringstream 
    stringstream ss; 
    // walk through both the list of spaces and the list of words, 
    // keeping in mind that there may be more words than spaces, or vice versa 
    // construct the new string by first copying the word, then the spaces 
    strings::const_reverse_iterator it_w = words.rbegin(); 
    strings::const_iterator it_s = spaces.begin(); 
    while(it_w != words.rend() || it_s != spaces.end()) 
    { 
     if(it_w != words.rend()) 
      ss << *it_w++; 
     if(it_s != spaces.end()) 
      ss << *it_s++; 
    } 

    // pull a `string` out of the results & dump it 
    string reversed = ss.str(); 
    cout << "Input: '" << test_string << "'" << endl << "Output: '" << reversed << "'" << endl; 

} 
+0

謝謝你的解決方案!有一個小錯誤:試着用一些以空格開頭的字符串來反轉。我試圖修改這些代碼以減少內存消耗(不需要保留字符串向量,只需要向量位置即可)。這是我重寫代碼的模糊嘗試:http://ideone.com/2uw9e。 – ovgolovin 2012-07-14 19:25:06

0

太糟糕stl字符串沒有實現push_front。然後你可以用transform()來做到這一點。

#include <string> 
#include <iostream> 
#include <algorithm> 

class push_front 
{ 
public: 
    push_front(std::string& s) : _s(s) {}; 
    bool operator()(char c) { _s.insert(_s.begin(), c); return true; }; 
    std::string& _s; 
}; 

int main(int argc, char** argv) 
{ 

    std::string s1; 
    std::string s("Now is the time for all good men"); 
    for_each(s.begin(), s.end(), push_front(s1)); 

    std::cout << s << "\n"; 
    std::cout << s1 << "\n"; 
} 

現在是所有好男人

時間

NEM doog LLA ROF EMIT EHT始源

+0

-1這甚至不是什麼OP要求 – pmg 2010-09-24 14:30:45

2

我想改寫這個問題是這樣的:

  • 非 - 空格令牌被顛倒,但保留其原始順序
    • 5個非空格標記'this','是','my','test','string'被顛倒爲'string','test','my','is','this' 。
  • 空間令牌停留在原來的順序
    • 空間令牌「「,「「,「「,「「保持在非空令牌的新秩序之間的原始順序。

以下爲O(N)溶液[N是字符數組的長度]。不幸的是,它不是OP所需要的,但它不使用額外的堆棧或隊列 - 它使用單獨的字符數組作爲工作空間。

這是一個C-ish僞代碼。

work_array = char array with size of input_array 
dst = &work_array[ 0 ] 

for(i = 1; ; i++) { 
    detect i’th non-space token in input_array starting from the back side 
    if no such token { 
     break; 
    } 
    copy the token starting at dst 
    advance dst by token_size 
    detect i’th space-token in input_array starting from the front side 
    copy the token starting at dst 
    advance dst by token_size 
} 

// at this point work_array contains the desired output, 
// it can be copied back to input_array and destroyed 
+0

+1良好的一般方法,雖然我會分解它!NUL {1)掃描下一個文本塊的大小2)複製文本到新的緩衝區3)按空間複製空間}。在複製空間之前不要計算空格。 – 2010-09-27 04:14:42

0

副本的陣列中的每個字符串,並以相反的順序打印(我 - )

int main() 
{ 
int j=0; 
string str; 
string copy[80]; 
int start=0; 
int end=0; 
cout<<"Enter the String :: "; 
getline(cin,str); 
cout<<"Entered String is : "<<str<<endl; 
for(int i=0;str[i]!='\0';i++) 
{ 
end=s.find(" ",start); 
if(end==-1) 
{ 
copy[j]=str.substr(start,(str.length()-start)); 
break; 
} 
else 
{ 
copy[j]=str.substr(start,(end-start)); 
start=end+1; 
j++; 
i=end; 
} 
} 

for(int s1=j;s1>=0;s1--) 
cout<<" "<<copy[s1]; 
}