凯撒密码算法中 C 中的分段错误
Segmentation fault in C in Caesar cipher algorithm
正在尝试解决 CS50 的 Ceasar 解决方案。
我遇到分段错误。
更正式地说,凯撒算法(即密码)通过将每个字母“旋转”k 个位置来加密消息。更正式地说,如果 p 是一些明文(即未加密的消息),pi
是 p 中的第 i 个字符,k
是密钥(即非负整数),那么密文 c 中的每个字母 ci
计算为
ci = (pi + k) % 26
这是我的代码:
#include <cs50.h>
#include <stdio.h>
#include <ctype.h>
#include <string.h>
#include <stdlib.h>
string cipher(string ptext, int k);
int main(int argc, string argv[])
{
if (argc != 2)
{
printf("Usage: ./caesar key\n");
return 1;
}
else
{
string ptext = NULL;
string ctext = NULL;
for (int i = 0, n = strlen(argv[1]); i < n; i++)
{
if (isdigit(argv[1][i]) == 0)
{
return 1;
}
else
{
ptext = get_string("Text:");
int k = atoi(argv[1]);
ctext = cipher(ptext, k);
}
}
printf("Plain Text: %s \n Cipher Text: %s", ptext, ctext);
return 0;
}
}
string cipher(string ptext, int k)
{
string ctext = NULL;
for (int i = 0, n = strlen(ptext); i < n; i++) {
// check if lower / upper is true if yes then shift chars by k % 26 and append to ctext
if (islower(ptext[i]))
{
ctext[i] = (ptext[i] + k - 96) % 26 + 96;
}
else if (isupper(ptext[i]))
{
ctext[i] = (ptext[i] + k - 65) % 26 + 65;
} // else append as it is
else
{
ctext[i] = ptext[i];
}
}
return (ctext);
}
输入 Hi!。我想要一个输出 Ij!
我无法弄清楚这个错误。请帮忙
with debug my code is exiting at
ctext1[i] = (ptext[i] + k1 - 65) % 26 + 65;
您还没有为您的字符串分配任何内存。这是分段错误的原因,因为 ctext[i]
访问了无效的内存地址。
要解决这个问题,您必须将内存分配给 ctext
。
CS50 introduces a type string
hiding a char
pointer. This creates confusion as this string
type is very different from what other languages name as such. Pointers are a fundamental concept that must be mastered to write programs in C.
The statement ptext = get_string("Text:");
sets ptext
to the pointer value returned by the function get_string()
declared in <cs50.h>
. This function allocates memory for an array of char
, reads user input into this array, sets a null terminator (a byte with a zero value) at the end of the array and returns a pointer to the first element of this array.
For your program to work, you can either:
- modify the array in place, replacing each byte with its cipher value, or
- allocate another array and store the cipher values into it, appending a null terminator after them. You chose this approach, but did not allocate the array.
Note also these problems:
- the
for
loop validating the key string should be separate from the code calling the cypher
function.
- you should use character values such as
'a'
and 'A'
instead of hard coding their ASCII values. It improves portability and readability.
Here is a modified version:
#include <cs50.h>
#include <ctype.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
char *cipher(char *ptext, int k);
int main(int argc, char *argv[]) {
if (argc != 2) {
printf("Usage: ./caesar key\n");
return 1;
} else {
char *key = argv[1];
for (int i = 0, n = strlen(key); i < n; i++) {
if (isdigit(key[i]) == 0) {
return 1;
}
}
int k = atoi(key);
char *ptext = get_string("Text:");
char *ctext = cipher(ptext, k);
printf("Plain Text: %s\nCipher Text: %s", ptext, ctext);
free(ctext);
return 0;
}
}
char *cipher(char *ptext, int k) {
int n = strlen(ptext);
char *ctext = malloc(n + 1); // allocate memory for the cipher string
if (ctext == NULL)
return NULL;
for (int i = 0; i < n; i++) {
unsigned char pi = ptext[i];
// check if lower / upper is true if yes then shift chars by k % 26 and append to ctext
if (islower(pi))
{
// handle lowercase letter
ctext[i] = (pi - 'a' + k) % 26 + 'a';
}
else if (isupper(pi))
{
// handle uppercase letter
ctext[i] = (pi - 'A' + k) % 26 + 'A';
}
else
{
// else append as it is
ctext[i] = pi;
}
}
ctext[n] = '[=10=]'; // set the null terminator
return ctext;
}
正在尝试解决 CS50 的 Ceasar 解决方案。 我遇到分段错误。
更正式地说,凯撒算法(即密码)通过将每个字母“旋转”k 个位置来加密消息。更正式地说,如果 p 是一些明文(即未加密的消息),pi
是 p 中的第 i 个字符,k
是密钥(即非负整数),那么密文 c 中的每个字母 ci
计算为
ci = (pi + k) % 26
这是我的代码:
#include <cs50.h>
#include <stdio.h>
#include <ctype.h>
#include <string.h>
#include <stdlib.h>
string cipher(string ptext, int k);
int main(int argc, string argv[])
{
if (argc != 2)
{
printf("Usage: ./caesar key\n");
return 1;
}
else
{
string ptext = NULL;
string ctext = NULL;
for (int i = 0, n = strlen(argv[1]); i < n; i++)
{
if (isdigit(argv[1][i]) == 0)
{
return 1;
}
else
{
ptext = get_string("Text:");
int k = atoi(argv[1]);
ctext = cipher(ptext, k);
}
}
printf("Plain Text: %s \n Cipher Text: %s", ptext, ctext);
return 0;
}
}
string cipher(string ptext, int k)
{
string ctext = NULL;
for (int i = 0, n = strlen(ptext); i < n; i++) {
// check if lower / upper is true if yes then shift chars by k % 26 and append to ctext
if (islower(ptext[i]))
{
ctext[i] = (ptext[i] + k - 96) % 26 + 96;
}
else if (isupper(ptext[i]))
{
ctext[i] = (ptext[i] + k - 65) % 26 + 65;
} // else append as it is
else
{
ctext[i] = ptext[i];
}
}
return (ctext);
}
输入 Hi!。我想要一个输出 Ij! 我无法弄清楚这个错误。请帮忙
with debug my code is exiting at
ctext1[i] = (ptext[i] + k1 - 65) % 26 + 65;
您还没有为您的字符串分配任何内存。这是分段错误的原因,因为 ctext[i]
访问了无效的内存地址。
要解决这个问题,您必须将内存分配给 ctext
。
CS50 introduces a type string
hiding a char
pointer. This creates confusion as this string
type is very different from what other languages name as such. Pointers are a fundamental concept that must be mastered to write programs in C.
The statement ptext = get_string("Text:");
sets ptext
to the pointer value returned by the function get_string()
declared in <cs50.h>
. This function allocates memory for an array of char
, reads user input into this array, sets a null terminator (a byte with a zero value) at the end of the array and returns a pointer to the first element of this array.
For your program to work, you can either:
- modify the array in place, replacing each byte with its cipher value, or
- allocate another array and store the cipher values into it, appending a null terminator after them. You chose this approach, but did not allocate the array.
Note also these problems:
- the
for
loop validating the key string should be separate from the code calling thecypher
function. - you should use character values such as
'a'
and'A'
instead of hard coding their ASCII values. It improves portability and readability.
Here is a modified version:
#include <cs50.h>
#include <ctype.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
char *cipher(char *ptext, int k);
int main(int argc, char *argv[]) {
if (argc != 2) {
printf("Usage: ./caesar key\n");
return 1;
} else {
char *key = argv[1];
for (int i = 0, n = strlen(key); i < n; i++) {
if (isdigit(key[i]) == 0) {
return 1;
}
}
int k = atoi(key);
char *ptext = get_string("Text:");
char *ctext = cipher(ptext, k);
printf("Plain Text: %s\nCipher Text: %s", ptext, ctext);
free(ctext);
return 0;
}
}
char *cipher(char *ptext, int k) {
int n = strlen(ptext);
char *ctext = malloc(n + 1); // allocate memory for the cipher string
if (ctext == NULL)
return NULL;
for (int i = 0; i < n; i++) {
unsigned char pi = ptext[i];
// check if lower / upper is true if yes then shift chars by k % 26 and append to ctext
if (islower(pi))
{
// handle lowercase letter
ctext[i] = (pi - 'a' + k) % 26 + 'a';
}
else if (isupper(pi))
{
// handle uppercase letter
ctext[i] = (pi - 'A' + k) % 26 + 'A';
}
else
{
// else append as it is
ctext[i] = pi;
}
}
ctext[n] = '[=10=]'; // set the null terminator
return ctext;
}