Простой алгоритм шифрования / дешифрования, вызывающий EOF

Я играл с очень простым алгоритмом шифрования / дешифрования, подобным этому;

#include  #include  #define BUFFESIZE 1024 int main(int argc, char *argv[]) { int keylen = 0; char *key = argv[1]; char *buffer = NULL; size_t buffersize = 0; size_t nbytes = 0; size_t nread; int i = 0; while(*key++ != 0) keylen++; key = argv[1]; do { buffersize+=BUFFESIZE; buffer = realloc(buffer, buffersize); nread = fread(buffer+nbytes, 1, BUFFESIZE, stdin); nbytes+=nread; } while (nread > 0); for(i=0; i<nbytes; i++) { putchar(buffer[i] ^ key[i % keylen]); } return 0; } 

Ключ Encyption – это первый аргумент командной строки для программы. Я ожидаю, что это должно получить исходный файл, когда он зашифрован / расшифрован с помощью того же ключа. Тем не менее, я иногда получаю только небольшой объем файла, если я его зашифрую / расшифрую. Я предполагаю, что алгоритм добавляет символ управления EOF в середине файла.

Как я могу обойти эту проблему?

Я скомпилировал это с помощью MinGW gcc 4.8.1 на Windows XP. Если вам интересно, вы можете найти образец входного файла, демонстрирующий проблему в истории изменений этого вопроса .

Ну, ваш код работает для меня в Linux (скомпилирован с GCC 4.8.2), даже используя ваш образец ввода и ключ. Это говорит о том, что проблема специфична для Windows – скорее всего, это вызвано тем, что stdin и stdout находятся в текстовом режиме по умолчанию. (В Linux и других Unix-ish системах обычно нет разницы между текстовым режимом и двоичным режимом, поэтому такие проблемы не отображаются там.)

Чтобы исправить это, вам нужно установить stdin и stdout в двоичный режим . Стандартный способ сделать это , начиная с C99 , будет следующим:

 freopen(NULL, "rb", stdin); freopen(NULL, "wb", stdout); 

но, увы, в соответствии с ответами в streamе, который я связал выше, библиотека Windows C не поддерживает эту функцию C99 , поэтому вам нужно снова _setmode() нестандартного _setmode() :

 _setmode(_fileno(stdin), _O_BINARY); _setmode(_fileno(stdout), _O_BINARY); 

Если вы хотите оставаться портативным, вы всегда можете использовать какой-то условный код, например, так (предупреждение: на самом деле не протестировано в Windows!):

 #if __STDC_VERSION__ >= 199901L #define binmode(fh, w) freopen(NULL, ((w) ? "wb" : "rb"), (fh)) /* C99 */ #elif _MSC_VER >= 1200 #include  #include  #define binmode(fh, w) _setmode(_fileno(fh), _O_BINARY) /* MSVC 6.0+ */ #elif defined(__unix__) || (defined(__APPLE__) && defined(__MACH__)) #define binmode(fh, w) /* Unix-ish, just do nothing */ #else #error Not sure how to define binmode() on this platform #endif binmode(stdin, 0); binmode(stdout, 1); 

Или, конечно же, вы можете просто обойти всю проблему, открыв свои собственные входные и выходные файлы (в двоичном режиме) вместо использования stdin и stdout .