当我运行我的代码并选择选项2或3时,在输入我的字符串后,我收到了分段错误错误,而且我看不出导致错误的原因。我假设我的加密和解密功能有问题,但我不确定是什么。
#include <stdio.h>
#include <string.h>
#define SIZE 500
int getUserChoice()
{
int decision = 0;
printf("-------------------------------\n");
printf("| 1) Change Shift (default 3) |\n");
printf("| 2) Encrypt a message |\n");
printf("| 3) Decrypt a message |\n");
printf("| 4) Quit |\n");
printf("-------------------------------\n");
printf("Option: ");
scanf("%d", &decision);
if(decision <= 0 || decision >= 4)
{
return 0;
}
return decision;
}
int getShift()
{
int key = 3;
printf("Enter new shift value: ");
scanf("%d", &key);
return key;
}
void getString(char buf[])
{
char c = 0;
int i = 0;
while((c = getchar()) != '\n' && c != EOF){
}
printf("Input: ");
fgets(buf, SIZE, stdin);
printf("Output: %s\n", buf[i]);
}
void encrypt(char buf[], int shift)
{
int i;
for(i = 0; i < (strlen(buf-1));++i)
{
buf[i] = buf[i] + shift;
}
}
void decrypt(char buf[], int shift)
{
int i;
for(i = 0; i < (strlen(buf-1)); ++i)
{
buf[i] = buf[i] - shift;
}
}
int main()
{
char userStr[SIZE];
int shift = 3;
int number;
while(1)
{
number = getUserChoice();
if(number == 1)
{
shift = getShift();
}
if (number == 2)
{
getString(userStr);
encrypt(userStr, shift);
}
if (number == 3)
{
getString(userStr);
decrypt(userStr, shift);
}
if (number == 0)
{
break;
}
}
return 0;
}
答案 0 :(得分:1)
由于getString()
函数中的这一行:
printf("Output: %s\n", buf[i]);
buf[i]
中存储的值是char
,但您尝试使用%s
转换规范进行打印,从而导致未定义的行为。 encrypt()
和decrypt()
函数中也存在问题,您尝试查找strlen(buf - 1)
。请记住,buf
转换为表达式中char
的指针,因此这是指针算术。如果指针算术运算的结果指向不在数组本身中的任何位置,或者指向数组末尾之外的任何位置,则行为未定义。所以你也有UB。我怀疑你的意思是strlen(buf) - 1
,无论如何都不应该这样。
您应该重写getString()
函数以从输入中删除尾随换行符,以便您不再需要担心它。此外,如果用户输入太多字符,输入流中会留下额外的字符,最好丢弃这些字符:
void getString(char buf[])
{
int c;
int i = 0;
while ((c = getchar()) != '\n' && c != EOF)
continue; // discard leading characters
fgets(buf, SIZE, stdin);
while (buf[i] != '\n' && buf[i] != '\0')
{
++i;
}
if (buf[i] == '\n') // replace newline with '\0'
{
buf[i] = '\0';
} else {
while ((c = getchar()) != '\n' && c != EOF)
continue; // discard extra characters
}
}
此处,c
被声明为int
,以保留可能的EOF
值。在调用fgets()
之前有一个循环,用于删除先前调用scanf()
的输入流中剩余的任何内容。获得输入后,有一个循环在输入中搜索\n
个字符。如果找到,则换行符将替换为NUL
终止符。否则,输入流中会有额外的字符,这些字符将被丢弃。
打印Input:
和Output:
的代码已移至main()
,应该显示,以便显示已转换的输入。
encrypt()
和decrypt()
函数可以通过\0
未转换的方式轻松改进:
void encrypt(char buf[], int shift)
{
int i = 0;
while (buf[i] != '\0')
{
buf[i] = buf[i] + shift;
++i;
}
}
循环继续,直到遇到NUL
字符,而不是使用计数来控制循环。
以下是修改后的代码:
#include <stdio.h>
#include <string.h>
#define SIZE 500
int getUserChoice(void)
{
int decision = 0;
printf("-------------------------------\n");
printf("| 1) Change Shift (default 3) |\n");
printf("| 2) Encrypt a message |\n");
printf("| 3) Decrypt a message |\n");
printf("| 4) Quit |\n");
printf("-------------------------------\n");
printf("Option: ");
scanf("%d", &decision);
if(decision <= 0 || decision >= 4)
{
return 0;
}
return decision;
}
int getShift(void)
{
int key = 3;
printf("Enter new shift value: ");
scanf("%d", &key);
return key;
}
void getString(char buf[])
{
int c;
int i = 0;
while ((c = getchar()) != '\n' && c != EOF)
continue; // discard leading characters
fgets(buf, SIZE, stdin);
while (buf[i] != '\n' && buf[i] != '\0')
{
++i;
}
if (buf[i] == '\n') // replace newline with '\0'
{
buf[i] = '\0';
} else {
while ((c = getchar()) != '\n' && c != EOF)
continue; // discard extra characters
}
}
void encrypt(char buf[], int shift)
{
int i = 0;
while (buf[i] != '\0')
{
buf[i] = buf[i] + shift;
++i;
}
}
void decrypt(char buf[], int shift)
{
int i = 0;
while (buf[i] != '\0')
{
buf[i] = buf[i] - shift;
++i;
}
}
int main(void)
{
char userStr[SIZE];
int shift = 3;
int number;
while(1)
{
number = getUserChoice();
if(number == 1)
{
shift = getShift();
}
if (number == 2)
{
printf("Input: ");
getString(userStr);
encrypt(userStr, shift);
printf("Output: %s\n", userStr);
}
if (number == 3)
{
printf("Input: ");
getString(userStr);
decrypt(userStr, shift);
printf("Output: %s\n", userStr);
}
if (number == 0)
{
break;
}
}
return 0;
}
以下是一个示例互动:
-------------------------------
| 1) Change Shift (default 3) |
| 2) Encrypt a message |
| 3) Decrypt a message |
| 4) Quit |
-------------------------------
Option: 2
Input: hello world
Output: khoor#zruog
-------------------------------
| 1) Change Shift (default 3) |
| 2) Encrypt a message |
| 3) Decrypt a message |
| 4) Quit |
-------------------------------
Option: 3
Input: khoor#zruog
Output: hello world
-------------------------------
| 1) Change Shift (default 3) |
| 2) Encrypt a message |
| 3) Decrypt a message |
| 4) Quit |
-------------------------------
Option: 4