C - 使用strcpy()和strncpy()

时间:2016-12-01 13:08:13

标签: c cs50

我在edx上学习CS50课程,我应该在C中编写一个使用Vigenere Cipher加密消息的代码。而我做到了。但问题是我一直在缓冲区溢出。

如果我使用短字符串,例如" Meet",它可以正常工作。但是,如果我使用更长的字符串,比如"在上午11点在公园见我,#124;我得到缓冲区溢出。

如果我使用strcpy()argv[1]中传递的密钥复制到另一个变量(让我们说k)和原始邮件(msg)到加密消息的变量(encMsg),然后它删除我在k中的内容。 如果我再次使用strcpy()argv[1]的值再次复制到k,我会在encMsg连接两个字符串时出现缓冲区溢出。

如果我使用strccpy(),则不会删除k的内容,但会溢出并连接encMsg上的两个字符串。

当我使用GetSting()(来自cs50.h);

时,这一切都会发生

如果我使用fgets(),那么我会得到' \ n'在msg的最后,然后必须添加一个if来放置一个' \ 0'那个' \ n'是,这解决了我的问题,但我想知道是否有人能解释为什么所有这一切都会发生。

这是我的代码:

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


int main(int argc, char *argv[])
{
    if (argc != 2) //Checks if number of command-line arguments is valid
    {
        printf ("usage: ./caesar + key \n");
        return 1;    
    }

    char k[strlen(argv[1])];
    //strcpy(k, argv[1]);         //Saves argument into a string
    strncpy(k, argv[1], strlen(argv[1]));

    for (int x = 0; x < strlen(k); x++) 
    {
        if (k[x] < 65 || (k[x] > 90 && k[x] < 97) || k[x] > 122) //Checks if there is any non-alphabetical character in key
        {
            printf ("key must contain only alphabetical characters \n");
            return 1;    
        }
    }

    //printf("Inform the message you want to encrypt: \n");
    string msg = GetString();
    //char msg[255];
    //fgets(msg, 255, stdin);

    char encMsg[strlen(msg)];
    //strcpy(encMsg, msg);
    strncpy(encMsg, msg, strlen(msg));

    //strcpy(k, argv[1]); 

    int y = 0;
    for (int x = 0; x < strlen(msg); x++) 
    {
        //if(msg[x] == '\n') msg[x] = '\0';
        if (msg[x] < 65 || (msg[x] > 90 && msg[x] < 97) || msg[x] > 122) encMsg[x] = msg[x];
        else if ((msg[x] + (k[y] - 97 ) > 90 && msg[x] + (k[y] - 97 ) < 97) || msg[x] + (k[y] - 97 ) > 122)
        {
            encMsg[x] = msg[x] + (k[y] - 97) - 26;
            y++;
        }
        else 
        {
            encMsg[x] = msg[x] + (k[y] - 97);
            y++;
        }
        if (y >= strlen(k)) y = 0;
    }

    printf("key     =    %s\n", k);
    printf("msg     =    %s\n", msg);
    printf("encMsg  =    %s\n", encMsg);


    return 0;
}

1 个答案:

答案 0 :(得分:4)

这种代码风格:

char k[strlen(argv[1])];

没有为终止'\0'字符留出空间。它应该是

char k[strlen(argv[1]) + 1 ];

正如评论中指出的那样,代码如

strncpy(k, argv[1], strlen(argv[1]));

将无法正确终止目标字符串。每the standard for strncpy()

  

如果s2指向的数组是一个短于n的字符串   字节,NUL字符应附加到数组中的副本   由s1指向,直到写入n个字节为止。

由于目标字符串短于n,因此只复制源字符串中的非NUL字节,因为n为它们。

正确的代码可能是

strncpy(k, argv[1], 1 + strlen(argv[1]));