2013-08-20 68 views
0

我制作了一个程序,用vigenere密码对消息进行加密和解密。在文件中打印的额外字符

在对文本进行加密或解密时,会在其中打印一些额外的垃圾值。

它从一个名为input.txt和输出文件输入到output.txt,你必须写在input.txt文件的消息,并在运行,你必须给一个键(用字母数字字符的字)。

为什么会发生这种情况?

的代码如下:

#include<stdio.h> 
#include<string.h> 
#include<stdlib.h> 
#include<ctype.h> 



int Encrypt(char key[])   // CODE FOR ENCRYPTION 
{ 
    int sz = 0, i; 
    FILE *ifp, *ofp; 
    ifp = fopen("input.txt", "r"); 
    char *buffer; 
    char outputFilename[] = "output.txt"; 


    if (ifp == NULL) 
    { 
     fprintf(stderr, "Cant open input file\n"); 
     exit(1); 
    } 


    fseek(ifp, 0, SEEK_END); 
    sz = ftell(ifp); 

    // printf("%d",sz); 

    fseek(ifp, 0, SEEK_SET); 


    /* allocate memory for entire content */ 
    buffer = (char *)malloc(sizeof(char) * sz); 
    if (!buffer) 
     fclose(ifp), fputs("memory alloc fails", stderr), exit(1); 

    /* copy the file into the buffer */ 
    if (1 != fread(buffer, sz, 1, ifp)) 
     fclose(ifp), free(buffer), fputs("entire read fails", stderr), exit(1); 


    ofp = fopen(outputFilename, "w"); 

    if (ofp == NULL) 
    { 
     fprintf(stderr, "Can't open output file !\n"); 
    } 
    // fprintf(ofp,"%s",buffer); 

    int j = 0; 
    for (i = 0; i < strlen(buffer); i++) 
    { 
     if (j > strlen(key) - 1) 
      j = 0; 
     if (buffer[i] >= 65 && buffer[i] < 91) 
     { 

      int c = ((((buffer[i] - 65) + ((key[j] - 65) % 26))) % 26) + 65; 
      fprintf(ofp, "%c", c); 

     } 
     else if (buffer[i] >= 97 && buffer[i] < 123) 
     { 
      int c = ((((buffer[i] - 97) + ((key[j] - 65) % 26))) % 26) + 97; 

      fprintf(ofp, "%c", toupper(c)); 

     } 
     else 
     { 
      fprintf(ofp, "%c", buffer[i]); 
      continue; 
     } 
     j++; 
    } 
    printf("\n"); 

    fclose(ifp); 
    fclose(ofp); 

    return 0; 
} 

int Decrypt(char key[])   // CODE FOR DECRYPTION 
{ 

    int sz = 0, i; 
    FILE *ifp, *ofp; 
    ifp = fopen("output.txt", "r"); 
    char *buffer; 
    char outputFilename[] = "output2.txt"; 


    if (ifp == NULL) 
    { 
     fprintf(stderr, "Cant open input file\n"); 
     exit(1); 
    } 


    fseek(ifp, 0, SEEK_END); 
    sz = ftell(ifp); 

    // printf("%d",sz); 

    fseek(ifp, 0, SEEK_SET); 

    /* allocate memory for entire content */ 
    buffer = (char *)malloc(sizeof(char) * sz); 
    if (!buffer) 
     fclose(ifp), fputs("memory alloc fails", stderr), exit(1); 

    /* copy the file into the buffer */ 
    if (1 != fread(buffer, sz, 1, ifp)) 
     fclose(ifp), free(buffer), fputs("entire read fails", stderr), exit(1); 


    ofp = fopen(outputFilename, "w"); 

    if (ofp == NULL) 
    { 
     fprintf(stderr, "Can't open output file !\n"); 
    } 
    // fprintf(ofp,"%s",buffer); 

    int j = 0; 
    for (i = 0; i < strlen(buffer); i++) 
    { 
     if (j > strlen(key) - 1) 
      j = 0; 
     if (buffer[i] >= 65 && buffer[i] < 91) 
     { 
      if (buffer[i] > key[j]) 
      { 
       int c = 
        ((((buffer[i] - 65) - ((key[j] - 65) % 26))) % 26) + 65; 
       fprintf(ofp, "%c", tolower(c)); 
      } 
      else 
      { 
       int c = ((((buffer[i] - key[j]) + 26)) % 26) + 65; 
       fprintf(ofp, "%c", tolower(c)); 
      } 
     } 
     else if (buffer[i] >= 97 && buffer[i] < 123) 
     { 
      int c = ((((buffer[i] - 97) - ((key[j] - 65) % 26))) % 26) + 97; 

      fprintf(ofp, "%c", tolower(c)); 

     } 
     else 
     { 
      fprintf(ofp, "%c", buffer[i]); 
      continue; 
     } 
     j++; 
    } 
    printf("\n"); 

    fclose(ifp); 
    fclose(ofp); 

    return 0; 
} 

void main() 
{ 
    int ch; 
    char key[20]; 
    a:printf("0.Exit the Menu\n1.Encrypt\n2.Decrypt\n"); 
    printf("Enter your choice\n"); 
    scanf("%d", &ch); 


    switch (ch) 
    { 

    case 0: 
     printf("Goodbye\n"); 
     break; 

    case 1: 
     printf 
      ("-----------------------------Welcome to the encryption zone---------------------\n"); 
     printf("Enter the key to be used\n"); 
     scanf("%s", key); 

     Encrypt(key); 
     break; 

    case 2: 
     printf 
      ("-----------------------------Welcome to the decryption zone---------------------\n"); 
     printf("Enter the key to be used\n"); 
     scanf("%s", key); 

     Decrypt(key); 
     break; 

    default: 
     printf("Enter the correct choice\n"); 
     goto a; 
     break; 

    } 
} 
+2

镜头在黑暗中:你忘了空终止? –

+0

在这种情况下不要使用'goto',使用循环。 –

+0

你真的应该将第二个和第三个参数的位置切换到'fread'和'fwrite'。第二个是每个元素的大小,第三个是元素的数量。您当然也必须更改返回值的检查。 –

回答

3

当你分配和复制在这里

buffer = (char *)malloc(sizeof(char) * sz); 
if (!buffer) 
    fclose(ifp), fputs("memory alloc fails", stderr), exit(1); 

/* copy the file into the buffer */ 
if (1 != fread(buffer, sz, 1, ifp)) 
    fclose(ifp), free(buffer), fputs("entire read fails", stderr), exit(1); 

你分配的缓冲区sz字节,并复制sz字节,但是你没有为空终止符留下空间。因此,当您检查strlen(buffer)并稍后进行加密时,您将进入您未分配的内存。

要解决这个问题,要么必须为'\0'分配一个额外的字节,要么复制一个更少的字符并在最后加上'\0'

+0

我发现这个问题在ubuntu(gcc编译器)中不会发生,但是在windows上的代码块中编译时会出现这个问题 –

+1

关于这个问题的是,一旦运行到未分配的内存中,您立即遇到未定义的行为。你有没有试过像'valgrind'这样的内存检查器来运行你的程序?如果它返回任何内存错误,那并不是说你没有问题,而是你很幸运,而未定义的行为恰好不会导致一次崩溃。 –

0

错误的长度计算。

正如@丹尼斯·孟提到的,strlen(缓冲区)可能(* 1)会超过您分配的缓冲区的末端。您的malloc()没问题。推荐的解决方案是不同的。而不是套结上一个NUL字符,2个for循环

for (i = 0; i < strlen(buffer); i++) 

改变

for (i = 0; i < sz; i++) 

这不仅会解决这个问题,它的运行速度更快,你将不再执行strlen(buffer)sz倍。

* 1如果您的文件包含NUL字符,它不会那么远。如果它确实超过了buffer的结尾,那么UB就停止了。