我有这个功能:
void ToUpper(char * S)
{
while (*S!=0)
{
*S=(*S >= 'a' && *S <= 'z')?(*S-'a'+'A'):*S;
S++;
}
}
*S != 0 是什么意思,它应该是 null 吗?
那是检查字符串的结尾,它是一个值为零的字符。它不以任何方式连接到 NULL 指针。
我会写它*S != '\0'
,因为我觉得这更惯用,但这实际上只是个人风格偏好。您正在检查空字符 (ASCII NUL)。
您还可以考虑S != 0
在任何代码之前检查,因为指针本身可能为空,并且您不想取消引用空指针。
NULL
在C
和C++
在C
#define NULL 0
在C++
#define NULL (void*) 0
NULL 是一个指针,而 *S 是存储在指针处的值。多亏了丹尼斯·里奇,数字 0 两者都可以接受。
我更喜欢算法而不是循环:
#include <algorithm>
#include <cstring>
#include <cctype>
void ToUpper(char* p)
{
std::transform(p, p + strlen(p), p, toupper);
}
此解决方案也适用于 a 到 z 不连续的字符编码。
只是为了好玩,这里有一个实验,它只用算法进行一次迭代:
#include <algorithm>
#include <cassert>
#include <cstring>
#include <cctype>
#include <iostream>
#include <iterator>
struct cstring_iterator : std::iterator<std::random_access_iterator_tag, char>
{
char* p;
cstring_iterator(char* p = 0) : p(p) {}
char& operator*()
{
return *p;
}
cstring_iterator& operator++()
{
++p;
return *this;
}
bool operator!=(cstring_iterator that) const
{
assert(p);
assert(!that.p);
return *p != '\0';
}
};
void ToUpper(char* p)
{
std::transform(cstring_iterator(p), cstring_iterator(),
cstring_iterator(p), toupper);
}
int main()
{
char test[] = "aloha";
ToUpper(test);
std::cout << test << std::endl;
}