CS50 Substitution作业报错:int转string指针类型不兼容问题求助
解决CS50 Pset2 Substitution编译错误及指针疑问
编译错误核心原因
你碰到的incompatible integer to pointer conversion错误,根源是两个关键问题:
- ciphertext类型定义错误:你写的
char *ciphertext[strlen(plaintext)]是一个指针数组,每个元素都是char*(指向字符的指针),但你试图赋值的k[j]是单个字符(char类型),而toupper(k[j])返回的是int类型(C语言中这类字符处理函数为兼容EOF返回整数),把整数/字符赋值给指针变量,必然触发类型不匹配报错。 - 函数名拼写错误:声明的函数是
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
相关产品推荐
相关产品推荐

