1

これが私のC++関数です。

void SetUserName(char username[])
{
    cout << "\nPlease enter a username.\n"
         << "Must not be longer than 12 characters.\n>> ";

    cin.getline(username, MAX) // MAX is globally defined

    while(strlen(username) > MAX)
    {
        cout << "\nUsername too long, try again.\n>> ";
        cin.getline(username, MAX);
    }
}

明らかに、ユーザー入力は毎回 12 文字に切り捨てられるため、while ループは機能しません。

ユーザー入力が長すぎるかどうかを効果的に判断し、条件が満たされるまでループし続けるにはどうすればよいですか?

編集:ここで 使用cstringすることは必須です。文字列を使用することがいかに簡単かはすでに知っています。

編集#2:これは私に多くのことを教えてくれたので、間違いなく実り多い質問でした. 最終コード: http://pastie.org/3537894

4

4 に答える 4

4

Cスタイルの終端された文字列は扱いがかなり難しいので、ほとんどの場合、std::string代わりにC++をお勧めします。ただし、特に終了した文字列を配列に読み込みたいと言っているので、これを行う1つの方法があります。

配列サイズはである必要があるため、文字の後にターミネータが続くMAX+1スペースがあることに注意してください。MAX

istream::getlinefailbit行が長すぎる場合にストリームフラグを設定します。読んだ後にこれをテストすることができます。一部の行のみが抽出され、次の行に移動する場合は、エラー状態をクリアし、残りの行を無視する必要があります。

while (!std::cin.getline(buffer, MAX+1)) {
    std::cout << "Too long\n";
    std::cin.clear();
    std::cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n');
}
于 2012-03-06T23:46:22.230 に答える
3

適切な C++ を使用します (特に、strings と freegetline関数):

#include <string>
#include <iostream>

std::string line;
while (std::getline(std::cin, line))
{
    if (line.length() > 12)
    {
        // error, line too long

        continue;
    }

    // process line
}
于 2012-03-06T23:10:48.123 に答える
3

std::istream::getline()要求どおりに文字でいっぱいの配列を読み取るが行末文字ではないかどうかを調べたい場合は、格納されている文字数 (終端の null を差し引いたもの) が抽出された文字と同じかどうかを調べる必要があります。つまり、次の例では、行に 12 文字を超える文字があるかどうかを判断します (13 番目の文字は終端の null に必要です)。

#include <iostream>
#include <string.h>

int main()
{
    char array[13];
    if (std::cin.getline(array, 13).gcount() == strlen(array)) {
        std::cout << "excess characters on the line\n";
    }
}

次に余分な文字をストリームから削除したい場合は、次のようなものを使用しますstd::cin.ignore(std::numeric_limits<std::streamsize>::max());。これも C とタグ付けされているので、C でこれを行う方法はわかりませんが、 に似たものがあることは確かですgcount()

実際、仕様を詳しく見ると、文字の読み取り中に改行が発生しない場合にstd::istream:getline()実際に設定されます(文字が読み取られない場合にも設定されますが、ファイルの終わりに達する前に少なくとも1文字が読み取られた場合は設定されません)。つまり、余分な文字を無視する前にストリームをクリアする必要があり、次の作業を行うことができます。std::ios_base::failbitstd::ios_base:failbitstd::ios_base::failbitstd::ios_base::failbitstd::ios_base::eof()

#include <iostream>
#include <limits>
#include <string.h>

int main()
{
    char array[13];
    std::cout << "enter password: ";
    while (!std::cin.getline(array, 13) && !std::cin.eof())
    {
        std::cin.clear();
        std::cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n');
        std::cout << "password is too long: enter max 12 chars: ";
    }
    std::cout << "the password is '" << array << "'\n";
}

が設定されているため、ストリームを何かに使用する前std::ios_base::failbitに呼び出す必要があります。clear()

于 2012-03-06T23:34:27.677 に答える
1

ユーザーが許可されているよりも多くの文字を入力するには、制限を少なくとも 1 文字超える必要があります。ユーザーが制限を「超えた」文字数は問題にならないため、制限を通過MAX+1して、長さが より大きいかどうかを確認できますMAX

もちろん、バッファ内に 13 番目の文字とゼロ ターミネータを保持するのに十分なスペースを確保する必要があります。EDITignoreまた、試行が失敗するたびに行末までスキップするように呼び出す必要があります。

于 2012-03-06T23:09:35.627 に答える