1

我正在尝试创建一个简单的(模块化)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 Hello ╠╠╠╠╠╠╠╠ 按任意键继续。. .

如果我在 readUserInput 函数中打印出 userInput 变量,它会打印出输入的内容。但是,尝试在 _tmain 函数中将 userInput 变量存储为 userName 会导致打印出难以理解的字符序列。IE。╠╠╠╠╠╠╠╠。根据我的最佳猜测,这可能是由指针问题引起的,但据我所知,我正确引用了所有内容。

调试此代码:在这一行: _printOut("Hello"); 在方法中:_tmain [userName = "abcdefg"] 在这一行:_printOut(userName); 在方法 _tmain [userName = "†UX"]

所以我想知道当用户名的值没有在两行之间分配或操作时,它的值是如何变化的。

4

5 回答 5

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

char userInput[256];数组仅在函数调用期间存在。一旦你到达函数的底部,它就不再存在,并且你返回一个指向一些垃圾内存的指针。这称为本地范围

无论如何,如果某人的名字很长(比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>>...getlinecin>>...会尽可能多地读取空格,然后将其余部分留在后面。因此,除了可能会丢失某人的姓氏之外,如果他们输入的名称没有空格,它只会在输入流中留下最后一个换行符。然后,当您来做时getline,您不会得到下一行用户输入。你得到了留下的空行。如果您cin>>再次使用,则换行符将被忽略。例如考虑这个用户输入:

Hello\n
World\n

如果您使用 进行第一次阅读cin>>,您将"Hello"进入您的程序,然后离开

\n
World\n

如果您随后使用 进行第二次阅读getline,您将""进入您的程序,然后使用

World\n
于 2013-05-17T08:57:22.597 回答
2

char userInput[256];readUserInput 退出时会被销毁,所以返回的指针是无效的。

改为使用std::string

或者动态分配变量,或者传递一个自动变量作为参数。

于 2013-05-17T08:56:32.433 回答
1

userInput 变量一旦超出范围就会被销毁。

局部变量存储在堆栈中。一旦函数执行完成,变量就会被销毁。

您需要使用动态分配的字符指针(堆上存储)或 std::string

于 2013-05-17T08:56:26.067 回答
0

您的问题是范围问题:

char userInput[256];定义一个仅在其自身范围内有效的局部变量(在一组{}括号之间)。

您实际上返回了一个有效的指针,一旦您离开该函数,该指针就会变得无效,因为它已被释放。

您违反了一条基本规则:永远不要返回指向本地(非静态)变量的指针。

要解决此问题,请将您的userInput静态或返回一个新字符串(使用 每次调用创建一个新字符串new)或使用可复制对象而不是指针(如std::string)。

于 2013-05-17T08:57:27.883 回答
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

于 2013-05-17T09:41:51.063 回答