用C覆盖文件中的行,奇怪的输出

时间:2012-11-16 00:20:52

标签: c file io fseek ftell

我正在尝试逐行浏览文件(每行不超过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 个答案:

答案 0 :(得分: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 char s,无论你读入的行多长,因此大多数时候,tmp缓冲区中没有0字节,因此{{ 1}}经常写入至少50个字节,其中一些与该位置的文件中的内容无关,并且超出缓冲区,调用未定义的行为并可能导致崩溃。

您应该检查循环中的终止0字节,甚至可能在换行符停止是个好主意。

fputs

注意:循环体更简单为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; }

答案 1 :(得分:2)

尝试使用GDB在加密时调试程序。

编译: gcc -g -Wall YOURPROGRAM.cxx

运行gdb: gdb YOURPROGRAM.cxx

设置BreakPoint:

第3行中断:break 3

调试您的计划:run

您可以使用stepnext逐步执行每行代码,并使用print VARIABLENAME在每个点打印出变量。它是一个功能强大的程序,在调试方面非常有用。

答案 2 :(得分:1)

您可能不应该使用面向行的fgets()fputs(),因为您可以在加密输出数据和解密输入数据中获得NUL '\0'个字符(使用fread()fwrite()。确保您处理正确数量的字符; fgets()可能不会返回49个字符和一个NUL;该行可能会更短,并且你还是不想处理NUL。