2010-09-23 104 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]; 
}