C Цезарь Cipher Функция вызова не ведет себя, как ожидалось - PullRequest
0 голосов
/ 11 ноября 2018

Я пытаюсь создать программу, которая будет выполнять простой шифр Цезаря в текстовом файле с одиночными строками без пробелов в каждой строке. По какой-то причине моя функция шифрования не смещает текст, и я обрезаю строки различной длины символов. Можете ли вы увидеть, где я запутался с вызовом функции в цикле while?

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>

#define FILE_NAME "./infile.txt"

void caeser (char * ch, int shift)
{
    int i = 0;
    int len = strlen(ch);

    while (ch[i] < len)
    {
        if (islower(ch[i]))
            ch[i] = ((ch[i] - 'a' + shift) % 26 + 'a');
        else
            ch[i] = ((ch[i] - 'A' + shift) % 26 + 'A');
    }i++;

    printf("Caesar Cipher = %s\n", ch);

}

int main(void)
{
    char *  c = malloc( sizeof(char) * 1000);


    FILE* fp = fopen (FILE_NAME, "r");
    if (fp == NULL)
    {
        printf("Can't open %s\n", FILE_NAME);
        exit(EXIT_FAILURE);
    }

    while(fgets(c, sizeof(c), fp) != 0)
    {
        printf("%s\n", c);
        caeser(c, 1);
    }

    fclose(fp);
    fp = NULL;
    return 0;
}

Ответы [ 2 ]

0 голосов
/ 12 ноября 2018

Обратите внимание, что fgets может возвращать "символ новой строки" ('\n') в конце строки. Вы можете удалить символ новой строки из буфера.

Если в строке есть пробелы, символ '\n' или любые символы, не входящие в диапазон A-Z или a-z, игнорируйте эти символы, поскольку они не соответствуют логике для шифра caeser.

char *  c = malloc( sizeof(char) * 1000);
while(fgets(c, sizeof(c), fp) != 0) { ... }

Как уже упоминалось в комментариях, c является указателем, а sizeof(c) обычно составляет 4 или 8 в этом случае. Таким образом, вы говорите fgets читать максимум 4 или 8 байтов. Но каждая строка в файле может быть намного длиннее. Если бы вы объявили, скажем, char c[1000];, тогда sizeof(c) будет 1000. В противном случае не используйте оператор sizeof здесь.

while(i < len) {...}i++;

Вы хотите добраться до конца строки и увеличивать ее внутри цикла, поэтому измените условие на:

 while(i < len) {... i++;}

Наконец, c или ch обычно используется для обозначения символа. Это неформально и на самом деле не имеет значения, но более понятно использовать buf или str, если вы объявляете строку.

Пример:

void caeser(char *buf, int shift)
{
    int i = 0;
    int len = strlen(buf);
    while(i < len)
    {
        char c = buf[i];
        if(c >= 'a' && c <= 'z')
            buf[i] = (c - 'a' + shift) % 26 + 'a';
        else if(c >= 'A' && c <= 'Z')
            buf[i] = (c - 'A' + shift) % 26 + 'A';
        //else, do nothing if chararacter is not between a-z or A-Z 
        i++;
    }
}

int main(void)
{
    FILE* fp = fopen(FILE_NAME, "r");
    if(fp == NULL)
    {
        printf("Can't open %s\n", FILE_NAME);
        exit(EXIT_FAILURE);
    }

    int buf_size = 1000;
    char *buf = malloc(sizeof(char) * buf_size);

    while(fgets(buf, buf_size, fp))
    {
        //optional: remove the new line character if any
        int len = strlen(buf);
        if(len && buf[len - 1] == '\n')
            buf[len - 1] = 0;

        printf("plain : %s\n", buf);
        caeser(buf, 1);
        printf("cipher: %s\n\n", buf);
    }

    //free the buffer allocated with malloc
    free(buf);
    fclose(fp);
    return 0;
}
0 голосов
/ 11 ноября 2018

Я сделал несколько изменений в вашем коде и выделил их жирным шрифтом.

Массив начинается с 0 и заканчивается символом n-1.

вы проверили, если ch [i]

в каждой итерации вам нужно увеличивать i на 1., чтобы вы могли получить следующий символ.

для лучшего дизайна попробуйте добавить формат для печати в основную функцию вместо печати в функции. Вы должны вернуть указатель на строку и распечатать его в main.

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>

#define FILE_NAME "./infile.txt"

void caeser (char * ch, int shift)
{
    int i = 0;
    int len = strlen(ch);

    while (**i < len-1**)
    {
        if (islower(ch[i]))
        {
            ch[i] = ((ch[i] - 'a' + shift) % 26 + 'a');
            **i++;**
        }
        else
        {
            ch[i] = ((ch[i] - 'A' + shift) % 26 + 'A');
            **i++;**
        }
    }
    printf("Caesar Cipher = %s\n", ch);
}

int main(void)
{
    char *  c = malloc( sizeof(char) * 1000);


    FILE* fp = fopen (FILE_NAME, "r");
    if (fp == NULL)
    {
        printf("Can't open %s\n", FILE_NAME);
        exit(EXIT_FAILURE);
    }

    while(fgets(c, sizeof(c), fp) != 0)
    {
        printf("%s\n", c);
        caeser(c, 1);
    }

    fclose(fp);
    fp = NULL;
    return 0;
}
...