2013-05-17 240 views
1

我試圖創建一個簡單的(模塊化的)C++程序,讀取用戶輸入並將其吐出。C++指針問題

#include "stdafx.h" 
#include <iostream> 
#include <fstream> 
#include <string> 

using namespace std; 

void _printOut(char * output) 
{ 
    cout << output << endl; 
} 
char * readUserInput() 
{ 
    char userInput[256]; 
    cin >> userInput; 
    return userInput; 
} 

int _tmain(int argc, _TCHAR* argv[]) 
{ 
    _printOut("Enter your name: "); 
    char * userName = readUserInput(); 
    _printOut("Hello"); 
    _printOut(userName); 
    system("pause"); 
    return 0; 
} 

輸入您的姓名: AAAA 你好 ╠╠╠╠╠╠╠╠ 按任意鍵繼續。 。 。

,如果我在readUserInput功能打印出userInput變量它打印出什麼輸入。然而,嘗試在_tmain函數中將userInput變量存儲打印爲userName會導致打印出不可理解的字符序列。即。 ╠╠╠╠╠╠╠╠。 據我的猜測,這可能是由指針問題引起的,但據我所知,我正確地引用了所有內容。

調試這樣的代碼: 在這一行:_printOut( 「你好」);在方法中:_tmain [userName =「abcdefg」] at this line:_printOut(userName);在方法_tmain [用戶名=「†UX」]

所以我想知道如何在不分配或兩條線之間操縱它的用戶名的值正在改變。一旦超出範圍

+1

的問題是,你使用'C字符指針++'。改用'std :: string'。 – stefan

+0

使字符串函數而不是複雜的字符指針。 –

回答

0

您使用的指向緩衝區的指針(在棧),其是已經超出範圍。

試試這個:

#include <iostream> 
#include <fstream> 
#include <string> 

using namespace std; 

void _printOut(char * output) 
{ 
    cout << output << endl; 
} 
char * readUserInput() 
{ 
    //Allocate in Heap, instead of stack 
    char* userInput = new char[256]; 
    cin >> userInput; 
    return userInput; 
} 

int main(int argc, char* argv[]) 
{ 
    _printOut("Enter your name: "); 
    char * userName = readUserInput(); 
    _printOut("Hello"); 
    _printOut(userName); 
    system("pause"); 
    return 0; 
} 

一個更好的辦法是使用的std :: string

+0

thx所有的答案傢伙。然而根據我的問題,這修復了我所查詢的具體問題。改變一條線是最好的修正: char userInput [256]; char * userInput = new char [256]; – gnuShark

1

userInput變量被銷燬。

局部變量被存儲在堆棧上。一旦函數執行完成,變量就會被銷燬。

要麼你需要使用動態分配的字符指針(存儲在堆)或std ::字符串readUserInput退出時

2

char userInput[256];就會被破壞,這樣你就返回指針是無效的。

使用std::string代替。

或者動態分配變量,或者傳遞一個自動變量作爲參數。

+0

至少有一個類似C++的方法來解決這個c/C++混合垃圾代碼... –

4
char * readUserInput() 
{ 
    char userInput[256]; 
    cin >> userInput; 
    return userInput; 
} 

char userInput[256];數組只在函數調用期間存在。一旦你到達函數的底部,它就不再存在,並且你返回一個指向一些垃圾內存的指針。 這被稱爲local scope

無論如何,如果某人有一個相當長的名字(長於255個字符)。

考慮使用std::string,這將解決這兩個問題。

std::string readUserInput() 
{ 
    std::string inp; 
    std::cin >> inp; 
    return inp; 
} 

void printOut (const std::string& toPrint) 
{ 
    std::cout << toPrint << '\n'; 
} 

(同樣,這是次要的,名字_printOut在這種情況下是不允許的,因爲領導_的。See here,儘管它可能走在你的頭上,如果你是一個初學者。)

編輯一個更好的方法去是使用std::getline到一次讀取一整行成std::string。但是,由於它們處理空格的方式,特別是'\n'換行符,getline(...)cin>>...不能很好地一起玩。通常只需選擇一個,並在整個程序中堅持下去。以下是如何readUserInput()看起來:如果

std::string readUserInput() 
{ 
    std::string line; 
    std::getline(std::cin, line); 

    return line; 
} 

這樣,用戶輸入一個空格包含名稱(例如"BoB T. Fish"),你會讀出完整的名稱,而不是僅僅"BoB"(然後離開休息到下一次迷惑你你讀)。

這可能是因爲混合cin>>...getline的原因在於cin>>...會讀取儘可能多的空白,然後將其餘的放在後面。因此除了mayb排除某人的姓氏之外,如果他們輸入一個沒有空格的名字,它只會將最後一個換行符留在輸入流中。那麼當你一起來做getline時,你不會得到下一個行用戶輸入。你得到了被遺留下來的空行。如果您再次使用cin>>,則換行符會被忽略。 例如考慮該用戶輸入:

Hello\n 
World\n 

如果你做cin>>第一次讀,你會得到"Hello"在你的程序,並留下了

\n 
World\n 

如果然後做第二次讀取與getline,你在你的程序"",並與

World\n 
+1

如果名稱中包含空格,cin >> imp'將不起作用。當需要任意內容字符串時,'std :: getline'是要走的路。 –

+0

@EmilioGaravaglia好點。我通常對此很好,但我不想太多改變原來的例子。我會添加一些東西。 – BoBTFish

0

你在這裏留下的問題是一個範圍問題:

char userInput[256];定義了一個局部變量,只有效其自身範圍內(之間IST組{}括號)。

基本上只是返回,一旦你離開的功能,因爲它釋放的是變得無效的有效的指針。

您違反基本規則:永遠不會返回指向本地(非靜態)變量。

要解決這個問題,讓你的userInput靜態或返回一個新的字符串(新建一個字符串使用new每次調用),或者使用可複製對象,而不是指針(如std::string)。