CS50x Caesar - 插入 isalpha (argv[1]) 时出现分段错误
CS50x Caesar - Segmentation fault when inserting isalpha(argv[1])
对于 CS50x 问题 Caesar,我创建了一个使用 Caesar 密码加密消息的程序。
为此,程序必须认识到命令行参数只是一个数字。所以没有两个或更多数字,没有小于零的数字,也没有文本。
但是一旦我添加检查它是否是带有 || isalpha(argv[1])
的文本,程序就不再工作了。
当我尝试 运行 程序时,终端打印以下内容:
Segmentation fault
谁能告诉我代码有什么问题
#include <cs50.h>
#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>
#include <string.h>
int main(int argc, string argv[])
{
int kkey = 0;
// Check if correct command-line arguments
if (argc != 2 || atoi(argv[1]) < 0 || isalpha(argv[1])) //segfault here
{
printf("./caesar key\n");
return 1;
}
else
{
kkey = atoi(argv[1]);
}
// Ask for Plaintext to encrypt
string plaintext = get_string("plaintext: ");
for (int i = 0, n = strlen(plaintext); i < n; i++)
{
if (isalpha(plaintext[i]) && islower(plaintext[i]))
{
plaintext[i] = (plaintext[i] - 'a' + kkey) % 26 + 97;
}
else if (isalpha(plaintext[i]) && isupper(plaintext[i]))
{
plaintext[i] = (plaintext[i] - 'A' + kkey) % 26 + 65;
}
printf("%c", plaintext[i]);
}
printf("\n");
return 0;
}
非常感谢您的帮助。
,你不能使用字符串作为isalpha
的参数,你需要一个循环来检查字符串的每个字符。
无论如何这都不是最好的方法,使用取反的 isdigit
会是更好的选择,因为它考虑了所有其他非数字字符。
//...
// Check if correct command-line arguments
if (argc != 2 || atoi(argv[1]) < 0)
{
printf("./caesar key\n");
return 1;
}
for(size_t i = 0; i < strlen(argv[1]); i++){
if(!isdigit(argv[1][i])){ //if one of the characters is not a digit 0-9
puts("./caesar key\n");
return 1;
}
}
kkey = atoi(argv[1]); //no else needed
//...
请注意,如果转换后的值无法用 int
表示,atoi
将调用未定义的行为。
您可以使用 strtol
作为更强大的替代方案。
link 用于 Linux 手册页,我觉得它非常好,但这是 cross-platform。
同样,,使用字符代码可能会适得其反,在这种情况下,您使用的是 ASCII 编码,但还有其他编码,这会降低您的代码的可移植性,请改用字符,26 + 'a'
和 26 + 'A'
.
对于 CS50x 问题 Caesar,我创建了一个使用 Caesar 密码加密消息的程序。
为此,程序必须认识到命令行参数只是一个数字。所以没有两个或更多数字,没有小于零的数字,也没有文本。
但是一旦我添加检查它是否是带有 || isalpha(argv[1])
的文本,程序就不再工作了。
当我尝试 运行 程序时,终端打印以下内容:
Segmentation fault
谁能告诉我代码有什么问题
#include <cs50.h>
#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>
#include <string.h>
int main(int argc, string argv[])
{
int kkey = 0;
// Check if correct command-line arguments
if (argc != 2 || atoi(argv[1]) < 0 || isalpha(argv[1])) //segfault here
{
printf("./caesar key\n");
return 1;
}
else
{
kkey = atoi(argv[1]);
}
// Ask for Plaintext to encrypt
string plaintext = get_string("plaintext: ");
for (int i = 0, n = strlen(plaintext); i < n; i++)
{
if (isalpha(plaintext[i]) && islower(plaintext[i]))
{
plaintext[i] = (plaintext[i] - 'a' + kkey) % 26 + 97;
}
else if (isalpha(plaintext[i]) && isupper(plaintext[i]))
{
plaintext[i] = (plaintext[i] - 'A' + kkey) % 26 + 65;
}
printf("%c", plaintext[i]);
}
printf("\n");
return 0;
}
非常感谢您的帮助。
isalpha
的参数,你需要一个循环来检查字符串的每个字符。
无论如何这都不是最好的方法,使用取反的 isdigit
会是更好的选择,因为它考虑了所有其他非数字字符。
//...
// Check if correct command-line arguments
if (argc != 2 || atoi(argv[1]) < 0)
{
printf("./caesar key\n");
return 1;
}
for(size_t i = 0; i < strlen(argv[1]); i++){
if(!isdigit(argv[1][i])){ //if one of the characters is not a digit 0-9
puts("./caesar key\n");
return 1;
}
}
kkey = atoi(argv[1]); //no else needed
//...
请注意,如果转换后的值无法用 int
表示,atoi
将调用未定义的行为。
您可以使用 strtol
作为更强大的替代方案。
link 用于 Linux 手册页,我觉得它非常好,但这是 cross-platform。
同样,26 + 'a'
和 26 + 'A'
.