2

私は本「C++ を使用したプログラミングの原則と実践」を使用してプログラミングを学習しています。演習の 1 つは、while ループを使用して文字 az をループすることです。

今、私は以前に C++ や他の言語でプログラミングしたことがあるので、(while ループを使用しながら) できるだけ少ない行数を使用することにしました。ただし、これには、出力がめちゃくちゃになるという代償が伴いました。

コード:

#include <iostream>
int main(){
    char ch = 'a';
    while(ch <= 'z')
        std::cout << ch << '\t' << (int) ch++ << std::endl;
    return 0;
}

出力:

b   97
c   98
d   99
e   100
...
x   119
y   120
z   121
{   122

今では、代わりに for ループを使用してこれを行うことができたことに気付きました。しかし、私はまだこのコードの何が問題なのか理解できず、本当にイライラしています。

「a」を出力するはずの場所に「b」を出力するため、「ch + 1」を出力するように指示したように見えます。インクリメントは、ch の整数値がアウトストリーム (ポストインクリメント) に入れられるまで行われません。以前にインクリメントしていたとしても、少なくとも印刷された文字とその整数値は対応しているはずです。

このコードが機能しない理由について何か考えはありますか?

4

4 に答える 4

5

呼び出しの順序はoperator<<明確に指定されていますが、オペランドが評価される順序は明確ではありません。

のインクリメントは、「初めて」ch出力する前または後に発生する可能性があり、インターリーブされた読み取り/書き込み操作のため、このプログラムを実行するだけでは未定義です。ch

[2003: 1.9/12]:完全式は、別の式の部分式ではない式です。[..]

[2003: 1.9/16]:各full-expressionの評価が完了すると、シーケンス ポイントがあります。

[2003: 5/4]:特に明記されていない限り、個々の演算子のオペランドと個々の式の部分式の評価の順序、および副作用が発生する順序は規定されていません。前のシーケンス ポイントと次のシーケンス ポイントの間で、スカラー オブジェクトの格納値は、式の評価によって最大 1 回変更されます。さらに、保存する値を決定するためにのみ、前の値にアクセスする必要があります。この段落の要件は、完全な式の部分式の許容される順序ごとに満たされるものとします。それ以外の場合、動作は未定義です。


代わりに、明示してください。

std::cout << ch << '\t' << int(ch) << std::endl;
++ch;

あなたのコンパイラはあなたのコードについて警告しているはずです。そうでないということは、診断が有用なレベルに設定されていないことを示しています。

GCC では-Wall -Wextra -std=c++98 -pedantic(または-Wall -Wextra -std=c++0x -pedanticC++0x の場合) を使用します。

于 2011-08-14T15:05:16.873 に答える
2

ch簡単に言えば、同じ式で別々の部分式を介して変数の値を変更して使用しているため、未定義の動作が少しあるということです。

ここで正しいこと (TM) は、目前のタスクに最も実用的なループを使用することです。

#include <iostream>
int main(){
    for(char ch = 'a'; ch <= 'z'; ++a){
        std::cout << ch << '\t' << ch+0 << std::endl;
    }
}
于 2011-08-14T15:00:25.943 に答える
2

コード内の ch++ が最初に評価されます。より読みやすく正しいバージョンは次のようになります。

#include <iostream>
int main(){
    char ch = 'a';
    while(ch <= 'z') {
        std::cout << ch << '\t' << int(ch) << std::endl;
        ++ch;
    }
    return 0;
}
于 2011-08-14T15:01:05.823 に答える
1

1 つのコマンドまたは式で 1 ​​つの変数を 2 回使用すると、1 回は ++ (または --) を使用し、1 回は使用せずに使用すると、未定義の動作が発生します。

代わりに次を使用します。

while(ch <= 'z')
{
   std::cout << ch << '\t' << (int) ch << std::endl;
   ch++;
}
于 2011-08-14T15:03:18.297 に答える