C - Странные символы появляются в строке - PullRequest
1 голос
/ 12 апреля 2019

Я пытаюсь закодировать простой Цезарь-Шифр в C. Я создаю функцию шифрования, которая получает строку (char *, текст для шифрования) и целое число (ключ).

В функции я выделяю память для пустой строки, которая будет получать сдвинутые символы.Затем я перебираю каждый символ в исходной строке и спрашиваю, является ли она буквой char (Az) или нет.Если это так, он смещается в соответствии с ключом.Если это не так, он просто повторяет текущий символ.Проблема в том, когда такие символы, как!,?,.или даже пробел появляется в конце, он добавляет немного «?»к этому.Я поместил операторы printf, и я предполагаю, что происходит неопределенное поведение, но я не могу понять это сам.Я надеюсь, что кто-то может помочь мне.Ниже приведен код, который я написал, и странные результаты.

char* encrypt(char* entry, int key) {
    int i = 0;
    key = key % 26;
    char * tmp = (char *)malloc(strlen(entry));
    if (!tmp) {
        printf("Error during allocation.\n");
        return entry;
    }
    //memset(tmp, 0, 1); // Tried with and without it.
    char t;
    while ((t = *(entry + i))) {
        printf("Current letter: %c\n",*(entry+i));
        if ((t >= 65 && t <= 90) || (t >= 97 && t <= 122)) { //is letter 
            *(tmp + i) = t + key > 90 ? t + key - 26 : t + key;
        }
        else { //isnt letter
            printf("No letter char appeared. Code = %d\n",t); 
            *(tmp+i) = t;
        }
        printf("tmp letter: %c\n",*(tmp+i));
        printf("current tmp: %s\n----------------\n",tmp);
        i++;
    }
    printf("final tmp = %s\n",tmp);
    entry = tmp;
    free(tmp);
    return entry;
}

Вызов функции: encrypt («ПРИВЕТ! КАК ВЫ ?!», 13);

Ожидается (окончательно)) результат: URYYB!UBJ NER LBH ?!Собственно (окончательный) результат: URYYB!UBJ NER LBH?!?(иногда добавляется еще «?»)

Отладка операторов printf:

Current letter: H
tmp letter: U
current tmp: U
----------------
Current letter: E
tmp letter: R
current tmp: UR
----------------
...
----------------
Current letter: !
No letter char appeared. Code = 33
tmp letter: !
current tmp: URYYB!
----------------
Current letter:  
No letter char appeared. Code = 32
tmp letter:  
current tmp: URYYB! ? // <<< It added a strange character to the string
----------------
Current letter: H
tmp letter: U
current tmp: URYYB! U // <<< '?' strange character gone
----------------
Current letter: O
tmp letter: B
current tmp: URYYB! UB
----------------
Current letter: W
tmp letter: J
current tmp: URYYB! UBJ // (I)
----------------
Current letter:  
No letter char appeared. Code = 32
tmp letter:  
current tmp: URYYB! UBJ // This time, space didn't raise a strange char after (I)
----------------
...
----------------
Current letter:  
No letter char appeared. Code = 32
tmp letter:  
current tmp: URYYB! UBJ NER ? // Missed me? I'm back
----------------
Current letter: Y
tmp letter: L
current tmp: URYYB! UBJ NER L // ...And gone again
----------------
Current letter: O
tmp letter: B
current tmp: URYYB! UBJ NER LB
----------------
Current letter: U
tmp letter: H
current tmp: URYYB! UBJ NER LBH???
----------------
Current letter: ?
No letter char appeared. Code = 63
tmp letter: ?
current tmp: URYYB! UBJ NER LBH???
----------------
Current letter: !
No letter char appeared. Code = 33
tmp letter: !
current tmp: URYYB! UBJ NER LBH?!?
----------------
final tmp = URYYB! UBJ NER LBH?!?

У кого-нибудь есть объяснение этому случаю?GCC информация о моей системе:

gcc -v
Configured with: --prefix=/Library/Developer/CommandLineTools/usr --with-gxx-include-dir=/usr/include/c++/4.2.1
Apple LLVM version 9.1.0 (clang-902.0.39.1)
Target: x86_64-apple-darwin17.5.0
Thread model: posix
InstalledDir: /Library/Developer/CommandLineTools/usr/bin

1 Ответ

0 голосов
/ 13 апреля 2019

tldr;Вы печатаете строки из памяти, которая никогда не была инициализирована.Попробуйте использовать calloc вместо malloc.

. Я думаю, что в вашем примере происходит то, что вам не хватает нулевых байтов для завершения строк.Чтобы понять, что происходит, вы должны рассмотреть следующие две вещи: строки

  1. C заканчиваются нулевыми байтами (\0).Функции, которые работают со строками C, всегда ожидают нулевой байт в конце строки.Если такого терминатора нет, они просто предполагают, что ваша строка еще не завершилась.
  2. malloc не инициализирует выделенную память.Это означает, что printf("%s", malloc(10)); может что-то напечатать или нет.Это зависит от большого числа факторов, поэтому обычно его называют «неопределенным поведением».

Итак, возвращаясь к вашему случаю: вы выделяете tmp, но никогда не инициализируете его нулями.Но это нужно для того, чтобы ваши печатные операторы работали.Так что используйте что-то вроде calloc(1, strlen(entry)+1).(Обратите внимание на +1. Вам нужен еще один байт для ограничителя строки (\0))

Чтобы вы могли понять, что происходит, я бы предложил добавить memset(tmp, 'X', strlen(entry)); послеmalloc -линии.А затем попытайтесь понять вывод.


Примечание: следующее не копирует строку из tmp в entry.

entry = tmp;
free(tmp);
return entry;

Вы просто возвращаете tmp здесь указывает на свободный блок памяти и приводит к недопустимому доступу к памяти вне функции.То, что вы хотите использовать, это memcpy.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...