You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

CS50字符串转大小写后打印异常:存储变量与直接输出结果不符

CS50替换密码习题中的字符串处理问题

我正在完成CS50的替换密码习题,使用cs50.h库的string类型处理字符串。自己实现了两个字符串大小写转换函数:

string strtolower(string text)
{
    int length = strlen(text);
    for (int i = 0; i < length; i++)
    {
        text[i] = tolower(text[i]);
    }
    return text;
}

string strtoupper(string text)
{
    int length = strlen(text);
    for (int i = 0; i < length; i++)
    {
        text[i] = toupper(text[i]);
    }
    return text;
}

测试异常情况

当在main函数中按以下方式调用时:

string key_upper = strtoupper(key);
string key_lower = strtolower(key);
printf("%s\n", key_upper);
printf("%s\n", key_lower);

无论输入的key是FFFFFFFFFFFFFFFFFFFFFFFFFF还是ffffffffffffffffffffffffff,输出都是:

ffffffffffffffffffffffffff
ffffffffffffffffffffffffff

修改调用方式,增加直接打印函数返回值的语句:

string key_upper = strtoupper(key);
string key_lower = strtolower(key);
printf("%s\n", key_upper);
printf("%s\n", key_lower);
printf("%s\n", strtoupper(key));

输出变为:

ffffffffffffffffffffffffff
ffffffffffffffffffffffffff
FFFFFFFFFFFFFFFFFFFFFFFFFF

进一步测试:

printf("%s\n", key_upper);
printf("%s\n", key_lower);
printf("%s\n", strtoupper(key));
printf("%s\n", key_lower);
printf("%s\n", strtolower(key));

输出为:

ffffffffffffffffffffffffff
ffffffffffffffffffffffffff
FFFFFFFFFFFFFFFFFFFFFFFFFF
FFFFFFFFFFFFFFFFFFFFFFFFFF
ffffffffffffffffffffffffff

核心疑问

  1. 为什么直接打印函数返回值和存储到变量后打印的结果不同?
  2. 这是否和cs50.h的string实现有关?
  3. 如何正确存储函数返回值以便后续调用?

问题原因

cs50.h中的string本质是char*的别名,你的转换函数直接修改了传入的text指向的内存区域——也就是原key字符串所在的内存。

当执行string key_upper = strtoupper(key);时,key_upper和key指向同一块内存,此时内容被转为大写;但紧接着调用strtolower(key),又把同一块内存的内容改成小写,所以key_upper和key_lower指向的都是被修改为小写后的内存,打印结果自然一致。

而直接调用printf("%s\n", strtoupper(key));时,函数修改内存后立刻打印,此时还未被后续的strtolower修改,所以能看到大写结果;后续再打印key_lower时,内存已经被strtoupper再次改成大写,输出也随之变化。

解决方案

要解决这个问题,需要在转换函数中创建原字符串的独立副本,修改副本后返回,而非直接修改原字符串的内存。修改后的函数示例:

#include <stdlib.h>
#include <string.h>

string strtolower(string text)
{
    int length = strlen(text);
    // 分配内存存储副本,+1用于存放字符串结束符'\0'
    string lower = malloc(length + 1);
    if (lower == NULL) // 检查内存分配是否成功
    {
        return NULL;
    }
    strcpy(lower, text); // 复制原字符串到副本
    for (int i = 0; i < length; i++)
    {
        lower[i] = tolower(lower[i]);
    }
    return lower;
}

string strtoupper(string text)
{
    int length = strlen(text);
    string upper = malloc(length + 1);
    if (upper == NULL)
    {
        return NULL;
    }
    strcpy(upper, text);
    for (int i = 0; i < length; i++)
    {
        upper[i] = toupper(upper[i]);
    }
    return upper;
}

注意:使用完动态分配的字符串后,需要用free()释放内存避免泄漏:

string key_upper = strtoupper(key);
string key_lower = strtolower(key);
// 使用key_upper和key_lower
free(key_upper);
free(key_lower);

修改后,key_upper和key_lower会指向各自独立的内存区域,不会互相覆盖,即可得到预期输出。

内容的提问来源于stack exchange,提问作者56492583

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.08 01:25:11