文件中打印的额外字符

时间:2013-08-20 16:59:16

标签: c file-io cryptography garbage

我制作了一个使用vigenere密码加密和解密邮件的程序。

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

它从名为input.txt的文件输入并输出到output.txt,您必须在input.txt文件中写入消息,并且在运行时您必须提供密钥(a带字母数字字符的单词)。

为什么会这样?

代码如下:

#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 :(得分: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'

答案 1 :(得分:0)

错误的长度计算。

正如@Dennis Meng所提到的,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。