使用循环替换字符串中的字符(需要帮助优化)

Using loops to replace characters in a string (need help optimizing)

本文关键字:帮助 优化 字符 循环 替换 字符串      更新时间:2023-10-16

对于我的一个CS作业,我被告知

"(1)从用户那里获得一个单词的输入。输出单词。如果单词包含某些字符,使用您选择的循环将它们替换为相应的符号或数字。

示例输出:

    Enter word: sixteen
    You entered: sixteen
    New word: $!*t33n

你应该支持这些字符:

a—@

e—3

i——!

g—9

s—$

x——*

如果您的单词不包含上述任何字符,只需重新打印原始单词。"

现在,我能够通过使用无数的while和for循环来解决这个问题。然而,我的印象是必须有一个更有效的方法来完成这项任务。

下面是我希望优化的相关代码:

while (userWord.find('a') != string::npos) {
     hasA = userWord.find('a');
  userWord.replace( userWord.find('a'), 1, "@");
   if (userWord.find('a') != string::npos) {
      hasA = userWord.find('a');
      userWord.replace( userWord.find('a'), 1, "@");
   }
   else if (userWord.find('e') != string::npos) {
      hasA = userWord.find('e');
      userWord.replace( userWord.find('e'), 1, "3");
   }
   else if (userWord.find('i') != string::npos) {
      hasA = userWord.find('i');
      userWord.replace( userWord.find('i'), 1, "!");
   }
   else if (userWord.find('g') != string::npos) {
      hasA = userWord.find('g');
      userWord.replace( userWord.find('g'), 1, "9");
   }
   else if (userWord.find('s') != string::npos) {
      hasA = userWord.find('s');
      userWord.replace( userWord.find('s'), 1, "$");
   }
  else if (userWord.find('x') != string::npos) {
      hasA = userWord.find('x');
      userWord.replace( userWord.find('x'), 1, "*");
   }
}
while (userWord.find('e') != string::npos) {
  hasA = userWord.find('e');
  userWord.replace( userWord.find('e'), 1, "3");
  if (userWord.find('a') != string::npos) {
      hasA = userWord.find('a');
      userWord.replace( userWord.find('a'), 1, "@");
  }
  else if (userWord.find('e') != string::npos) {
      hasA = userWord.find('e');
      userWord.replace( userWord.find('e'), 1, "3");
  }
  else if (userWord.find('i') != string::npos) {
      hasA = userWord.find('i');
      userWord.replace( userWord.find('i'), 1, "!");
  }
  else if (userWord.find('g') != string::npos) {
      hasA = userWord.find('g');
      userWord.replace( userWord.find('g'), 1, "9");
  }
  else if (userWord.find('s') != string::npos) {
      hasA = userWord.find('s');
      userWord.replace( userWord.find('s'), 1, "$");
  }
  else if (userWord.find('x') != string::npos) {
      hasA = userWord.find('x');
      userWord.replace( userWord.find('x'), 1, "*");
  }
}
while (userWord.find('i') != string::npos) {
  hasA = userWord.find('i');
  userWord.replace( userWord.find('i'), 1, "!");
if (userWord.find('a') != string::npos) {
      hasA = userWord.find('a');
      userWord.replace( userWord.find('a'), 1, "@");
  }
  else if (userWord.find('e') != string::npos) {
      hasA = userWord.find('e');
      userWord.replace( userWord.find('e'), 1, "3");
  }
  else if (userWord.find('i') != string::npos) {
      hasA = userWord.find('i');
      userWord.replace( userWord.find('i'), 1, "!");
  }
  else if (userWord.find('g') != string::npos) {
      hasA = userWord.find('g');
      userWord.replace( userWord.find('g'), 1, "9");
  }
  else if (userWord.find('s') != string::npos) {
      hasA = userWord.find('s');
      userWord.replace( userWord.find('s'), 1, "$");
  }
  else if (userWord.find('x') != string::npos) {
      hasA = userWord.find('x');
      userWord.replace( userWord.find('x'), 1, "*");
  }
}
while (userWord.find('g') != string::npos) {
  hasA = userWord.find('g');
  userWord.replace( userWord.find('g'), 1, "9");
  if (userWord.find('a') != string::npos) {
      hasA = userWord.find('a');
      userWord.replace( userWord.find('a'), 1, "@");
  }
  else if (userWord.find('e') != string::npos) {
      hasA = userWord.find('e');
      userWord.replace( userWord.find('e'), 1, "3");
  }
  else if (userWord.find('i') != string::npos) {
      hasA = userWord.find('i');
      userWord.replace( userWord.find('i'), 1, "!");
  }
  else if (userWord.find('g') != string::npos) {
      hasA = userWord.find('g');
      userWord.replace( userWord.find('g'), 1, "9");
  }
  else if (userWord.find('s') != string::npos) {
      hasA = userWord.find('s');
      userWord.replace( userWord.find('s'), 1, "$");
  }
  else if (userWord.find('x') != string::npos) {
      hasA = userWord.find('x');
      userWord.replace( userWord.find('x'), 1, "*");
  }
}
while (userWord.find('s') != string::npos) {
  hasA = userWord.find('s');
  userWord.replace( userWord.find('s'), 1, "$");
 if (userWord.find('a') != string::npos) {
      hasA = userWord.find('a');
      userWord.replace( userWord.find('a'), 1, "@");
  }
  else if (userWord.find('e') != string::npos) {
      hasA = userWord.find('e');
      userWord.replace( userWord.find('e'), 1, "3");
  }
  else if (userWord.find('i') != string::npos) {
      hasA = userWord.find('i');
      userWord.replace( userWord.find('i'), 1, "!");
  }
  else if (userWord.find('g') != string::npos) {
      hasA = userWord.find('g');
      userWord.replace( userWord.find('g'), 1, "9");
  }
  else if (userWord.find('s') != string::npos) {
      hasA = userWord.find('s');
      userWord.replace( userWord.find('s'), 1, "$");
  }
  else if (userWord.find('x') != string::npos) {
      hasA = userWord.find('x');
      userWord.replace( userWord.find('x'), 1, "*");
  }
}
while (userWord.find('x') != string::npos) {
  hasA = userWord.find('x');
  userWord.replace( userWord.find('x'), 1, "*");
  if (userWord.find('a') != string::npos) {
      hasA = userWord.find('a');
      userWord.replace( userWord.find('a'), 1, "@");
  }
  else if (userWord.find('e') != string::npos) {
      hasA = userWord.find('e');
      userWord.replace( userWord.find('e'), 1, "3");
  }
  else if (userWord.find('i') != string::npos) {
      hasA = userWord.find('i');
      userWord.replace( userWord.find('i'), 1, "!");
  }
  else if (userWord.find('g') != string::npos) {
      hasA = userWord.find('g');
      userWord.replace( userWord.find('g'), 1, "9");
  }
  else if (userWord.find('s') != string::npos) {
      hasA = userWord.find('s');
      userWord.replace( userWord.find('s'), 1, "$");
  }
  else if (userWord.find('x') != string::npos) {
      hasA = userWord.find('x');
      userWord.replace( userWord.find('x'), 1, "*");
  }
}
cout << "New word: " << userWord << endl;

必须有比在每个while循环后重新嵌套每个if语句更好的方法来确保任何可替换字母的每个实例都将被替换。

任何见解将不胜感激!

使用c++的标准模板库,这应该很容易。使用std::transformstd::map<..>关联容器

(假设c++ 11可用见下面的'真正的' c++ 11实现!)

#include <map>
#include <iostream>
#include <string>
#include <algorithm>
#include <iterator>
// A functor (object posing as function call)
struct charmapper {
    charmapper( const std::map<char, char>& cm):
       charmap( cm )
    {}
    // If the character 'in' is present in the std::map<>
    // return the mapped character, otherwise the original character
    char operator()(char in) const {
        std::map<char, char>::iterator entry = charmap.find(in);
        return (entry == charmap.end()) ? in : entry->second;
    }
    std::map<char, char>  charmap;
};
int main(void) {
   // Here define your character replacements
   std::map<char, char>  toreplace{ {'a', '@'}, {'i', '1'} }; // etc
   std::string  input{ "This is an input string" };
   std::string  output;
   // Now transform the input string, using the charmapper functor
   std::transform(input.begin(), input.end(), std::back_inserter(output),
                  charmapper(toreplace) );
   // Display to check what transform has done
   std::cout << output << std::endl;
   return 0;
}

看到,在这里运行程序:https://ideone.com/GROl6p

编辑:

再多考虑一下,使用更多c++ 11的特性,它可以做得更好。下面的基本思想是,我们用一个函数调用操作符修饰std::map;对于转换来说,只有映射才是必需的。这是通过继承std::map并定义operator()来实现的。

在这个派生类中定义c++ 11的转发构造函数,并使用可变的模板参数。这意味着可以使用std::map的初始化列表构造函数原位创建派生类型;不需要创建std::map和派生(装饰)类型的单独实例。

代码现在类型更安全,更重要的是,'mapper'现在是泛型的,可以轻松地用于任何替换映射操作。

#include <map>
#include <iostream>
#include <string>
#include <algorithm>
#include <iterator>
using std::string; using std::map;
template <typename ...Types>
struct mapper : public map<Types...> {
    typedef map<Types...> Self;
    using map<Types...>::map;
    // C++11 forwarding constructor!
    template <typename ...Args>
    mapper(Args... args) : map<Types...>(args...) {}
    // Decorate the std::map<> with function call operator
    typename Self::mapped_type operator()(const typename Self::key_type& k) const {
        typename Self::const_iterator  ptr = this->find(k);
        return (ptr==this->end()) ? typename Self::mapped_type(k) : ptr->second;
    }
};
int main(void) {
   string  input{ "This is an input string" };
   string  output;
   // Now transform the input string, using the mapperr
   std::transform(input.begin(), input.end(), std::back_inserter(output),
                  mapper<string::value_type, string::value_type>({{'a', '@'}, {'i','1'}}) );
   // Display to check what transform has done
   std::cout << output << std::endl;
   return 0;
}

在这里看到它的作用:https://ideone.com/vmON0E

不打算提供完整的代码示例,因为这听起来像是家庭作业。

最有效的方法是创建一个ASCII替换映射:
const substitution[] = " !"#$%&'()*+,-./0123456789:;<=>?@BCD3F9H!JKLMNOPQR$TUVW*YZ[]^_`@bcd3f9h!jklmnopqr$tuvw*yz{|}~";

然后循环遍历输入并将每个字符替换为替换映射中的相应字符:

for (int i = 0; i < myWord.size(); i++)
{
    myWord[i] = substitution[myWord[i] - 32];
}

你可以在一个循环中完成所有这些。

int main()
{
  string myWord;
  cout << "enter a word: ";
  cin >> myWord;
  for(unsigned int i = 0; i < myWord.size(); i++)
  {
    if(myWord[i]=='a')
      myWord[i] = '@';
    else if(myWord[i] == 'e')
      myWord[i] = '3';
    else if(myWord[i] == 'i')
      myWord[i] = '!';
    else if(myWord[i] == 'g')
      myWord[i] = '9';
    else if(myWord[i] == 's')
      myWord[i] = '$';
    else if(myWord[i] == 'x')
      myWord[i] = '*';
  }
  cout << myWord;
}

看到它在这里运行http://cpp.sh/86qh