Ваша программа рушится из-за этой линии в функции 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
Почему вы вычитанием '1' из' buf'? Это обращается за пределами буфера, что является неопределенным поведением. – Barmar
Надеюсь, что это была просто опечатка, и вы намеревались делать 'for (i = 0; i <(strlen (buf) -1); ++ i)', но это должно быть просто 'for (i = 0; i < strlen (buf); ++ i) ' – Anty
Когда я шифрую и расшифровываю свою строку, я не хочу также шифровать и расшифровывать символы новой строки или нулевые. – Boo92