c - cs50 PSET2 替换:仅在使用 DWUSXNPQKEGCZFJBTLYROHIAVM 作为密钥加密所有字母字符时出现问题
问题描述
我是cs50的初学者。这是我第二周的工作。这是问题集替换。
所以这是我的代码。除这道题外,所有题都编译成功。输出为“分段错误”
这是我的代码:
#include <stdio.h>
#include <cs50.h>
#include <string.h>
#include <ctype.h>
#include <stdlib.h>
int main (int argc, string argv[])
{
string key1 = argv[1];
//check for only 2 arguments//
if (argc != 2)
{
printf("Usage: ./substitution key\n");
return 1;
}
//check key length, must 26 lenght//
if (strlen(key1) != 26)
{
printf("Key must contain 26 characters.\n");
return 1;
}
for (int i=0; i < strlen(key1); i++)
{
//check for non alphabet//
if (!(isalpha(key1[i])))
{
printf("Key must contain only letters.\n");
return 1;
}
//convert all word to uppercase to make encryption easier//
else
{
key1[i] = toupper (key1[i]);
}
//check for not repeated word//
for (int j=0; j < i; j++)
{
if (key1[i] == key1[j])
{
printf("Key must not contain repeated letters.\n");
return 1;
}
}
}
//ask input//
string input1 = get_string("plaintext: ");
string input2 = input1;
//check if the word is lower or uppercase//
int checker[25];
for (int s = 0; s < strlen (input1); s++)
{
if (isupper(input1[s]) == 0)
{
checker[s] = 0; //false
//convert to uppercase to make encryption easier//
input1[s] = toupper (input1[s]);
}
else
{
checker[s] = 1; //true
}
//printf("Input %d: %c is %d\n", s, input1[s], checker[s]); //debug//
}
//printf("word is %s\n", input1); //debug//
//CONVERTTTT//
int new_ascii = 0;
printf("ciphertext: ");
for (int k = 0; k < strlen(input1); k++)
{
char x = input1[k];
int ascii = (int) x;
//check if it's alphabet or not//
if (isalpha(x))
{
ascii -= 65;
new_ascii = key1[ascii];
//restore to upper/lowercase
if (checker[k]==0)
{
new_ascii = (int) tolower ((char) new_ascii); //we use tolower cause all word has converted to upper
}
}
else //if not just continue
{
new_ascii = ascii;
}
printf("%c", (char) new_ascii);
}
printf("\n");
return 0;
}
这是输出:
./substitution DWUSXNPQKEGCZFJBTLYROHIAVM
plaintext: The quick brown fox jumps over the lazy dog
Segmentation fault
我不知道我的问题在哪里,因为这是唯一一个无法编译的。有人有线索吗?
解决方案
(不幸的是,我无法在 onlinegdb.com 上重现分段错误。)
数组的大小checker
必须至少是输入的字符串长度。这是有问题的,因为您不知道输入将持续多长时间。您的示例输入比数组的大小 25 长,因此您的代码将写入数组末尾并(尝试)覆盖存储在此内存位置的任何内容。这可能导致分段错误。
为避免对数组的这种越界访问,您可以检查输入字符串的长度并截断它或打印一条错误消息,通知用户有关限制。
更好的解决方案是将大写/小写检查集成到加密输入的函数中。使用这种方法,您必须只知道刚刚处理的字符的大写/小写信息,而不是输入字符串的所有字符。
由于这是一项学习任务,因此我没有展示现成的解决方案,而只是将算法作为伪代码:
for all characters of the input string
{
get the next character
if alphabetic (or better if it is in range 'A'..'Z' or 'a'..'z')
{
if lowercase
{
set lowercase flag
key index = character - 'a'
}
else
{
clear lowercase flag
key index = character - 'A'
}
get encrypted character based on key index
if lowercase flag
{
convert to lowercase
}
print encrypted character
}
else /* not alphabetic */
{
print original character
}
}
请注意,函数的结果isalpha
取决于您的语言环境设置。对于英语以外的语言,其他字符可能被归类为字母字符。这可能会导致对您的密钥数组的越界访问。为避免这种情况,您可以为..或..添加检查isascii
或使用显式检查。'A'
'Z'
'a'
'z'
推荐阅读
- json - JSON 数组中的长字符串导致 .NET Core Web API 中出现 400 Bad Request
- css - 如何使用 Flexbox 将第二个孩子包裹在第一个孩子周围
- python - 基于训练好的张量流模型对单张图像进行分类
- amazon-web-services - DynamodDB - 按小时/分钟付费(存储成本)
- python - load_model() 缺少 1 个必需的位置参数:“文件路径”
- video - iframe Vimeo 全屏按钮未显示
- javascript - 如何解决 document.body.innerHTML.replace 冲突?
- gitlab - 在 Gitlab 中为 GitKraken 重定向 URI
- c++ - C++ 中的执行时间差异(通过引用传递和通过值传递的函数之间)是否显着?
- php - 如何避免在一个字段出现错误时要求用户重新填写所有表单字段