我正在尝试逐行浏览文件(每行不超过 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);
}
}
所以如果测试.csv最初读取
this, is, a, test
运行程序会产生
~rs}6*s}6*k6*~o}~
êñv[ ‰
this, is, a, test
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
秒,不管你读入的行有多长,因此大多数时候,tmp
缓冲区中没有 0 字节,因此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 ' '
字符,在解密时在输入数据中获取 NUL 字符(换行符将是 .使用fread()
和fwrite()
。确保也处理正确数量的字符; fgets()
可能不会返回 49 个字符和一个 NUL;该行可能更短,并且您无论如何都不想处理 NULL。