【问题标题】:reversing the letters of the words in a string反转字符串中单词的字母
【发布时间】:2013-06-17 12:29:10
【问题描述】:

我想反转字符串中单词的字母,并且必须将其存储在同一个数组中。示例:i/p: hi how are you o/p: ih woh era uoy。我写了这个程序,但它只是打印相同的字符串而不反转,并且程序没有终止它继续打印一些东西。我找不到错误。请帮助我并告诉我正确的代码。

#include<iostream.h>
#include<conio.h>
#include<stdio.h>

void stre(char (&a1)[20], int j1, int i1)
{
    char b[20];
    for(int k=i1-j1;k<i1;k++)
        b[k]=a1[i1-k-1];
    for(k=i1-j1;k<i1;k++);
        a1[k]=b[k];
}


void main()
{
    clrscr();
    int j;
    char a[20];
    gets(a);
    for(int i=0;a[i]!='\0';i++)
    {
        j++;
        if(a[i]==' ')
        { 
            stre(a,j,i);
            j=0;
        }
    }
    stre(a,j,i);
    for(j=0;j<i;j++)
    cout<<a[j];
    getch();
}

朋友们,在您回答之后,我删除了 for 循环中的分号并初始化了 j=0,但我现在仍然无法为 i/p:hi 获得所需的输出,你好吗 o/p:ihh hi hhi嘿嘿。仍然需要你的帮助。

【问题讨论】:

  • 您正在制作 C 和 C++ 的糟糕组合...尝试在您的情况下坚持使用 C++ 流和格式化输入。
  • 不确定是否重复,但这里有一个类似的问题:stackoverflow.com/questions/12879348/…
  • A gets 在 20 个 char 的数组上?任何gets 的使用都是一个错误,但只有 20 个char,它几乎肯定会很快显现出来。
  • 它的价值:一个更简单(更好)的解决方案是将字符串分解为单词,并在每个单词上调用std::reverse
  • 更不用说在 must 系统上没有像 &lt;conio.h&gt; 这样的标头,并且它存在的地方已被弃用,j 永远不会初始化,main 不允许返回void.

标签: c++ arrays pass-by-reference


【解决方案1】:
for(k=i1-j1;k<i1;k++);
  a1[k]=b[k];

for 循环后的分号可防止最后一个动作发生多次。

【讨论】:

    【解决方案2】:

    试试

      #include <iostream>
        using namespace std;
    
    
           int main() {
    
    int j =0;
    char a[20] = "hi how are you";
    char b[20] = "";
        int l=0;
        for(int i=0;a[i]!='\0';i++){
    
            if(a[i]==' ' ||a[i+1]=='\0'){
              cout<<j<<' '<<i;
               if(a[i+1]=='\0'){
                   b[l++] = ' ';
    
    
               }
    
    
              for(int k=i;k>=j;k--){
                  b[l]=a[k];
                  l++;
              }
              for(int k=j;k<=i;k++){
                cout<<b[k];
                a[k] = b[k];
              }  
    
    
            cout<<endl;
            j = i+1;
    
            }
        }
       cout << a;
        return 0;
    
      }
    

    【讨论】:

    • 我猜 OP 是首先在数组 b 中制作一个临时副本,然后将一个字符一个字符地复制到原始数组中。因此,完全运行循环(直到长度的一半)是正确的。
    【解决方案3】:

    这个for循环以分号结束:

    for(k=i1-j1;k<i1;k++);
                        ^^^
    

    【讨论】:

      【解决方案4】:

      这是一个无论如何都不完美的版本,但至少,它试图更像 C++ 而不是 C:

      http://ideone.com/f5vciW

      首先:分词成单词和空格序列

      //the spaces should be preserved
      std::string test("hi   how are you"),reference("ih   woh era uoy");
       std::vector<std::string> tokens;
      tokenize(test,tokens);
      

      然后反转标记

      for (auto& token : tokens)
          std::reverse(token.begin(),token.end());
      

      将标记组装到字符串缓冲区中

      std::stringstream buf;
      for (auto token : tokens)
          buf<<token;
      

      检查结果

      std::string res=buf.str();
      assert(res==reference);
      

      标记器看起来像这样:

      template <typename TContainer,typename TString>
      void tokenize(TString input,TContainer& res)
      {
      
          if (input.length()<2) {
              res.push_back(input);
              return;
          }
      
          typename TString::const_iterator pos=input.begin();
          bool space_state=std::isspace(input[0],std::locale());
          for (typename TString::const_iterator it=input.begin(); it!=input.end();
                  ++it) {
              bool is_space=std::isspace(*it,std::locale());
              if (is_space!=space_state) {
                  res.push_back(TString(pos,it));
                  pos=it;
                  space_state=is_space;
              }
          }
      
          //the rest
          if (pos!=input.end()) {
              res.push_back(
               TString(
                pos,
                static_cast<typename TString::const_iterator>(input.end())
               ));
          }
      
      }
      

      【讨论】:

      • 这肯定会颠倒单词的顺序。 OP 希望保持单词的顺序相同,但颠倒每个单词中的字母。请参阅代码上方的示例。
      • 这里有一个更新的答案。标记器绝对可以进一步重构,以及其余代码......它至少适用于您的示例
      • 查看更短、更高效的答案:stackoverflow.com/a/17147560/847349
      【解决方案5】:

      您传递了j 而不分配值。所以会是垃圾。

      【讨论】:

        【解决方案6】:

        我可以在您的代码中看到两件事可能不会产生预期的输出:

        1)

        int j;
        

        应该替换为

        int j=0;
        

        还有

        for(k=i1-j1;k<i1;k++);
            a1[k]=b[k];
        

        for循环后面的分号需要去掉。

        仅供参考,不建议混合使用 C 和 C++ 代码(这会损害可读性)。请坚持其中任何一个。

        【讨论】:

          【解决方案7】:

          this site. 上显示了一个类似的示例,他们还使用了与您选择的几乎相同的方法(通过计算空格数来反转每个单词),并借助堆栈数据结构。
          确保您的环境中安装了 STL 库以运行此代码。
          最好在 linux 平台上运行此代码。

          【讨论】:

            【解决方案8】:

            这是另一个更短的版本,在不使用额外缓冲区的情况下进行内联反转:

            http://ideone.com/hs9NZ7

            分词器的标准是isspace 条件的变化:

            auto next_token=
             [&](char c) {
                   return std::isspace(c,loc)!=std::isspace(*pos,loc);
             };
            

            使用它我们可以遍历输入字符串并访问令牌:

            for (auto it=std::find_if(pos,test.end(),next_token);
                      it!=test.end();
                      it=std::find_if(pos,test.end(),next_token))
            

            反转它们并更新当前位置

            std::reverse(pos,it);
            pos=it;
            

            不要忘记剩余的令牌。

            【讨论】:

              猜你喜欢
              • 1970-01-01
              • 2015-12-13
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 2010-11-03
              • 2011-11-07
              • 1970-01-01
              相关资源
              最近更新 更多