我将 运行 保留为一个我似乎无法修复的分段错误
I keep running into a segmentation error that I can't seem to be able to fix
对于我正在学习的课程,我应该创建一个程序,使用用户作为命令行参数输入的密钥从明文创建一个简单的密文。
这是代码,它是用 C 语言编写的
#include <stdio.h>
#include <ctype.h>
#include <cs50.h>
#include <string.h>
int main(int argc , string argv[])
{
string key = argv[1];
char keyL[2][26];
char keyU[2][26];
int normL = 97;
int normU = 65;
for (int i = 0;i <= 25;i++ , normL++, normU++)
{
keyL[0][i] = tolower(key[i]);
keyU[0][i] = toupper(key[i]);
keyL[1][i] = (char) normL;
keyU[1][i] = (char) normU;
}
string plaint = get_string("plaintext:);
string ciphert = "";
int lengplain = strlen(plaint);
for (int f = 0 ; f <= lengplain ; f++)
{
if (isupper(plaint[f]) == true)
{
for (int d = 0;d<=25;d++)
{
if (plaint[f] == keyU[0][d])
{
ciphert[f] = keyL[1][d];
}
}
}
else if (islower(plaint[f]) == true)
{
for (int x = 0;x<=25;x++)
{
if (plaint[f] == keyU[0][x])
{
ciphert[f] = keyL[1][x];
}
}
}
else
{
ciphert[f] = plaint [f];
}
}
printf("ciphertext: %s\n" , ciphert);
}
这可以编译,但是当我 运行 它时,我 运行 变成了一个分段错误。如果您发现任何逻辑错误,请自行保留。这是我优先修复的分段错误。
谢谢!
string ciphert = "";
这将用“”初始化字符串。问题?它位于只读部分。你在这一行中写: ciphert[f] = plaint [f];
到这个数组==> 你写到一个只读部分==> 崩溃。
(此外,您应该检查 argc 中提供的参数数量,否则它会在这一行中崩溃 (keyL[0][i] = tolower(key[i]);
)
c 中的字符串与其他语言中的字符串不同。在 c 中,字符串是指向字符数组的指针,其中最后一个字符是空终止符 '[=10=]'
。当您声明字符串 ciphert = "";
时,您实际上是在创建一个长度为 1 的字符数组,其中只有空终止符。当您尝试访问不存在的密码元素时会发生段错误 ciphert[f] = plaint[f]
您必须将 ciphert 声明为长度为 lengplain + 1
的数组,这使得它与明文(加上空终止符)的长度相同,并且允许您这样做 ciphert[f] = plaint[f]
。
我建议您看一下有关 c.
中字符串的一些指南
发布的代码有几个问题。这是一个典型的问题:
string plaint = get_string("plaintext:);
get_string()
的参数必须是指向以 NUL 结尾的字符数组的指针。
这个参数:
"plaintext:
缺少结尾的双引号:"
你试过编译贴出的代码吗?我想不会,因为编译会因为这个问题而失败。
编译时,始终启用警告,然后修复这些警告。
对于gcc
建议:
gcc -c -g -Wall -Wextra -Wconversion -pedantic -std=gnu11
请注意,其他编译器使用不同的选项来产生相同的结果。
关于;
int lengplain = strlen(plaint);
函数:strlen()
returns一个size_t
,不是一个int
关于;
string key = argv[1];
切勿在未首先检查 argc
以确保用户实际输入了预期的命令行参数的情况下访问 argv[0]
以外的内容。
关于:
int normL = 97;
int normU = 65;
使用 'magic' 数字是一种糟糕的编程习惯,因为它们会使代码更难以理解、调试等。建议;
int normL = 'a';
int normU = 'A';
关于:
char keyL[2][26];
char keyU[2][26];
'magic'数26
没有意义。建议(在 #include
语句之后)定义一个有意义的名称:
#define alphabetLen 26
然后在整个代码中使用该有意义的名称。
您可以通过更改以下内容来避免您的代码读者的烦恼:
for (int i = 0;i <= 25;i++ , normL++, normU++)
{
keyL[1][i] = (char) normL;
keyU[1][i] = (char) normU;
至
for ( int i = 0; i < alphabetLen; i++ )
{
keyL[1][i] = normL + 'a';
keyU[1][i] = normU + 'A';
并且:
int normL = 97;
int normU = 65;
至:
int normL = 'a';
int normU = 'A';
当然,为了消除一些警告,这个
keyL[1][i] = normL;
keyU[1][i] = normU;
最好通过以下方式编写(并且没有编译器警告):
keyL[1][i] = (char) normL;
keyU[1][i] = (char) normU;
关于;
string ciphert = "";
这会生成一个指向只读内存的指针,指向一个只有 1 个字符长的文字。因为它在只读内存中,代码不能写入它,也不能从它偏移。建议:
string ciphert[ 26+1 ];
对于我正在学习的课程,我应该创建一个程序,使用用户作为命令行参数输入的密钥从明文创建一个简单的密文。
这是代码,它是用 C 语言编写的
#include <stdio.h>
#include <ctype.h>
#include <cs50.h>
#include <string.h>
int main(int argc , string argv[])
{
string key = argv[1];
char keyL[2][26];
char keyU[2][26];
int normL = 97;
int normU = 65;
for (int i = 0;i <= 25;i++ , normL++, normU++)
{
keyL[0][i] = tolower(key[i]);
keyU[0][i] = toupper(key[i]);
keyL[1][i] = (char) normL;
keyU[1][i] = (char) normU;
}
string plaint = get_string("plaintext:);
string ciphert = "";
int lengplain = strlen(plaint);
for (int f = 0 ; f <= lengplain ; f++)
{
if (isupper(plaint[f]) == true)
{
for (int d = 0;d<=25;d++)
{
if (plaint[f] == keyU[0][d])
{
ciphert[f] = keyL[1][d];
}
}
}
else if (islower(plaint[f]) == true)
{
for (int x = 0;x<=25;x++)
{
if (plaint[f] == keyU[0][x])
{
ciphert[f] = keyL[1][x];
}
}
}
else
{
ciphert[f] = plaint [f];
}
}
printf("ciphertext: %s\n" , ciphert);
}
这可以编译,但是当我 运行 它时,我 运行 变成了一个分段错误。如果您发现任何逻辑错误,请自行保留。这是我优先修复的分段错误。
谢谢!
string ciphert = "";
这将用“”初始化字符串。问题?它位于只读部分。你在这一行中写: ciphert[f] = plaint [f];
到这个数组==> 你写到一个只读部分==> 崩溃。
(此外,您应该检查 argc 中提供的参数数量,否则它会在这一行中崩溃 (keyL[0][i] = tolower(key[i]);
)
c 中的字符串与其他语言中的字符串不同。在 c 中,字符串是指向字符数组的指针,其中最后一个字符是空终止符 '[=10=]'
。当您声明字符串 ciphert = "";
时,您实际上是在创建一个长度为 1 的字符数组,其中只有空终止符。当您尝试访问不存在的密码元素时会发生段错误 ciphert[f] = plaint[f]
您必须将 ciphert 声明为长度为 lengplain + 1
的数组,这使得它与明文(加上空终止符)的长度相同,并且允许您这样做 ciphert[f] = plaint[f]
。
我建议您看一下有关 c.
发布的代码有几个问题。这是一个典型的问题:
string plaint = get_string("plaintext:);
get_string()
的参数必须是指向以 NUL 结尾的字符数组的指针。
这个参数:
"plaintext:
缺少结尾的双引号:"
你试过编译贴出的代码吗?我想不会,因为编译会因为这个问题而失败。
编译时,始终启用警告,然后修复这些警告。
对于gcc
建议:
gcc -c -g -Wall -Wextra -Wconversion -pedantic -std=gnu11
请注意,其他编译器使用不同的选项来产生相同的结果。
关于;
int lengplain = strlen(plaint);
函数:strlen()
returns一个size_t
,不是一个int
关于;
string key = argv[1];
切勿在未首先检查 argc
以确保用户实际输入了预期的命令行参数的情况下访问 argv[0]
以外的内容。
关于:
int normL = 97;
int normU = 65;
使用 'magic' 数字是一种糟糕的编程习惯,因为它们会使代码更难以理解、调试等。建议;
int normL = 'a';
int normU = 'A';
关于:
char keyL[2][26];
char keyU[2][26];
'magic'数26
没有意义。建议(在 #include
语句之后)定义一个有意义的名称:
#define alphabetLen 26
然后在整个代码中使用该有意义的名称。
您可以通过更改以下内容来避免您的代码读者的烦恼:
for (int i = 0;i <= 25;i++ , normL++, normU++)
{
keyL[1][i] = (char) normL;
keyU[1][i] = (char) normU;
至
for ( int i = 0; i < alphabetLen; i++ )
{
keyL[1][i] = normL + 'a';
keyU[1][i] = normU + 'A';
并且:
int normL = 97;
int normU = 65;
至:
int normL = 'a';
int normU = 'A';
当然,为了消除一些警告,这个
keyL[1][i] = normL;
keyU[1][i] = normU;
最好通过以下方式编写(并且没有编译器警告):
keyL[1][i] = (char) normL;
keyU[1][i] = (char) normU;
关于;
string ciphert = "";
这会生成一个指向只读内存的指针,指向一个只有 1 个字符长的文字。因为它在只读内存中,代码不能写入它,也不能从它偏移。建议:
string ciphert[ 26+1 ];