なぜstrlenがsのサイズと違うのですか、そしてなぜcout charは数字ではなく文字を表示するのですか?

たくさんの単語の中に何個の 'e' があるかを数えるためのコードを書いた。

たとえば、「ニュースを読みます」と入力した場合、存在するカウンタの数は3になります。

#include 
#include 
using namespace std;

int main()
{
    char s[255],n,i,nr=0;
    cin.getline(s,255);

    for(i=1; i<=strlen(s); i++)
    {
        if(s[i-1]=='e') nr++;
    }
    cout<

私はC ++の文字について2つの不明確なことがあります。

  1. 上記のコードで strlen(s)を255に置き換えた場合、私のコードは機能しません。単語を入力するだけでプログラムが停止します。私は学校で strlen(s) s という文字列の長さであると教えられました。 strlen(s)?

  2. ではなく、255と入力してください。
  3. 上記のプログラムを普通に実行しても、やるべきことのように数字が表示されません。それは私にそれが私にそれがASCIIまたはASCIIテーブルからだと確信しているけれど、私は確信していないと思います、心臓またはダイヤモンドのように、示します。単語から e の数を印刷することになっています。

誰かが私にこれらを説明してもらえますか?

4
cin.getline()は、改行(値 '\ n' char )を検出して末尾にゼロ( '\ 0' )配列のその時点で、 strlen(s)は、値0()で見つかった最初の char のインデックスを返します。 '\ 0' )。配列 s の要素数は返されません。 s cin.getline()を呼び出す前に初期化されていないため、ゼロより後の文字は初期化されていません。 strlen(s) 255 に変更すると、ループはこれらの初期化されていない値にアクセスするため、未定義の動作になります。
追加された 著者 Peter,

4 答え

  1. strlen(s) gives you the length of the string held in the s variable, up to the first NULL character. So if you input "hello", the length will be 5, even though s has a capacity of 255....
  2. nr is displayed as a character because it's declared as a char. Either declare it as int, for example, or cast it to int when cout'ing, and you'll see a number.
5
追加された
インデックスの中の i-1 に注意してください。慣用的なスタイルではありませんが、厳密に正しいものです。
追加された 著者 BoBTFish,
@BoBTFish良い点、それを逃した!編集しました...
追加された 著者 Ian,
どうやら誰もが i char として宣言されていて、一般的なプラットフォームで127を超えることはあり得ないことを見逃していました…
追加された 著者 Arne Vogel,

strlen() counts the actual length of strings - the number of real characters up to the first \0 character (marking end of string).

だから、あなたが "こんにちは"を入力した場合:

sizeof(s) == 255
strlen(s) == 5

2番目の質問として、 nr char 型として宣言します。 std :: cout char を1文字として認識し、それをそのまま出力しようとします。これを回避するには、変数を int 型として宣言するか、印刷する前にキャストしてください。

int nr = 42;
std::cout << nr; 
//or
char charNr = 42;
std::cout << static_cast(charNr);
3
追加された
どうもありがとう!!!
追加された 著者 PaulP1,

他の人によって言及されていない追加の誤り、および注:

  • You should always check whether the stream operation was successful before trying to use the result.
  • i is declared as char and cannot hold values greater than 127 on common platforms. In general, the maximum value for char can be obtained as either CHAR_MAX or std::numeric_limits::max(). So, on common platforms, i <= 255 will always be true because 255 is greater than CHAR_MAX. Incrementing i once it has reached CHAR_MAX, however, is undefined behavior and should never be done. I recommend declaring i at least as int (which is guaranteed to have sufficient range for this particular use case). If you want to be on the safe side, use something like std::ptrdiff_t (add #include at the start of your program), which is guaranteed to be large enough to hold any valid array size.
  • n is declared but never used. This by itself is harmless but may indicate a design issue. It can also lead to mistakes such as trying to use n instead of nr.
  • You probably want to output a newline ('\n') at the end, as your program's output may look odd otherwise.
  • Also note that calling a potentially expensive function such as strlen repeatedly (as in the loop condition) can have negative performance implications (strlen is typically an intrinsic function, though, and the compiler may be able to optimize most calls away).
  • You do not need strlen anyway, and can use cin.gcount() instead.
  • Nothing wrong with return 0; except that it is redundant – this is a special case that only applies to the main function.

ここにあなたのプログラムの改良版があります、あなたのコードスタイルをあまり変更しようとしないでください:

#include 
#include 
#include 
using namespace std;
int main()
{
    char s[255];
    int nr=0;
    if ( cin.getline(s,255) )
    {//only if reading was successful
        for(int i=0; i

説明のために、以下は std :: string (任意の長さの入力用)と標準的なアルゴリズムを使ったより簡潔で表現力のあるバージョンです。 (インタビュアーとして、私はこれを、正当な答え、すなわち完全な信用に値するものとしてモジュロマイナーなスタイルの違いとして設定するでしょう。)

#include 
#include 
#include 
using namespace std;
int main()
{
    string s;
    if ( getline(cin, s) )
    {
        cout << std::count(begin(s), end(s), 'e') << '\n';
    }
}
2
追加された

私はC ++の文字について2つの不明な点があります。1)上記のコードでは、   私が "strlen(s)"を255に置き換えると、私のコードは動作しません、   単語をタイプすることしかできず、プログラムは停止します、そして私は教えられました   "strlen(s)"が文字列sの長さである学校、これには   宣言したとおり、caseは255です。では、代わりに255と入力することができないのはなぜですか。   strlen(s);

その通りですが、スペースがさらに割り当てられていても、文字列はnullターミネータのみを使います。一例として、これを考えてみましょう。

char buf[32];
strcpy(buf, "Hello World!");

32文字分のスペースがありますが、私の文字列は12文字しかありません。この例で strlen 12 を返すのはそのためです。バッファの長さがわからないからです。文字列のアドレスを知っているだけで、nullターミネータが見つかるまで解析します。

したがって、255と入力した場合、 cin で設定された内容を過ぎてしまい、残りのバッファを読むことになります。この場合、初期化されていません。これは未定義の振る舞いです - この場合それは恐らくいくつかのゴミ値を読むでしょう、そしてそれらは偶然 'e' 値を持っているかもしれず、その結果間違った結果を与えるかもしれません。

2)上記のプログラムを通常よりも上で実行しても、数値は表示されません。   それがすることになっているように、それは私に性格を示しています   ASCIIテーブルだが、よくわからないが、ハートやダイヤモンドのようだが、   は単語からeの数を出力することになっています。誰でもできます   説明してください。

nr char として宣言しました。実際には整数値を保持できますが、このように印刷すると、文字として印刷されます。代わりに int として宣言するか、印刷時にキャストしてください。

1
追加された
どうもありがとう!!!
追加された 著者 PaulP1,