如何在C语言中将字符串转换为小写?

143

我该如何在C语言中将一个大小写混合的字符串转换为小写字符串?


2
你只处理ASCII码中的a-z字母吗? - Mark Byers
1
ASCII。我该如何考虑?下面的例子还有效吗?如果我的字符是“#”,并且调用 tolower() 函数会发生什么? - Tony Stark
1
可以这样做。我更多地是在想,如果你的字符串包含像é或Ü这样的字符。 - Mark Byers
4
为什么不直接使用 "strlwr" 呢?strlwr((char*)str); 它会遍历整个字符串并将其转换为小写字母。 - Larry
1
@Larry 这是非标准的。 - mid
7个回答

209

这个函数在标准库中,这是我认为最直接的实现方式。因此,只需遍历字符串并将每个字符转换为小写即可。

像这样非常简单:

#include <ctype.h>

for(int i = 0; str[i]; i++){
  str[i] = tolower(str[i]);
}

如果你喜欢一行代码,那么你可以使用 J.F. Sebastian 提供的这个:

for ( ; *p; ++p) *p = tolower(*p);

43
for ( ; *p; ++p) *p = tolower(*p); 这样写更符合惯用语。 - jfs
16
@J.F. 给你,这取决于他们想要代码看起来吓人还是好看 :)(一行代码非常易读,但看起来有些可怕) - Earlz
1
如果str是一个char *,那么这会给我一个segfault,但如果str是一个char数组,就不会。你有什么解释吗? - Electric Coffee
5
我认为这个一行代码会导致你失去对字符串的指针。 - Ace.C
2
我相信这个一行代码会有无数的影响。 - NOP da CALL
显示剩余5条评论

9

将文本转换为小写字母相当于在ASCII字符集中将二进制位0x60上升:

for(char *p = pstr; *p; ++p)
    *p = *p > 0x40 && *p < 0x5b ? *p | 0x60 : *p;

7
为了使其更易读,您可以这样修改:for(char *p = pstr;*p;++p) *p=*p>='A'&&*p<='Z'?*p|0x60:*p;。这段代码将大写字母转换为小写字母,而不改变其他字符。 - Grant Peters
8
这个版本比glibc的tolower()函数要慢。在我的机器上是55.2与44.15相比。 - jfs
我无法想象:tolower() 处理字符;只有当它是宏时。 - Oleg Razgulyaev
1
@oraz:tolower()的签名为int (*)(int)。这是用于性能测量的代码http://gist.github.com/370497 - jfs
1
最快的版本使用查找表而不是分支。 - Joe
显示剩余3条评论

7

通过循环指针来提高性能:

#include <ctype.h>

char* toLower(char* s) {
  for(char *p=s; *p; p++) *p=tolower(*p);
  return s;
}
char* toUpper(char* s) {
  for(char *p=s; *p; p++) *p=toupper(*p);
  return s;
}

如果你想使用单行代码的方式,那么s是你函数中的一个本地变量,你可以直接使用它而不需要声明p - NewbiZ
@NewbiZ,确实: // 将字符串转换为小写,原地操作: char* toLower(char* p) { for( ; *p; p++) *p=tolower(*p); return p; } - Felipe G. Nievinski
1
@NewbiZ,没有给出这个签名(它返回字符串的起始指针)。需要在某个地方进行复制! - undefined
@TobySpeight,噢,确实没错。 - undefined

1
如果我们要使用像 tolower() 这样的函数,就应该这样做:
char blah[] = "blah blah Blah BLAH blAH\0";
int i = 0;
while( blah[i] |=' ', blah[++i] ) {}

然而,如果你输入一些符号或数字,它会爆炸,并且总体上它是邪恶的。不过这是一个不错的面试问题。


7
这段话的意思是:这个程序会折叠、切断和破坏各种符号(在ASCII码中,任何符号、控制字符或数字如果其第五位为0,则会变成相同字符代码但第五位变成1)。因此,请务必不要使用它。 - Ken S
1
这篇文章在 meta 上进行了讨论。 - Patrick Hofman
你能详细说明一下吗?当我阅读关于 tolower() 的内容时,他们都提到它们只适用于具有小写字符定义的字符。来自 opengroup.org 的说明是:“如果 tolower() 的参数表示大写字母,并且存在相应的小写字母[CX] [Option Start](由程序区域设置类别 LC_CTYPE 中的字符类型信息定义)[Option End],则结果应该是相应的小写字母。在该域中的所有其他参数都将返回不变。”如果是这样,tolower() 在哪些方面会失败? - 9a3eedi

1

-1
我对C语言还很陌生,一直在努力将字符串从大写转换为小写。我犯了一个错误,将字符串'A' + 32 = 'a'。而且我无法解决这个问题。
我使用了char类型,最终成功将其转换为string类型。你可以参考一下:
#include <ctype.h>
#include <stdio.h>
#include <string.h>

string convert_lower(string str)
{
    int length = strlen(str);
    char c[length + 1];

    for (int i = 0; i < length; i++)
    {
        if (str[i] <= 'Z' || str[i] >= 'A')
        {
            c[i] = tolower((char)str[i]);
        }
    }
    c[length] = '\0';
    string text = c;
    return text;
}

-1

你只处理ASCII字符串,没有地域问题吗?那么是的,这将是一个不错的方法。


如果在非ASCII a-z字符上调用tolower()会发生什么?比如'!'或'#'。我在'#'上测试了一下,似乎工作得很好。对于所有不是字母a-z的ASCII字符,这通常都是正确的吗? - Tony Stark
1
@hatorade:如果 tolower() 函数的参数不在 'A'..'Z' 范围内,则不会改变它。 - jfs
2
!和#都是ASCII字符。Mark提到了其他编码,比如UTF8,其中你不能假设每个字符只有一个字节(就像这个解决方案一样)。 - hdgarrood
这应该是一个评论,而不是一个答案。 - Bryan Green

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接