2013-05-17 187 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)。