【问题标题】:Can't convert to Lower/uppercase a char* pointer using a loop in C without toupper无法在没有 toupper 的情况下使用 C 中的循环将 char* 指针转换为小写/大写
【发布时间】:2020-09-19 04:05:06
【问题描述】:

我正在尝试创建一个函数toLowerCase(char *string),但我无法使其正常工作。

这是我的代码

void toLowerCase(char *string) {
    int i = 0;
    while (*(string+i) != '\0') {
        if (*(string+i) >= 'A' && *(string+i) <= 'Z') {
            *(string+i) = *(string+i) + 32;
        }
        i++;
    }
    printf("%s", string);
}

我正在尝试通过使用 *(string + i) 访问每个元素并使用 ASCII 转换为小写来遍历 char * 指针的字符串。

我是新来的,如果在我很抱歉之前回答了这个问题,但我问是因为我找不到解决我的问题的具体解决方案。我已经尝试过这个线程中的内容:Converting Char * to Uppercase in C 但这对我也不起作用。

编辑:这就是我调用函数的方式

int main() {
    toLowerCase("HELLO WORLD");
    return 0;
}

编辑 2:所以,我这样做了,正如 PSkocik 所示。它奏效了,但我不知道为什么它会这样。 toLowerCase() 函数是否可以与任何 char * 指针一起使用?即使我不将其声明为char 数组?

这也解决了来自莫斯科的弗拉德指出我使用字符串文字的问题

#define T 100
int main() {
    char string[T] = "HELLO WORLD";
    toLowerCase(&string);
    return 0;
}

编辑 3:非常感谢您的帮助!没想到这么快就得到帮助!我不知道字符串字面量是什么!

非常感谢您的宝贵时间

【问题讨论】:

  • 您似乎正在将字符串文字传递给函数。显示您如何调用该函数。
  • 对我来说很好用:gcc.godbolt.org/z/X4YA5B*(string+i) 而不是 string[i] 有点不寻常,我至少将魔术常数 32 替换为 ('a'-'A'),但它确实可以正常工作。
  • 您遇到的错误是什么?是分段错误吗?
  • 我刚刚添加了调用函数的位置。我没有收到错误,它在 ''' *(string+i)= *(string+i)+32; 之后卡住了''' 行并返回 -1073741819
  • 返回该值的是什么?当你说它卡住时,你的意思是循环永远不会结束吗?

标签: c char c-strings string-literals tolower


【解决方案1】:

由于历史原因,C 字符串文字的类型为 char[],但实际上它们是 char const[]——您不能修改它们。

幸运的是,C 允许您使用字符串字面量初始化可写的char 数组,从而非常容易地创建可写副本:

#include <stdio.h>
void toLowerCase(char* string)
{
    int i=0;
    while(*(string+i)!= '\0'){
        if (*(string+i) >= 'A' && *(string+i)<='Z'){
            *(string+i)= *(string+i)+32;
        }
        i++;
    }
}
int main()
{
     char string[]="HELLO WORLD";
     toLowerCase(&string[0]);
     puts(string);
    //prints: hello world
}

https://gcc.godbolt.org/z/X4YA5B

*(string+i) 而不是string[i] 有点不寻常,我至少会用('a'-'A') 替换魔术常数32,但被调用者的代码在其他方面没问题。)

【讨论】:

  • 这应该是一条评论。
  • 为什么写toLowerCase(&amp;string[0]);而不是toLowerCase(string);
  • @chqrlie 因为看起来更严重
  • @P__J__: 没有toLowerCase(&amp;0[string]);toLowerCase(0[&amp;string]); 严重:)
  • @chqrlie 同意
【解决方案2】:

您不能更改字符串文字。任何更改字符串文字的尝试都会导致未定义的行为。

来自 C 标准(6.4.5 字符串文字)

7 不确定这些数组是否是不同的,前提是它们的 元素具有适当的值。 如果程序试图 修改这样的数组,行为未定义。

所以不是这个调用

toLowerCase("HELLO WORLD");

至少使用

char s[] = "HELLO WORLD";

toLowerCase( s );

注意,当函数返回指向修改后的字符串的指针并且不输出字符串时会好很多。由函数的调用者决定是否输出修改后的字符串。

所以像这样定义函数

char * toLowerCase( char *string )
{
    // ...
    return string;
}

【讨论】:

  • 你能定义一个这样的字符数组吗? s[] 没有尺寸?
  • @DavidChoi 是的,那是 语法糖,因为您正在使用字符串文字初始化数组。
  • @DavidChoi 大小由初始化器的数量决定,即由字符串文字中的字符数(包括其终止零字符)决定。
【解决方案3】:

您将字符串文字传递给函数toLowerCase,然后尝试使用*(string+i)= *(string+i)+32; 更改它。

如果你想改变case的字符,你应该在一个变量中包含Hello World,然后将它传递给函数。

【讨论】:

    【解决方案4】:

    toLowerCase("HELLO WORLD"); => toLowerCase((char[]){"HELLO WORLD"}); 因为更改字符串文字是一个 UB。

    您的函数应该返回字符串以便于用作参数。

    char *toLowerCase(char* string)
    {
        int i=0;
        while (string[i])
        {
            if (string[i] >= 'A' && string[i] <= 'Z')
            {
                string[i] += 'a' - 'A';
            }
            i++;
        }
        return string;
    }
    
    
    
    int main() 
    {
        puts(toLowerCase((char[]){"HELLO WORLD"}));
        return 0; 
    }
    

    【讨论】:

    • 如果string 中的任何字符不是大写字母,恐怕你会陷入无限循环。
    • @chqrlie 哦,是的-该睡觉了
    • @P__J__ 您应该将调用更改为puts(toLowerCase(0[&amp;(char[]){"HELLO WORLD"}])); 以使其看起来更严肃。 (JK。+1)
    • 许多while 循环隐藏了一个更好的for 循环。
    猜你喜欢
    • 2018-08-01
    • 2016-04-04
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-03-21
    • 1970-01-01
    • 2015-05-08
    • 1970-01-01
    相关资源
    最近更新 更多