Перезапись строк в файле на C, странный вывод

Я пытаюсь пройтись по файлу построчно (каждая строка не более 50 символов), сдвинуть каждый символ на 10 или -10 (для шифрования и дешифрования), а затем распечатать сдвинутую строку там, где была старая строка. Но я получаю действительно забавный вывод.

вот код:

#include <stdio.h>
int main(void){
    FILE *fp;
    fp=fopen("tester.csv","r+");
    Encrypt(fp);      // I call decrypt here when I test it.
    fclose(fp);
}

int Encrypt(FILE *fp){
    int offset=10;
    Shift(fp, offset);
}
int Decrypt(FILE *fp){
    int offset= -10;
    Shift(fp, offset);
}
int Shift(FILE *fp, int offset){
    char line[50],tmp[50], character;
    long position;
    int i;
    position = ftell(fp);
    while(fgets(line,50,fp) != NULL){
        for(i=0;i<50;i++){
            character = line[i];
            character = (character+offset)%256;
            tmp[i] = character;                 
        }
        fseek(fp,position,SEEK_SET);
        fputs(tmp, fp);
        position = ftell(fp);
    }
}

так что если tester.csv изначально читает

this, is, a, test

запуск программы производит

~rs}6*s}6*k6*~o}~
























êñv[    ‰

this, is, a, test

3 ответа

Решение
fputs(tmp, fp);

fputs записывает байты до завершающего 0 байта.

while(fgets(line,50,fp) != NULL){
    for(i=0;i<50;i++){
        character = line[i];
        character += offset;
        tmp[i] = character;                 
    }

тебе смена 50 chars, независимо от того, какой длины была строка, в которой вы читали, и, следовательно, большую часть времени, в байте нет 0-байтов. tmp буфер, таким образом fputs часто записывает не менее 50 байтов, некоторые из которых не имеют ничего общего с тем, что было в файле в этом месте, и выходят за пределы буфера, что вызывает неопределенное поведение и может вызвать сбой.

Вы должны проверить завершающий 0-байт в цикле, возможно, даже остановка на новой строке - хорошая идея.

while(fgets(line,50,fp) != NULL){
    for(i = 0; i < 50 && line[i] != 0 && line[i] != '\n'; i++){
        character = line[i];
        character += offset;
        tmp[i] = character;                 
    }

Примечание: тело цикла будет проще line[i] += offset;,

Попробуйте использовать GDB для отладки вашей программы, так как она шифруется.

Компилировать с:gcc -g -Wall YOURPROGRAM.cxx

Запустите GDB:gdb YOURPROGRAM.cxx

Установить точку останова:

Перерыв в строке 3: break 3

Отладка вашей программы: run

Вы можете пройти через каждую строку кода, используя step а также nextи распечатывать переменные в каждой точке, используя print VARIABLENAME, Это мощная программа, и она действительно полезна при отладке.

Вы, вероятно, не должны использовать линейно-ориентированные fgets() а также fputs() так как вы могли бы получить NUL '\0' символы в выходных данных о шифровании, а во входных данных о дешифровании (и переводы строк будут. Использование fread() а также fwrite(), Убедитесь, что вы обрабатываете правильное количество символов тоже; fgets() может не возвращать 49 символов и NUL; строка может быть короче, и вы все равно не хотите обрабатывать NUL.

Другие вопросы по тегам