C++ toupper Syntax



我刚刚被介绍到toupper,我对语法有点困惑;它似乎在重复自己。我一直使用它的目的是对于字符串的每个字符,如果可能的话,它会将字符转换为大写字符。

for (int i = 0; i < string.length(); i++)
{
    if (isalpha(string[i]))
    {
        if (islower(string[i]))
        {
            string[i] = toupper(string[i]);
        }
    }
}

为什么你必须列出两次string[i]?这不应该行吗? toupper(string[i]);(我试过了,所以我知道它没有。

toupper是一个按

值获取参数的函数。它可以被定义为接受对字符的引用并就地修改它,但这会使编写仅检查字符的大写变体的代码变得更加尴尬,如以下示例所示:

// compare chars case-insensitively without modifying anything
if (std::toupper(*s1++) == std::toupper(*s2++))
  ...

换句话说,toupper(c)不会改变c,原因与sin(x)不会改变x的原因相同。


若要避免在赋值的左侧和右侧重复表达式(如 string[i](,请引用字符并使用它来读取和写入字符串:
for (size_t i = 0; i < string.length(); i++) {
  char& c = string[i];  // reference to character inside string
  c = std::toupper(c);
}

使用基于范围的for,上述内容可以更简短地编写(并更有效地执行(为:

for (auto& c: string)
    c = std::toupper(c);

从文档中看,字符是按值传递的。
正因为如此,答案是否定的,不应该

toupper的原型是:

int toupper( int ch );

如您所见,字符按值传递、转换和返回。
如果不将返回值分配给变量,它肯定会丢失。
这就是为什么在您的示例中重新分配它以替换原始示例的原因。

正如许多其他答案已经说过的那样,传递给std::toupper的参数并且结果返回了按值返回,这是有意义的,因为否则,您将无法调用,例如std::toupper('a')。不能就地修改文本'a'。您也可能将输入存储在只读缓冲区中,并希望将大写输出存储在另一个缓冲区中。因此,按价值计算方法要灵活得多。

另一方面,多余的是你检查isalphaislower .如果该字符不是小写字母字符,toupper无论如何都会保留它,因此逻辑简化为此。

#include <cctype>
#include <iostream>
int
main()
{
  char text[] = "Please send me 400 $ worth of dark chocolate by Wednesday!";
  for (auto s = text; *s != ''; ++s)
    *s = std::toupper(*s);
  std::cout << text << 'n';
}

如果您发现这更漂亮,则可以通过使用算法进一步消除原始循环。

#include <algorithm>
#include <cctype>
#include <iostream>
#include <utility>
int
main()
{
  char text[] = "Please send me 400 $ worth of dark chocolate by Wednesday!";
  std::transform(std::cbegin(text), std::cend(text), std::begin(text),
                 [](auto c){ return std::toupper(c); });
  std::cout << text << 'n';
}

>toupper按值获取int,并返回该大写字符charint值。每次函数不将指针或引用作为参数时,参数都将按值传递,这意味着无法从函数外部查看更改,因为参数实际上是传递给函数的变量的副本,您捕获更改的方式是通过保存函数返回的内容。在本例中,字符大写。

请注意,isalpha(( 中有一个令人讨厌的陷阱,如下所示:该函数仅适用于 0-255 + EOF 范围内的输入。

那又怎样,你觉得。

好吧,如果你的 char 类型碰巧是有符号的,并且你传递的值大于 127,这被认为是负值,因此传递给 isalpha 的 int 也将是负值(因此超出了 0-255 + EOF 的范围(。

在Visual Studio中,这将使您的应用程序崩溃。我已经向Microsoft抱怨过这个问题,理由是对所有输入都不安全的字符分类函数基本上毫无意义,但得到的答复指出这完全符合标准,我应该写更好的代码。好吧,很公平,但是标准中的其他地方没有人关心char是有符号还是无符号。只有在 isxxx 函数中,它才能充当地雷,可以在没有人注意到的情况下轻松通过测试。

以下代码使Visual Studio 2015崩溃(据我所知,所有早期版本(:

int x = toupper ('é'); 

因此,代码中的 isalpha(( 不仅是多余的,而且实际上是有害的,因为它会导致任何包含值大于 127 的字符的字符串使应用程序崩溃。

请参阅 http://en.cppreference.com/w/cpp/string/byte/isalpha:"如果 ch 的值不能表示为无符号字符且不等于 EOF,则行为未定义。

相关内容

  • 没有找到相关文章

最新更新