Шифр Цезаря - ошибка в коде - C (СИ)
Формулировка задачи:
Добрый день
похожих вариантов задания было много, но не нашла ответа на свой вопрос. Как все таки доделать что бы была шифровка и расшифровка информации?
запись и вывод изменю нормально получается, а в шифровке какая-то абракадабра получается.
ЗАДАНИЕ: Составить программу, реализующую функции указанного ниже меню. Выполнить функциональное разбиение программного кода.
Меню программы:
1 – Сформировать с клавиатуры строку и записать в файл (строка может содержать пробелы);
2 – Считать строку из файла и распечатать;
3 – Зашифровать строку и записать в файл;
4 – Расшифровать строку и записать в файл;
5 – Выход.
Каждая буква меняется на следующую по часовой стрелке в алфавите букву, буква "я" остается без изменения.
#include <conio.h>
#include <stdio.h>
#include <locale.h>
#include <string.h>
#include <stdlib.h>
#include <process.h>
#include <windows.h>
#include <malloc.h>
#define RUS 32
void vvod(char*); //ввод данных
void vivod (char*); //вывод на экран содержимого файла
void shifr ();
void deshifr();
void main ()
{ setlocale(LC_CTYPE, "Russian");
SetConsoleCP(1251);
SetConsoleOutputCP(1251);
system ("cls");
fflush(stdin);
char *C=new char[100];
int menu=0;
while (1)
{
int k=0;
menu=0;
system("cls");
puts("Выберите пункт меню:");
puts("1-Записать строку в файл");
puts("2-Считать строку из файла и распечатать");
puts("3-Зашифровать строку и записать в файл");
puts("4-Расшифровать строку и записать в файл");
puts("5-Выход");
scanf_s("%d", &menu);
switch (menu)
{
case 1: vvod(C); break;
case 2: vivod(C); break;
case 3: shifr(); break;
case 4: deshifr(); break;
case 5: exit(0);
default: system("cls");
fflush(stdin);
puts("Неверный выбор, нажмите любую клавишу для возврата в меню");
_getch();
}}
_getch();}
void vvod(char *C)
{
system("cls");
FILE *f1;
system("cls");
char *C1= new char [100];
f1=fopen("f1.txt","w");
if ((C1!=0)&&(f1!=0))
{
printf ("Введите символы:\n");
fflush (stdin);
fgets(C1,100,stdin);
fputs (C1,f1);
printf ("Записано в файл \n");
fclose (f1);
delete [] C1;
_getch();
}
}
void vivod (char *C)
{FILE *f1;
system("cls");
char *C1= new char [100];
f1=fopen("f1.txt","r");
if ((C!=0)&&(f1!=0))
{printf ("Содержимое текстового файла:\n");
fgets (C,100,f1);
puts(C);
fclose(f1);
delete [] C;
_getch();}}
void shifr ()
{
FILE *f1;
system("cls");
fflush(stdin);
char* str1=new char[100];
char* str2=new char[100];
f1=fopen("f1.txt","r+");
while (!feof(f1))
{int flag;
int n=1;
int j=0;
fgets(str1,100,f1);
for (int i=0; i<strlen(str1);i++)
{if ((*(str1+i))>='А' && (*(str1+i))<'Я')
{*(str2+j)=*(str1+i)+(n% RUS);}
if (*(str1+i)>'Я') *(str2+j)='А'+(*(str1+i))-'Я'-1;
fprintf (f1, "c%", str2);
flag=1;
}
for (int i=0; i<strlen(str1);i++)
if (*(str1+i)>='а' && (*(str1+i))<'я')
{
(*(str2+j))=*(str1+i)+(n% RUS);
if (*(str1+i)>'я') *(str2+j)='а' + ((*(str1+i))- 'я') - 1;
{fprintf (f1, "%c", str2);
flag = 1;
}
}
if (!flag) fprintf (f1, "%c", str2);
//str2 = getc(f1);
printf_s ("zashifr stroka:\n");
puts(str2);
fputs(str2,f1);
fclose(f1);
delete str1;
delete str2;
_getch();}
}
void deshifr()
{
FILE *f1;
system("cls");
fflush(stdin);
char* str2=new char[100];
char* str3=new char[100];
f1=fopen("f1.txt","r+t");
while (!feof(f1))
{
int flag;
int n=1;
int j=0;
fgets(str2,100,f1);
for (int i=0; i<strlen(str2);i++)
if ((*(str2+i))>='А' && (*(str2+i))<='Я')
{*(str3+j)=*(str2+i)-(n% RUS);}
for (int i=0; i<strlen(str2);i++)
if (*(str2+i)<'Я') *(str3+j)='Я'-('А'-(*(str2+i))+1);
fprintf (f1, "c%", str2);
flag=1;
for (int i=0; i<strlen(str2);i++)
if (*(str2+i)>='а' && (*(str2+i))<='я')
{
(*(str3+j))=*(str2+i)-(n % RUS);
if (*(str2+i)<'а') *(str3+j)='я' - ('а'-(*(str2+i))) +1;
{fprintf (f1, "%c", str3);
flag = 1;
}
}
if (!flag) fprintf (f1, "%c", str2);
//str2 = getc(f1);
/*printf_s ("zashifr stroka:\n");*/
fputs(str2,f1);
fclose(f1);
delete str2;
delete str3;
_getch();}
}Решение задачи: «Шифр Цезаря - ошибка в коде»
textual
Листинг программы
#include <stdio.h>
#include <ctype.h>
#include <string.h>
/* Константы для смещения и количество символов в алфавите */
#define VAL 3
#define ALF 26
/* Прототипы функций зашифровки и расшифровки */
void encrypt(char * str);
void decrypt(char * str);
/* Используется массив функций */
void (*select[])(char *str)={encrypt,decrypt};
int main(void)
{
/* Переменные для выбора в меню и строковый массив */
int mode;
char src[255];
puts("Welcome! Please select mode: 0-encypt, 1-decrypt, any key - exit");
scanf("%d",&mode);
while (mode>=0 && mode<2)
{
puts("Enter string:");
/* В циклах иногда не успевает сработать запрос ввода с клавиатуры. Для нормализации
* используется fflush(stdin) */
fflush(stdin);
gets(src);
(*select[mode])(src);
puts("---------------------------------------------------------");
printf("%s%s\n","Result: ",src);
puts("---------------------------------------------------------");
puts("Please select mode: 0-encypt, 1-decrypt, any key - exit");
scanf("%d",&mode);
}
system("PAUSE");
return 0;
}
void encrypt(char *str)
{
/* Собственно мой быдлокод-алгоритм шифровки. В цикле, до тех пор, пока не достигнут конец строки двигаемся
* по строке. Если встречен пробел или другой знак, ничего не делаем. Иначе, если символ расположен менее чем
* за (Z-3 буквы), то сдвигаем на три. В противном случае, вычитаем разницу между числом букв в алфавите и смещением)
* Условный оператор ? сделан для различения заглавных и простых букв. Если введена цифра проделываем тоже самое, за последнюю
* цифру принимая 9 (9-3), за начальную 0(разница между количеством чисел (их всегда 10) и смещением).
* Аналогичный процесс происходит в расшифровке. */
int i;
for (i=0;str[i]!='\0';i++)
{
if (isalpha(str[i]))
{
if (str[i]<= (islower(str[i]) ? ('z'-VAL) : ('Z'-VAL)) ) str[i]+=VAL;
else str[i]-=(ALF-VAL);
}
if (isdigit(str[i]))
{
if (str[i]<= ('9'-VAL)) str[i]+=VAL;
else str[i]-=(10-VAL);
}
}
}
void decrypt(char *str)
{
int i;
for (i=0;str[i]!='\0';i++)
{
if (isalpha(str[i]))
{
if (str[i]>= (islower(str[i]) ? ('a'+VAL) : ('A'+VAL))) str[i]-=VAL;
else str[i]+=(ALF-VAL);
}
if (isdigit(str[i]))
{
if (str[i]>=('0'+VAL)) str[i]-=VAL;
else str[i]+=(10-VAL);
}
}
}
Объяснение кода листинга программы
- Программа использует шифр Цезаря для шифрования и расшифровки текстовых данных.
- Входные данные вводятся пользователем с клавиатуры, а затем выводятся на экран.
- Программа предлагает пользователю выбрать режим работы: шифрование, расшифровка или выход из программы.
- Для шифрования и расшифровки используется массив функций, который содержит адреса функций шифрования и расшифровки.
- В функции main() происходит основной цикл программы, который повторяется до тех пор, пока пользователь не введет неправильный номер режима или не отправит сигнал на выход из программы.
- В функции encrypt() происходит шифрование входной строки, а в функции decrypt() - расшифровка.
- Шифрование и расшифровка основаны на сдвиге символов в алфавите на фиксированное количество позиций.
- Если символ является буквой, то он сдвигается на три позиции вперед в шифровании и на три позиции назад в расшифровке.
- Если символ является цифрой, то он сдвигается на количество позиций, равное значению шифра Цезаря, вперед в шифровании и на количество позиций, равное разнице между количеством цифр и значением шифра Цезаря, в расшифровке.
- В обоих функциях используется цикл, который проходит по каждому символу входной строки.
- В обоих функциях используются условные операторы для обработки заглавных и строчных букв и цифр.