C ++ toupper语法

时间:2016-02-13 21:31:40

标签: c++ string syntax toupper

我刚刚被介绍给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]);(我试过了,所以我知道它没有。)

5 个答案:

答案 0 :(得分:4)

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);

答案 1 :(得分:2)

documentation开始,字符按值传递 因此,答案是不,它不应该

toupper的原型是:

int toupper( int ch );

如您所见,字符按值传递,转换并按值返回 如果你没有将返回的值赋给变量,它肯定会丢失 这就是为什么在你的例子中它被重新分配,以便替换原来的。

答案 2 :(得分:1)

正如许多其他答案已经说过的那样,std::toupper的参数被传递,结果返回 by-value ,这是有道理的,否则,你将无法做到打电话,说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 != '\0'; ++s)
    *s = std::toupper(*s);
  std::cout << text << '\n';
}

如果您觉得这个更漂亮,可以使用algorithm进一步消除原始循环。

#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';
}

答案 3 :(得分:0)

toupperint取值,并返回该大写字符的int的{​​{1}}值。每次函数不将指针或引用作为参数时,参数将通过值传递,这意味着没有可能的方法来查看函数外部的更改,因为参数实际上是传递的变量的副本对函数来说,捕获更改的方法是保存函数返回的内容。在这种情况下,字符大写。

答案 4 :(得分:0)

请注意,isalpha()中有一个令人讨厌的问题,如下所示:函数 only 对0-255 + EOF范围内的输入正常工作。

那么,你认为。

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

在Visual Studio中,这会使您的应用程序崩溃。我向微软抱怨过这个问题,理由是对所有输入都不安全的字符分类功能基本没有意义,但是得到的答案表明这完全符合标准,我应该编写更好的代码。好吧,公平,但标准中其他地方并不关心char是签名还是未签名。只有在isxxx功能中,它才能成为一种可以轻松通过测试而无需任何人注意的地雷。

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

int x = toupper ('é'); 

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

参见http://en.cppreference.com/w/cpp/string/byte/isalpha:“如果ch的值不能表示为unsigned char且不等于EOF,则行为未定义。”