2013-08-20 71 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就停止了。