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 こんにちは ╠╠╠╠╠╠╠╠ 続行するには何かキーを押してください。. .

readUserInput 関数で userInput 変数を出力すると、入力内容が出力されます。ただし、userInput 変数ストアを _tmain 関数で userName として出力しようとすると、出力される文字列が理解不能になります。すなわち。╠╠╠╠╠╠╠╠. 私の推測では、これはポインターの問題が原因である可能性がありますが、私が知る限り、すべてを正しく参照しています。

このコードのデバッグ: この行: _printOut("Hello"); メソッド内: _tmain [userName = "abcdefg"] この行: _printOut(userName); メソッド _tmain で [userName = "†UX"]

そのため、username の値が 2 つの行の間で割り当てられていないか、操作されていない場合に、その値がどのように変化するのか疑問に思っています。

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はありません先頭に_.

編集さらに良い方法は、 を使用std::getlineして一度に 1 行全体を に読み込むことstd::stringです。'\n'ただし、スペース、特に改行文字の扱い方が原因で、一緒にうまく機能しませんgetline(...)cin>>...通常は、1 つを選択して、プログラム全体でそれを使い続けるのが最善です。これがどのようreadUserInput()に見えるかです:

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

    return line;
}

このようにして、ユーザーが空白を含む名前 (例: "BoB T. Fish") を入力すると、名前だけではなく全体を読むことができます"BoB"(そして、次に読むときに混乱するように残りを残します)。

これが混ざりにくい理由は、空白まで可能な限り読み取り、残りcin>>...を残すためです。したがって、誰かの姓を省略する可能性は別として、スペースなしで名前を入力すると、入力ストリームの最後の改行文字がそのまま残ります。その後、 を実行すると、ユーザー入力の次の行が得られません。取り残された空の行を取得します。代わりにもう一度使用した場合、改行は無視されます。たとえば、次のユーザー入力を検討してください。getlinecin>>...getlinecin>>

Hello\n
World\n

で最初の読み取りを行うと、プログラムに入り、で終了しcin>>ます"Hello"

\n
World\n

次に で 2 番目の読み取りを行うと、プログラムに入り、 で終了しgetlineます""

World\n
于 2013-05-17T08:57:22.597 に答える
2

char userInput[256];readUserInput が終了すると破棄されるため、返されるポインターは無効です。

std::string代わりに使用してください。

または、変数を動的に割り当てるか、自動変数をパラメーターとして渡します。

于 2013-05-17T08:56:32.433 に答える
1

userInput 変数は、スコープ外になると破棄されます。

ローカル変数はスタックに格納されます。関数の実行が完了すると、変数は破棄されます。

動的に割り当てられた char ポインター (ヒープ上のストア) または std::string を使用する必要があります。

于 2013-05-17T08:56:26.067 に答える
0

ここでの問題は、スコープの問題です。

char userInput[256];独自のスコープ内 ({}括弧の ist セットの間) でのみ有効なローカル変数を定義します。

解放されるため、関数を終了すると無効になる有効なポインターを本質的に返します。

基本的なルールに違反しています:ローカル (非静的) 変数へのポインターを決して返さないでください。

これを修正するには、userInput静的にするか、新しい文字列を返す ( を使用して呼び出しごとに新しい文字列を作成するnew) か、ポインターではなくコピー可能なオブジェクトを使用します ( などstd::string)。

于 2013-05-17T08:57:27.883 に答える