在 C 和 C++ 中将 C 字符串转换为大写
Posted
技术标签:
【中文标题】在 C 和 C++ 中将 C 字符串转换为大写【英文标题】:C string to uppercase in C and C++ 【发布时间】:2016-01-10 05:17:24 【问题描述】:当我在 C++ 中组合一个大写函数时,我注意到在 C 中我没有收到预期的输出。
C++ 函数
#include <iostream>
#include <cctype>
#include <cstdio>
void strupp(char* beg)
while (*beg++ = std::toupper(*beg));
int main(int charc, char* argv[])
char a[] = "foobar";
strupp(a);
printf("%s\n", a);
return 0;
按预期输出:
FOOBAR
C 函数
#include <ctype.h>
#include <stdio.h>
#include <string.h>
void strupp(char* beg)
while (*beg++ = toupper(*beg));
int main(int charc, char* argv[])
char a[] = "foobar";
strupp(a);
printf("%s\n", a);
return 0;
输出是缺少第一个字符的预期结果
OOBAR
有谁知道为什么在 C 中编译时结果会被截断?
【问题讨论】:
如果你真的想在C++
中这样做:std::transform(a, a + strlen(a), a, std::toupper);
您能解释一下为什么您希望这会将字符串转换为大写吗?具体来说,您为什么希望 =
的右侧在左侧之前被评估?
感谢所有提供反馈和提供宝贵信息的人
@Schullz 我坚信从错误中吸取教训是避免再次犯同样错误的最有效方法。因此,由于这个问题完全源于实验,而不是在团队项目环境中,我认为编写这段代码 sn-p 开始是一个错误
@MillieSmith 在这种情况下,将哪个项目变为大写的顺序是否重要?无论如何,大多数(如果不是全部)改变字符串的经典 C++ 方法都使用std::transform
。
【参考方案1】:
问题是里面没有序列点
while (*beg++ = toupper(*beg));
所以我们有未定义的行为。在这种情况下,编译器正在做的是在 toupper(*beg)
之前评估 beg++
在 C 中,而在 C++ 中它以另一种方式进行。
【讨论】:
这是否意味着经典的 c 字符串复制单行while(*s++ = *t++) ;
具有未定义的行为?
@markh 否,因为这是两个不同的变量。这是while (*s++ = *s++)
的同义词
@SteveJessop 实际上,while(*s++ = *t++);
已经定义了行为,即使 s == t
也是如此。 strcpy
未定义重叠区域的原因是 strcpy
不一定用 while(*s++ = *t++);
实现。
@immibis:公平点,同意它的定义。然而,即使strcpy
是通过该循环实现的,它对于一个重叠的“方向”仍然具有未定义的行为。如果目标大于源并且它们重叠,则终止的 nul 在读取之前被覆盖,最终缓冲区溢出!在两个“方向”上禁止重叠的原因是可能的其他实现。【参考方案2】:
while (*beg++ = std::toupper(*beg));
导致未定义的行为。
未指定*beg++
是在std::toupper(*beg)
之前还是之后排序。
简单的解决方法是使用:
while (*beg = std::toupper(*beg))
++beg;
【讨论】:
【参考方案3】:线
while (*beg++ = toupper(*beg));
包含对被使用两次的实体的副作用。您无法知道 beg++ 是在 *beg 之前还是之后执行(在 toupper 内部)。您很幸运,两种实现都显示了两种行为,因为我很确定 C++ 也是如此。 (但是,c++11 有一些规则更改,我不确定 - 仍然是不好的风格。)
只需将 beg++ 移出条件即可:
while (*beg = toupper(*beg)) beg++;
【讨论】:
【参考方案4】:关于上面的答案,'f' 永远不会在函数内部传递,你应该尝试使用这个:
while ((*beg = (char) toupper(*beg))) beg++;
【讨论】:
转换为 char 很重要,因为 int 类型的值可能不适合接收器类型 char 那个演员没有任何成就,如果没有它就不会发生。以上是关于在 C 和 C++ 中将 C 字符串转换为大写的主要内容,如果未能解决你的问题,请参考以下文章