大写字母
Capitalizing letters
我有个小问题。我想利用字符串中的双字母。我成功编译了一个程序,但是没有成功
#include <iostream>
#include <cctype>
#include <string>
std::string::iterator function(
std::string::const_iterator a,
std::string::const_iterator b,
std::string::const_iterator e)
{
for (; a < b; a++)
{
if (*a == *(a + 1))
{
toupper(*a);
toupper(*(a + 1));
}
}
}
int main()
{
std::string in = "peppermint 1001 bubbles balloon gum", out(100, '*');
auto e = function(in.cbegin(), in.cend(), out.begin());
int n = e - out.begin();
std::string s = out.substr(0, n);
bool b = (s == "pePPermint 1001 buBBles baLLOOn gum");
std::cout << std::boolalpha << b << std::endl;
}
我做错了什么?
您的函数表现出未定义的行为,因为它从来没有 returns 值。请使用 -Wall -Wextra
编译以启用所有编译器警告以避免此类不必要的错误。
你有几个问题。
首先,您的函数承诺 return std::string::iterator
std::string::iterator function(....)
{
//... return statement is missing here!
}
而且你没有遵守诺言。这将导致undefined behaviour。例如,在你的情况下,它只是编译而不给出输出。
为了获得定义的行为,您应该 return 从函数
std::string::iterator function(...)
{
// ... code
return {}; // return appropriately iterator of std::string
}
其次,你要修改字符串的字符,这需要一个可修改的迭代器而不是std::string::const_iterator
。
然后在循环中,您需要通过重新分配给大写的 char
ector 来改变它。例如:
*a = toupper(*a);
第三,在函数 for-loop 中执行此操作时要小心
for(; a < b; a++)
{
if(*a == *(a + 1)) // --->here
// ... code
}
当a== str.end()-1
的情况下会发生什么,你仍然会做增量(即*(a + 1)
),对吧?。再次递增结束迭代器 leads you Undefined behaviour.
在这种情况下,您可以使用 <iterator>
header 中的 std::next
来安全地检查它。
下面是解决上述问题的演示代码:
#include <iostream>
#include <string>
#include <iterator> // std::next
std::string::iterator function(
std::string::iterator a,
std::string::iterator b,
std::string::iterator e)
{
auto beg = a;
for (; a < b; a++)
{
if (std::next(a) != b && *a == *std::next(a)) {
*a = toupper(*a);
*std::next(a) = toupper(*std::next(a));
}
}
std::cout << std::string{ beg, b };
return {}; // return appropriately iterator of std::string
}
现在打印:https://godbolt.org/z/ZsLHxw
pePPermint 1001 buBBles baLLOOn gum
我假设您希望以某种方式将输出输出到第三个函数参数 std::string::iterator e
。我会让那部分让你弄清楚。同时,看看标准算法函数std::transform
,做这种转换可能很方便。
答案已经给出。我还想根据现有的 C++ 功能显示一个答案。对于给定的任务,C++ 标准算法库中存在一个函数。它被称为std::adjacent_find
。请参阅 here。
有了它,您可以将代码简单地重写为:
#include <iostream>
#include <string>
#include <algorithm>
#include <cctype>
int main() {
std::string test{ "peppermint 1001 bubbles balloon gum" };
// Find all duplicates
for (auto il = std::adjacent_find(test.begin(), test.end()); il != test.end(); il = std::adjacent_find(il+1, test.end())) {
// If duplicate found, then convert both to uppercase
*il = std::toupper(*il);
*(il + 1) = std::toupper(*(il+1));
}
std::cout << test << '\n';
return 0;
}
我们在一个简单的 for 循环中调用此函数,直到找不到更多重复项。
也许它可以给你一个更简单的实现的想法。
我有个小问题。我想利用字符串中的双字母。我成功编译了一个程序,但是没有成功
#include <iostream>
#include <cctype>
#include <string>
std::string::iterator function(
std::string::const_iterator a,
std::string::const_iterator b,
std::string::const_iterator e)
{
for (; a < b; a++)
{
if (*a == *(a + 1))
{
toupper(*a);
toupper(*(a + 1));
}
}
}
int main()
{
std::string in = "peppermint 1001 bubbles balloon gum", out(100, '*');
auto e = function(in.cbegin(), in.cend(), out.begin());
int n = e - out.begin();
std::string s = out.substr(0, n);
bool b = (s == "pePPermint 1001 buBBles baLLOOn gum");
std::cout << std::boolalpha << b << std::endl;
}
我做错了什么?
您的函数表现出未定义的行为,因为它从来没有 returns 值。请使用 -Wall -Wextra
编译以启用所有编译器警告以避免此类不必要的错误。
你有几个问题。
首先,您的函数承诺 return std::string::iterator
std::string::iterator function(....)
{
//... return statement is missing here!
}
而且你没有遵守诺言。这将导致undefined behaviour。例如,在你的情况下,它只是编译而不给出输出。
为了获得定义的行为,您应该 return 从函数
std::string::iterator function(...)
{
// ... code
return {}; // return appropriately iterator of std::string
}
其次,你要修改字符串的字符,这需要一个可修改的迭代器而不是std::string::const_iterator
。
然后在循环中,您需要通过重新分配给大写的 char
ector 来改变它。例如:
*a = toupper(*a);
第三,在函数 for-loop 中执行此操作时要小心
for(; a < b; a++)
{
if(*a == *(a + 1)) // --->here
// ... code
}
当a== str.end()-1
的情况下会发生什么,你仍然会做增量(即*(a + 1)
),对吧?。再次递增结束迭代器 leads you Undefined behaviour.
在这种情况下,您可以使用 <iterator>
header 中的 std::next
来安全地检查它。
下面是解决上述问题的演示代码:
#include <iostream>
#include <string>
#include <iterator> // std::next
std::string::iterator function(
std::string::iterator a,
std::string::iterator b,
std::string::iterator e)
{
auto beg = a;
for (; a < b; a++)
{
if (std::next(a) != b && *a == *std::next(a)) {
*a = toupper(*a);
*std::next(a) = toupper(*std::next(a));
}
}
std::cout << std::string{ beg, b };
return {}; // return appropriately iterator of std::string
}
现在打印:https://godbolt.org/z/ZsLHxw
pePPermint 1001 buBBles baLLOOn gum
我假设您希望以某种方式将输出输出到第三个函数参数 std::string::iterator e
。我会让那部分让你弄清楚。同时,看看标准算法函数std::transform
,做这种转换可能很方便。
答案已经给出。我还想根据现有的 C++ 功能显示一个答案。对于给定的任务,C++ 标准算法库中存在一个函数。它被称为std::adjacent_find
。请参阅 here。
有了它,您可以将代码简单地重写为:
#include <iostream>
#include <string>
#include <algorithm>
#include <cctype>
int main() {
std::string test{ "peppermint 1001 bubbles balloon gum" };
// Find all duplicates
for (auto il = std::adjacent_find(test.begin(), test.end()); il != test.end(); il = std::adjacent_find(il+1, test.end())) {
// If duplicate found, then convert both to uppercase
*il = std::toupper(*il);
*(il + 1) = std::toupper(*(il+1));
}
std::cout << test << '\n';
return 0;
}
我们在一个简单的 for 循环中调用此函数,直到找不到更多重复项。
也许它可以给你一个更简单的实现的想法。