2014-03-02 53 views
0

,因爲我現在真的絕望了,我可以使用一些幫助。在這裏,看看這段代碼,然後看看輸出。什麼導致這個錯誤?我該如何解決它?
感謝任何形式的幫助!
代碼:C++如果其他人不按預期工作? (很奇怪的BUG)

while (1) 
{ 
    while (1) 
    { 
    cout << "Choose your username: "; 
    cin >> username; 
    std::strcpy (username1, username.c_str()); 
    if (isdigit(username1[0]) || isdigit(username1[1]) || isdigit(username1[2])) 
    { 
     cout << "The first 3 characters HAVE to contain only letters!\n\a"; 
    } 
      else if (username1[3] < 0) // I don't actually know why, but this works as intended o.O 
      { 
       cout << "Your username HAS to contain atleast 3 letters!\n\a"; 
      } 
       else if (username1[10] > 0)      // Works - dunno why o.0 
       { 
        cout << "Your username CAN ONLY contain maximum 10 characters!\n\a"; 
       } 
        else 
         break; 
    } 

輸出:

Choose your username: ko 
Your username HAS to contain atleast 3 letters! 
Choose your username: k 
Your username HAS to contain atleast 3 letters! 
Choose your username: kokokokokoo // Now that's > 10 
Your username CAN ONLY contain maximum 10 characters! // Now this is okay BUT... 
Choose your username: ko 
Your username CAN ONLY contain maximum 10 characters! // Wrong error! 
Choose your username: kok   // This should be accepted! 
Your username CAN ONLY contain maximum 10 characters! // Well, it is not... there should not be an error at all! 

注重我在輸出增加,所以你知道什麼是錯的意見。 謝謝你所有的答案!

+2

瞭解如何使用開發環境的調試器。現在是最好的時機。 – nvoigt

+0

您需要檢查輸入字符串* first *的長度。否則,當用戶輸入一個短字符串時,您正在訪問無效字符。 –

+0

您需要重置字符串後返回到循環 String = aaaaaaaaaa <= 10個字母 下一個循環它仍然有10個字母,所以做一個memcpy來清除內容或填充0。 – Lefsler

回答

2

方括號裏的東西沒有做你認爲它在做的事情。

當您使用username1[10]代碼,你實際上說的是「讓我在字符串中的11位(記住,索引是從零開始的)。

的性格讓下面的代碼行.. 。

... 
else if (username1[3] < 0) 
... 

字面上說「是在第4位的字符串小於零的性格嗎?」,而這完全是胡說(ASCII字符不能爲負)。

你可能打算什麼說的是「是的長度少於三個字符「,在這種情況下,你應該使用::strlen方法,像這樣:?,

else if (::strlen(username1) < 3) 

然而作爲另一個答案中提到,如果您使用純C++,有可能是沒有必要使用username1在所有的,你可以只調用std::string::size()原始username變量。就像這樣:

else if (username.size() < 3) 

您的代碼以意想不到的方式工作的原因是因爲你想尋找的字符串中並不存在的人物。

想象一下以下內容:

username1: [ k | o | k | o | \0 | 4 | f | 6 | 7 | a | 3 | 3 ] 
    indexes: 0 1 2 3 4 5 6 7 9 9 10 11 

以上是一些原始內存的基本圖像,你可以看到,在0位置,你有你的字符串"koko",然後空終止符,然後大量的無關垃圾,你還沒有初始化。當你說username1[10]時,你會經過輸入字符串的末尾,進入與你的字符串變量無關的垃圾內存。所以if語句失敗!但是,由於5-11位置的字符是未初始化的,有時位置10的字符可能爲零,或者它可能是別的,或者甚至可能導致程序崩潰!這就是所謂的未定義行爲,你應該不惜一切代價避免它!

1

沒有什麼設置username1[10]回零你把字符串「kokokokokoo」,在它之後。

如果使用strncpy代替strcpy則(a)您會從緩衝區溢出和(b)strncpy零墊的目的地,你希望你的程序將工作安全。

不過說真的,其他的評論說,你應該複製前檢查字符串的長度,或使用它。

0

,你不知道爲什麼他們的工作不工作的部分。你很可能根本不需要username1;你真正應該做的是檢查輸入長度username.length()

if (username.length() < 3) { 
    // "too short" error 
else if (username.length() > 10) { 
    // "too long" error 

你在做什麼檢查是在索引3和串10的(可能是不確定的垃圾)字符。當strcpy將更短的東西複製到字符串中時,它不會擦除索引10。

1

後您輸入

kokokokokoo 

然後ebtered

ko 

字符數組username1包含if語句

以下

[k] [o] ['\0'] [o] [k] [o] [k] [o] [k] [o] [o] ['\0'] 
0 1  2 3 4 5 6 7 8 9 10 11 

所以這個條件

是錯誤的,因爲三個字符[k] [o] ['\ 0']都不是數字。

這種情況

else if (username1[3] < 0) 

也是假因爲USERNAME1 [3]等於 'O' 是大於零。

這種情況

else if (username1[10] > 0) 

爲真,因爲USERNAME1 [10]等於 'O' 是大於零。

後您輸入的字符串字面

kok 

USERNAME1成爲看作

[k] [o] [k] ['\0'] [k] [o] [k] [o] [k] [o] [o] ['\0'] 
0 1 2 3  4 5 6 7 8 9 10 11 

其實沒有什麼相對改變的條件。作爲USERNAME1 [10]等於「O」是大於零,那麼你得到的消息

Your username CAN ONLY contain maximum 10 characters! 

而且目前尚不清楚爲什麼你複製類型的std :: string用戶名的對象轉換成字符數組USERNAME1。

您可以使用用戶名而不是用戶名1進行所有檢查,之後您可以將用戶名複製到用戶名1(如果需要的話)。例如

if (username.size() < 3) 
{ 
    cout << "Your username HAS to contain atleast 3 letters!\n\a"; 
} 
else if (username.size() > 10) 
{ 
    cout << "Your username CAN ONLY contain maximum 10 characters!\n\a"; 
} 
else if (isdigit(username[0]) || isdigit(username[1]) || isdigit(username[2])) 
{ 
    cout << "The first 3 characters HAVE to contain only letters!\n\a"; 
} 
//...