c语言 - 将字符串的所有小写字母更改为大写的函数



>我正在尝试编写一个函数,将字符串的所有小写字母更改为大写。这是我的代码:

/**
* string_toupper - This function will replace all lowercase letters in
* the string pointed by str to uppercase
* @str: The string that will be checked for lowercase letters
*
* Return: The resulting string str, where all the letters are uppercase
*/
char *string_toupper(char *str)
{
int i;
for (i = 0; *str != ''; i++)
{
if (str[i] >= 'a' && str[i] <= 'z')
str[i] -= 32;
}
return (str);
}

我尝试了它:

#include <stdio.h>
int main(void)
{
char str[] = "Hello World!n";
char *ptr;
ptr = string_toupper(str);
printf("%sn", ptr);
printf("%sn", str);
return (0);
}

但是我得到以下输出:

Segmentation fault(core dumped)

我的方法 -->我将检查字符串是否有小写字母。然后,如果它与小写字符匹配,我将从字符中减去 32。我这样做是为了使字符变为大写,通过减去 32,我能够得到我在字符串中找到的相应小写字符的大写字母。

但是我收到一个Segmentation fault错误,为什么会这样?

将for 循环条件更改为for (i = 0; str[i] != ''; i++),因为它应该检查每个索引。

char *string_toupper(char *str)
{
int i;
for (i = 0; str[i] != ''; i++)
{
if (str[i] >= 'a' && str[i] <= 'z')
str[i] =(int)str[i] - 32;
}
return (str);
}

根据要求,这是为教育和辩论提供的。

一些工作场所或机构坚持使用特定风格的大括号等。

请注意,函数名称不会在注释块中重现。坏习惯导致通过复制/粘贴错误且肯定具有误导性的评论块来满足主管。最好让代码使用传统的习语和标准库来解释自己。

#include <stdio.h>
#include <ctype.h>
#include <assert.h>
char *string_toupper( char *str ) {
// Uppercase all lowercase letters found in 'str'.
// Return str after processing.
assert( str != NULL ); // Trust no-one, especially yourself
// Alternative for()::  for( int i = 0; str[ i ]; i++ )
for( int i = 0; str[ i ] != ''; i++ )
str[ i ] = (char)toupper( str[ i ] ); // note casting.
return str;
}
int main( void ) {
char str[] = "Hello World!";
// No further use? Don't store return value; just use it.
printf( "%sn", string_toupper( str ) );
printf( "%sn", str );
return 0;
}

Prithvish很好地解释了OP的关键问题:错误的循环测试。

// for (i = 0; *str != ''; i++)
for (i = 0; str[i] != ''; i++)

为了帮助OP如何使我的代码在每个环境中工作?,一些想法供以后考虑。

未来名称

"以strmemwcs开头的函数名称以及小写字母可以添加到<string.h>标头中的声明中。" C17dr § 7.31.13

因此,不要对以str<lowercase>开头的函数名称进行编码,以避免将来发生冲突。

索引类型

int i;对于线来说太窄了。 使用size_t进行数组索引。

或者,只需增加指针。

具有分类is...()函数的测试用例

str[i] >= 'a' && str[i] <= 'z'在以下系统上不正确 [a...z] 不是连续的。 (这些天不常见 - 例如EBCDIC)。

topper()简化

要将任何字符转换为等效的大写字符,请执行以下操作:

str[i] = toupper(str[i]);

使用未签名的访问权限

is..(x)toupper(x)函数需要unsigned char字符值(或EOF)才能x

在即将过时的稀有非 2 补码系统上,应unsigned char访问字符串,以避免在 -0 上停止。


把这个放在一起:

#include <ctype.h>
char *str_toupper(char *str) {
unsigned char *ustr = (unsigned char *) str;
while (*ustr) {
*ustr = toupper(*ustr);
ustr++;
}
return str;
}

您的代码中存在一个重大错误:

  • 函数string_toupperfor (i = 0; *str != ''; i++)中的测试不正确:它只测试str的第一个字符,而不是测试字符串的结尾。按照编码,您不断修改内存远远超出 字符串的末尾,直到到达无法读取或写入的内存区域,从而导致分段错误。代码具有未定义的行为。你应该写:

    for (i = 0; str[i] != ''; i++)
    
  • 另请注意,if (str[i] >= 'a' && str[i] <= 'z')假定小写字母在执行字符集中形成一个连续块。虽然 ASCII 是这种情况,但您不应在可移植代码中做出此假设。

  • 同样,str[i] -= 32;特定于 ASCII 和相关字符集。您应该使用更具可读性的str[i] = str[i] - 'a' + 'A';或使用<ctype.h>中的函数。

这是一个修改版本:

#include <stdio.h>
/**
* string_toupper - This function will replace all lowercase letters in
* the string pointed by str with their uppercase equivalent
* @str: The string that will be checked for lowercase letters
*
* Return: The resulting string str, where all the letters are uppercase
*/
char *string_toupper(char *str) {
for (size_t i = 0; str[i] != ''; i++) {
if (str[i] >= 'a' && str[i] <= 'z')
str[i] = str[i] - 'a' + 'A';
}
return str;
}
int main() {
char str[] = "Hello World!n";
char *ptr;
printf("before: %sn", str);
ptr = string_toupper(str);
printf("result: %sn", ptr);
printf(" after: %sn", str);
return 0;
}

这是string_toupper()的便携式版本:

#include <ctype.h>
#include <stddef.h>
char *string_toupper(char *str) {
for (size_t i = 0; str[i] != ''; i++) {
if (islower((unsigned char)str[i]))
str[i] = (char)toupper((unsigned char)str[i]);
}
return str;
}

最新更新