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

CS50 Substitution作业报错:int转string指针类型不兼容问题求助

解决CS50 Pset2 Substitution编译错误及指针疑问

编译错误核心原因

你碰到的incompatible integer to pointer conversion错误,根源是两个关键问题:

  1. ciphertext类型定义错误:你写的char *ciphertext[strlen(plaintext)]是一个指针数组,每个元素都是char*(指向字符的指针),但你试图赋值的k[j]是单个字符(char类型),而toupper(k[j])返回的是int类型(C语言中这类字符处理函数为兼容EOF返回整数),把整数/字符赋值给指针变量,必然触发类型不匹配报错。
  2. 函数名拼写错误:声明的函数是substitution,但定义时写成了substituion(少一个t),这会导致后续链接错误,不过当前编译阶段优先触发了前者的错误。

指针基础说明

在CS50环境里,string是typedef char* string的别名,本质就是指向字符的指针:

  • 指针是存储内存地址的变量,char*类型指针指向内存中某个字符的位置。
  • C语言中字符串是一段连续的字符内存,最后用'\0'(空字符)标记结束,string变量存储的就是这段内存第一个字符的地址。
  • 比如string s = "hello",s指向字符'h'的内存地址,s[0]等价于*(s+0),是通过指针偏移访问对应位置字符的语法糖。

代码修正步骤

1. 修正ciphertext的内存分配

不能在栈上定义数组后返回(函数结束后栈内存会被释放,返回的指针会变成野指针),需用动态内存分配:

string ciphertext = malloc(strlen(plaintext) + 1); // +1是为了存储字符串终止符'\0'

2. 修正循环边界

原代码i <= strlen(plaintext)会越界,因为字符串索引范围是0到strlen(plaintext)-1,最后一个位置是'\0',应改为:

for(int i = 0; i < strlen(plaintext); i++)

3. 初始化重复计数数组

原代码int repeated[26];未初始化,数组元素是随机值,会导致重复字符检查逻辑错误,需初始化为全0:

int repeated[26] = {0};

4. 处理非字母字符

原代码只处理大小写字母,非字母字符(空格、标点等)未处理,需直接复制到密文中:

if (!isalpha(plaintext[i])) {
    ciphertext[i] = plaintext[i];
    continue;
}

5. 修正函数名拼写

把substituion改为substitution,与函数声明保持一致。

6. 补充字符串终止符

动态分配的密文数组最后要手动添加'\0',确保是合法的C字符串:

ciphertext[strlen(plaintext)] = '\0';

修正后的完整代码

#include <cs50.h>
#include <stdio.h>
#include <string.h>
#include <ctype.h>

string substitution(string k);

int main(int argc, string argv[])
{
    // 检查参数数量和密钥长度
    if(argc != 2 || strlen(argv[1]) != 26)
    {
        printf("usage: ./substitution key\n");
        return 1;
    }

    // 检查密钥是否全为字母
    for(int i = 0; i < 26; i++)
    {
        if(!isalpha(argv[1][i]))
        {
            printf("only letters are allowed in the key\n");
            return 1;
        }
    }

    // 字母表和重复计数数组(初始化全0)
    int repeated[26] = {0};
    char alphabet[26] = {'a','b','c','d','e','f','g','h','i','j','k','l','m','n','o','p','q','r','s','t','u','v','w','x','y','z'};

    // 将密钥转为小写
    string key = argv[1];
    for(int i = 0; i < 26; i++)
    {
        key[i] = tolower(key[i]);
    }

    // 统计每个字母出现的次数
    for(int i = 0; i < 26; i++)
    {
        for(int j = 0; j < 26; j++)
        {
            if(alphabet[i] == key[j])
            {
                repeated[i]++;
            }
        }
    }

    // 检查密钥是否包含所有字母且无重复
    for(int i = 0; i < 26; i++)
    {
        if(repeated[i] != 1)
        {
            printf("key must contain all of the alphabet without repetitions\n");
            return 1;
        }
    }

    printf("ciphertext: %s\n", substitution(key));
}

string substitution(string k)
{
    char alphabet[26] = {'a','b','c','d','e','f','g','h','i','j','k','l','m','n','o','p','q','r','s','t','u','v','w','x','y','z'};
    string plaintext = get_string("plaintext: ");
    // 动态分配内存,+1存终止符
    string ciphertext = malloc(strlen(plaintext) + 1);

    // 明文转密文
    for(int i = 0; i < strlen(plaintext); i++)
    {
        // 非字母直接复制
        if(!isalpha(plaintext[i]))
        {
            ciphertext[i] = plaintext[i];
            continue;
        }

        // 处理大写字母
        if(isupper(plaintext[i]))
        {
            for(int j = 0; j < 26; j++)
            {
                if(plaintext[i] == toupper(alphabet[j]))
                {
                    ciphertext[i] = toupper(k[j]);
                    break; // 找到对应字母后退出循环
                }
            }
        }
        // 处理小写字母
        else
        {
            for(int j = 0; j < 26; j++)
            {
                if(plaintext[i] == alphabet[j])
                {
                    ciphertext[i] = k[j];
                    break; // 找到对应字母后退出循环
                }
            }
        }
    }
    // 添加字符串终止符
    ciphertext[strlen(plaintext)] = '\0';

    return ciphertext;
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.20 06:15:13