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;

    }
}
4

2 回答 2

3

When you are allocating and copying here

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);

you've allocated sz bytes in buffer, and copied sz bytes, but you didn't leave room for the null terminator. Hence, when you check strlen(buffer) and encrypt later, you're going off into memory you didn't allocate.

To fix this, either you have to allocate one extra byte for the '\0', or you copy over one less and tack on the '\0' at the end.

于 2013-08-20T17:09:25.383 回答
0

长度计算错误。

正如@Dennis Meng 所提到的, strlen(buffer)可能(*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。

于 2013-08-20T22:04:09.213 回答