如何在C语言中将字符串(char *)转换为大写或小写

3

我有一个结构体:

typedef struct entry {
char *surname;
int house_no;
char *postcode;
} BEntry;

并且需要一个将字符串转换为大写的函数:

void toUpper(char *str){
    while (*str != '\0')
    {
        *str = toupper(*str);
        str++;
    }
}

在我的主函数中,我为结构体成员分配值,并希望将姓氏转换为大写:

mentry->surname = "bob";
mentry->house_no = 17;
mentry->postcode = "GK116BY";
toUpper(me->surname);

如何正确将字符串转换为大写字母并通过传递指向字符的指针到函数中?我的程序返回了一个段错误。非常感谢任何帮助,谢谢。


你的代码有什么问题? - Scott Hunter
7
“bob”是一个字符串文字,存在于只读位置。您无法修改它。请先复制再进行修改。 - Mahesh
问题在于将类型为 char*surname 赋值为常量字符串 "bob"。你至少应该得到一个警告,表明你忽略了赋值中的常量性。始终使用完整的警告。解决这个问题的一种方法是在赋值的一部分中运行 char * strdup(const char s)。然后你会得到一个可以修改的 char *。别忘了在完成后释放内存。 - Dov Grobgeld
3个回答

3
你的 toUpper() 实现应该可以正常工作。但是,你需要注意来自编译器的警告(如果没有警告,请提高警告级别--当你将一个字符串字面值赋给 char * 时,你应该会看到一些东西)。字符串字面值是 const 的,即它们不能被修改。当你尝试写入它们时,这将导致你所看到的分段错误。

你需要像这样做:

mentry->surname = malloc(4);
strcpy(mentry->surname, "bob");

或者更方便,但不是C标准的方法:
mentry->surname = strdup("bob");

当然,无论如何都要确保之后调用free()


在 C 语言中,字符串字面量并不是 const 类型。我认为标准定义这种方式是错误的,但不幸的是它确实是这样的。因此,OP 不会收到警告。在 gcc 中,您可以使用 -Wwrite-strings 强制发出警告,此时程序违反了标准,但我认为这样做更好。 - Patrick Schlüter
@tristopia:我本以为它们是可以修改的,但我看了一下,你完全正确。它确实说修改它们是未定义行为,这就引出了一个问题,为什么它们不是...但是,是的,从这个角度来看没有明显的警告。 - FatalError

1
在C语言中,将char *转换为小写或大写的最简单方法是使用strdup
#include <string.h>

char    *to_uppercase(char *s)
{
    int i = 0;
    char    *str = strdup(s);

    while (str[i])
    {
        if (str[i] >= 97 && str[i] <= 122)
            str[i] -= 32;
        i++;
    }
    return (str);
}

1

"Hello, World!"这样的字符串文字是不可写的。要么复制该字符串文字:

hw = strdup("Hello, World!");

或者声明一个char[]变量并将其初始化为字符串文字。作为特殊情况,以这种方式使用的字符串字面值是可写的:
char hw[] = "Hello, World!";

1
字面量不可写,而且在第二种情况下,您展示的不是字面量将可写,而是hw的内容将可写。 - alk
@alk 这是因为它不是一个字面量;我知道。我以这种略微不正确的方式编写答案,因为这比正确版本更简单易懂。 - fuz
1
在这两种情况下,“Hello, World!”是字面值。在这两种情况下,它都是不可写的。 - alk
@alk 从技术上讲,是的,但这是一种特殊情况,其中字符串字面值的内容隐式地初始化了数组(参见ISO 9899:2011§6.7.9.14)。你可以将其视为从程序员的角度实际可写的字符串字面值。我知道这不完全正确,但更容易理解。 - fuz

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