2014-01-28 43 views
0

我在写密码程序。程序首先要求用户输入包含8个或更多包含字符和标点符号的字符的密码。密码将无法正确加密(携带太多字符)

后,该方案将通过在中间的密码的第二半移动到前增加一个“+”,然后将第一半附加到端“加密”的密码。

我得到的问题是,每当我输入密码,那就是奇怪的字符它复制的最后一个字符两次,是打破我的程序。我该如何解决?我知道我必须添加一个条件,因为有奇怪的字符,但是它应该包含idk。这里是我的代码:

// write a function to encrypt the password: 
// return a dynamically allocated C string of the exact size (no extra room) with: 
// the last half of the password, the + symbol, and then the first half of the password 
char * encrypt (char pw[]) 
{ 
int exactsize = strlen(pw) + 2; 
char * encPW = new char[exactsize]; 
int mid = exactsize/2; 


strcpy(encPW, pw + mid); 
strcat(encPW, "+"); 
strncat(encPW, pw, exactsize - mid); 

return encPW; 

} 

// write the same (overloaded) function for a C++ String 
char * encrypt (string pw) 
{ 
int exactsize = pw.length() + 2; 
char * encPW = new char[exactsize]; 
int mid = exactsize/2; 

string temp(pw, mid); 
string temp2(pw, 0 ,mid); 
temp = temp + "+" + temp2; 

strcpy(encPW, temp.c_str()); 


return encPW; 
} 

here is the output i am getting and what i am talking about: 
Enter your password: salehrocks93 
add punctuation 
Enter your password: salehrocks93/ 
Valid password format. Encrypting... 

Encrypted password: cks93/+salehroc 

Enter your new password: salehrocks93/ 
New Encrypted password: cks93/+salehro 
1 
Press any key to continue . . . 

当它要求输入密码的第一次加密是重复的C两次

+0

什么是理想的行为时,该密码是奇数的长度?例如,“密码”的加密应该是什么? – crockeea

+0

一些无法回答的观察:1.您的API不平衡:函数分配内存,但需要调用者释放它 - 这是一个不好的做法。 2.你的重载是通过* value *来获得一个'std :: string',这意味着它在被调用时会创建一个本地副本,这使得它成为一个糟糕的设计选择。把它作为一个'const std :: string&'来引用它。 3.'温度=温度+“+” + TEMP2;'想什么,做... – kfsone

+0

@Eric密码的加密应该始终是相同的取密码下半年把它放在第一的前面,在中间添加一个“+”。 – SalehK

回答

1

什么我喜欢这样的问题呢? 穿过它们。我发现它通常有助于绘制出来。好笔'笔和纸调试。如果你不能在纸上搞清楚,你将如何在计算机中弄清楚它? 有这么多的电线!

所以。让我们一步一步通过它。首先,我们需要选择一个虚假的参数来传递它。


为了演示的目的,我们使用C风格的以NULL结尾的字符串“PASSWOR”。如果我画这个阵列,它可能看起来像这样:

['P'].['A'].['S'].['S'].['W'].['O'].['R'] 

好的,现在到你的代码。

char * encrypt (char pw[]) 
{ 
    int exactsize = strlen(pw) + 2; 
    char * encPW = new char[exactsize]; 
    int mid = exactsize/2; 

在这里,我们在你的功能的开始。你声明的变量exactsize使用字符串的长度和幻数。我的猜测是你使用这个神奇的数字来解释NULL终结符和你想添加的'+'。

所以,我们的假论据 “PASSWOR”,我们应该得到的一个的strlen(),使我们的 'exactsize' 。

然后你分配一个字符数组,encPW,作为这个新的'确切'的大小。这里是encPW现在看起来,作为字符

// initial value 
[ 0 ].[ 0 ].[ 0 ].[ 0 ].[ 0 ].[ 0 ].[ 0 ].[ 0 ].[ 0 ] 
// with indices 
    0  1  2  3  4  5  6  7  8 

的数组,那么你声明中旬,我认为我们可以放心地假设意味着中点。这有点棘手,因为你正在参考你的新尺寸确定中间值。但我们坚持使用手头的代码。因为我们的要求是,那么mid应该是4.5。但它是一个整数,所以最终结果是。我们继续。

strcpy(encPW, pw + mid); 

现在你strcpy进入encPW的目的地,从pw + mid开始。 pw + mid给我们一个指向原始字符串的字符'W'的指针。它将复制并包括NULL终止符。

// now what do we have? 
['W'].['O'].['R'].[ 0 ].[ 0 ].[ 0 ].[ 0 ].[ 0 ].[ 0 ] 

然后你追加'+'字符串:

strcat(encPW, "+"); 
// now what do we have? 
[ 'W' ].[ 'O' ].[ 'R' ].[ '+' ].[ 0 ].[ 0 ].[ 0 ].[ 0 ].[ 0 ] 

最后,调用strncat函数(),其中追加NUM字符C风格的字符串, NULL终止符。

您正在告诉它将exactsize - mid个字符写入字符串。由于必要性是9,中间是4,我们正在告诉它写字符。

正如我们在上面看到的,strncat还写入了一个NULL终止符。这是6个字符!但是,正如我们所看到的(通过计算上面的 字符串中的0左侧),在我们将 写入不属于我们的内存之前,只剩下5个字符!

这里的引擎盖下会发生什么(在较高水平)

strncat(encPW, pw, exactsize - mid) 
// strncat tries to write this stuff at the end 
[ 'W' ].[ 'O' ].[ 'R' ].[ '+' ].[ 'P' ].[ 'A' ].[ 'S' ].[ 'S' ].[ 'W' ].[ 0 ] 
                     .^ 
             Uh oh, somebody call the memory police! 

然而,即使我们没有写进去吓人,神秘的内存,该算法仍然出现根本性的缺陷,因为一个我们的角色出现两次!


我对你的问题:什么是中旬?当你宣布它时,你打算如何使用它?

所以现在,我们拿出我们简单的笔和纸修复。


我将如何解决这个问题:

int mid = strlen(pw)/2; 

并为您strncat函数()我会使用

strncat(encPW, pw, mid) 

这解决了一些问题我们。我们用两个例子,“PASSWOR”和“PASSWORD”。

使用“PASSWOR”,中期将是3

PW +中期将'S'(第二S)

所述的strcpy encPW之后将是 “SWOR”

第一的strcat后,这将是 “SWOR +”

strncat(encPW, pw, mid)后,这将是 “SWOR + PAS”。

理想,是吗?

使用“密码”,中期将是4

PW +中旬将'W'

的strcpy encPW之后将是 “WORD”

第一后strcat的,这将是 “WORD +”

strncat(encPW, pw, mid)后,这将是 “WORD + PASS”。

0
#include <iostream> 
#include <string> 

void encrypt(const std::string& password) 
{ 
    size_t exactSize = password.length() + sizeof('+') + sizeof('\0'); 
    size_t mid = exactSize/2; 

    std::cout << "password = " << password 
       << ", exactSize = " << exactSize 
       << ", mid = " << mid 
       << ", password[0,mid) = " << password.substr(0, mid) 
       << ", password[mid,npos) = " << password.substr(mid, std::string::npos) 
       << '\n'; 

    std::string t1(password, mid); 
    std::string t2(password, 0, mid); 

    std::cout << "t1 = " << t1 << ", t2 = " << t2 << '\n'; 
} 

int main() 
{ 
    encrypt("12345678"); 
    encrypt("123456789"); 

    return 0; 
} 

产生输出http://ideone.com/fork/Y9GsHM

password = 12345678, exactSize = 10, mid = 5, password[0,mid) = 12345, password[mid,npos) = 678 
t1 = 678, t2 = 12345 
password = 123456789, exactSize = 11, mid = 5, password[0,mid) = 12345, password[mid,npos) = 6789 
t1 = 6789, t2 = 12345 

的问题那exactSize结果大小包括'+'和'\ 0',而不是源字符串的大小。

#include <iostream> 
#include <string> 

void encrypt(const std::string& password) 
{ 
    size_t mid = password.length()/2; 
    size_t exactSize = password.length() + sizeof('+') + sizeof('\0'); 

    std::cout << "password = " << password 
       << ", exactSize = " << exactSize 
       << ", mid = " << mid 
       << ", password[0,mid) = " << password.substr(0, mid) 
       << ", password[mid,npos) = " << password.substr(mid, std::string::npos) 
       << '\n'; 

    std::string t1(password, mid); 
    std::string t2(password, 0, mid); 

    std::cout << "t1 = " << t1 << ", t2 = " << t2 << '\n'; 
} 

int main() 
{ 
    encrypt("12345678"); 
    encrypt("123456789"); 

    return 0; 
} 

http://ideone.com/E5YFKm

你的C-字符串版本是相当狡猾太,我作出了上述代码的匹配C-字符串版本。

#include <iostream> 
#include <cstring> 

void encrypt(const char* password) 
{ 
    size_t len = strlen(password); 
    size_t allocSize = strlen(password) + sizeof('+') + sizeof('\0'); 
    size_t mid = len/2; 

    char left[16]; 
    char right[16]; 

    strncpy(left, password, len - mid); 
    left[len - mid] = '\0'; 
    strcpy(right, password + mid); 

    std::cout << "password = " << password 
       << ", len = " << len 
       << ", remainder = " << (len - mid) 
       << ", mid = " << mid 
       << ", left = " << left 
       << ", right = " << right 
       << '\n'; 
} 

int main() 
{ 
    std::cout << "begin\n"; 
    encrypt("12345678"); 
    encrypt("123456789"); 

    return 0; 
} 

http://ideone.com/O6Na9t