简体   繁体   English

C ++ toupper语法

[英]C++ toupper Syntax

I've just been introduced to toupper, and I'm a little confused by the syntax; 我刚被介绍过toupper,但是我对语法有些困惑; it seems like it's repeating itself. 好像是在重复自己。 What I've been using it for is for every character of a string, it converts the character into an uppercase character if possible. 我一直在使用它的目的是针对字符串的每个字符,如果可能的话,它将字符转换为大写字符。

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

Why do you have to list string[i] twice? 为什么您必须两次列出string[i] Shouldn't this work? 这不行吗? toupper(string[i]); (I tried it, so I know it doesn't.) (我尝试过,所以我知道没有。)

toupper is a function that takes its argument by value. toupper是一个按值接受参数的函数。 It could have been defined to take a reference to character and modify it in-place, but that would have made it more awkward to write code that just examines the upper-case variant of a character, as in this example: 可以将其定义为引用字符并就地对其进行修改,但这会使编写仅检查字符的大写变体的代码变得更加尴尬,如本例所示:

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

In other words, toupper(c) doesn't change c for the same reasons that sin(x) doesn't change x . 换句话说, toupper(c)不会更改c ,原因与sin(x)不会更改x


To avoid repeating expressions like string[i] on the left and right side of the assignment, take a reference to a character and use it to read and write to the string: 为避免在赋值的左侧和右侧重复诸如string[i]类的表达式,请引用一个字符,并使用该字符读取和写入字符串:

for (size_t i = 0; i < string.length(); i++) {
  char& c = string[i];  // reference to character inside string
  c = std::toupper(c);
}

Using range-based for , the above can be written more briefly (and executed more efficiently) as: 使用基于范围的for ,以上内容可以更简短地编写(并更有效地执行)为:

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

As from the documentation , the character is passed by value. 文档开始 ,字符按值传递。
Because of that, the answer is no, it shouldn't . 因此,答案是否定的,不是

The prototype of toupper is: toupper的原型是:

int toupper( int ch );

As you can see, the character is passed by value, transformed and returned by value. 如您所见,字符按值传递,按值转换和返回。
If you don't assign the returned value to a variable, it will be definitely lost. 如果不将返回值分配给变量,则肯定会丢失该值。
That's why in your example it is reassigned so that to replace the original one. 这就是为什么在您的示例中将其重新分配以替换原来的示例。

As many of the other answers already say, the argument to std::toupper is passed and the result returned by-value which makes sense because otherwise, you wouldn't be able to call, say std::toupper('a') . 正如许多其他答案已经说过的那样,传递了std::toupper的参数并将结果按值返回这很有意义,因为否则您将无法调用,说std::toupper('a') You cannot modify the literal 'a' in-place. 您不能就地修改文字'a' It is also likely that you have your input in a read-only buffer and want to store the uppercase-output in another buffer. 您的输入也可能位于只读缓冲区中,并且希望将大写输出存储在另一个缓冲区中。 So the by-value approach is much more flexible. 因此,按价值方法更加灵活。

What is redundant, on the other hand, is your checking for isalpha and islower . 什么多余的,在另一方面,是您检查isalphaislower If the character is not a lower-case alphabetic character, toupper will leave it alone anyway so the logic reduces to this. 如果该字符不是小写字母字符,则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';
}

You could further eliminate the raw loop by using an algorithm , if you find this prettier. 如果发现漂亮的话,可以使用算法进一步消除原始循环。

#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 takes an int by value and returns the int value of the char of that uppercase character. toupper按值获取int值,并返回该大写字符的charint值。 Every time a function doesn't take a pointer or reference as a parameter the parameter will be passed by value which means that there is no possible way to see the changes from outside the function because the parameter will actually be a copy of the variable passed to the function, the way you catch the changes is by saving what the function returns. 每次函数不将指针或引用作为参数时,参数将通过值传递,这意味着无法从函数外部查看更改,因为参数实际上是传递的变量的副本对于函数,捕获更改的方法是保存函数返回的内容。 In this case, the character upper-cased. 在这种情况下,字符将大写。

Note that there is a nasty gotcha in isalpha(), which is the following: the function only works correctly for inputs in the range 0-255 + EOF. 请注意,isalpha()中有一个讨厌的陷阱,如下所示:该函数适用于0-255 + EOF范围内的输入。

So what, you think. 那你怎么想。

Well, if your char type happens to be signed, and you pass a value greater than 127, this is considered a negative value, and thus the int passed to isalpha will also be negative (and thus outside the range of 0-255 + EOF). 好吧,如果您的char类型恰好是带符号的,并且您传递的值大于127,则该值被视为负值,因此传递给isalpha的int也将为负(因此在0-255 + EOF范围之外) )。

In Visual Studio, this will crash your application. 在Visual Studio中,这会使您的应用程序崩溃。 I have complained about this to Microsoft, on the grounds that a character classification function that is not safe for all inputs is basically pointless, but received an answer stating that this was entirely standards conforming and I should just write better code. 我向Microsoft抱怨过这一点,理由是对于所有输入都不安全的字符分类功能毫无意义,但收到了一个答案,指出这完全符合标准,我应该编写更好的代码。 Ok, fair enough, but nowhere else in the standard does anyone care about whether char is signed or unsigned. 好了,够公平,但无处可在标准没有关于字符是否带符号的人照顾。 Only in the isxxx functions does it serve as a landmine that could easily make it through testing without anyone noticing. 只有在isxxx函数中,它才能充当地雷,无需任何人注意即可通过测试轻松实现。

The following code crashes Visual Studio 2015 (and, as far as I know, all earlier versions): 以下代码使Visual Studio 2015(以及据我所知的所有早期版本)崩溃:

int x = toupper ('é'); 

So not only is the isalpha() in your code redundant, it is in fact actively harmful, as it will cause any strings that contain characters with values greater than 127 to crash your application. 因此,不仅代码中的isalpha()是多余的,而且实际上还很有害,因为它将导致任何包含值大于127的字符的字符串使应用程序崩溃。

See http://en.cppreference.com/w/cpp/string/byte/isalpha : "The behavior is undefined if the value of ch is not representable as unsigned char and is not equal to EOF." 请参阅http://en.cppreference.com/w/cpp/string/byte/isalpha :“如果ch的值不能表示为无符号字符并且不等于EOF,则该行为是不确定的。”

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM