1

何らかの理由で、C++ で If/else ステートメントが正しく機能しない

問題は、バリアベルが右 (höger) に等しい場合、If ステートメントを出力せず、代わりに else ステートメントに進むことです。文字 'ö' を say 'o' に置き換えて、代わりに 'hoger' にすると、if ステートメントが機能します。したがって、「höger」という単語を書くときはいつでも、if ステートメントに移動せず、代わりに else ステートメントに移動します。ただし、バリアベルを 'hoger' に等しくしてから 'hoger' と書くと、うまくいきます。If ステートメントが代わりにそれを認識する場合、どうすれば 'höger' を書くことができるようになりますか? まるでスウェーデン文字が通用しないかのようです。

私のコードは次のようになります。

#include <iostream>
#include <string>

using namespace std;


int main() {
    setlocale(LC_ALL,"");


    string test; // Define variabel
    cout << " Höger elle vänster"<<endl; // Right or left
    cin >> test;


    if(test == "höger") { // If right, then output this.

        cout <<"Du valde höger"<<endl;

    } 

    else if(test == "vänster") { // If left, then output this

        cout <<"Du valde vänster"<<endl;

    } else {

        // Do this

    }


}
4

4 に答える 4

4

問題はほぼ確実にエンコーディングに関係しています。

C/C++ 言語仕様では、7 ビット ASCII 以外は自動的に処理されません。o ウムラウト文字はその範囲外であり、正確な動作はソース コード ファイルのエンコーディングによって異なります。

最も可能性が高いのは、ISO 8859-1、Windows ANSI-1252、UTF-8、または Windows OEM 850 です。最初の 2 つはこの文字を同じようにエンコードしますが、他のそれぞれでは異なります。

使用しているエンコーディングとツール セットについてもう少し情報があれば、より具体的な診断とアドバイスを提供できる可能性があります。

[ちなみに、C/C++ の if/else ステートメントは問題なく動作します。ありがとうございます。]


今のところこれが Windows と Visual C++ であると仮定すると、これがあなたが扱っているものです。

  • Visual Studio 内で記述されたソース コード: コード ページ 1252。o ウムラウト文字のコード ポイントは 0xf6 です。
  • コンソールから読み取ったキーボード入力: コード ページ 850。 o ウムラウト文字のコード ポイントは 0x94 です。

明らかに相性が悪い。ただし、Visual Studio は、UTF-8 (バイト マーク付き)、UTF-16 (ワイド文字)、およびコード ページ 850 を含む多くのエンコーディングでソース コード ファイルを非常にうまく編集することもできます。

  • Visual Studio 内で記述されたソース コード: コード ページ 850。o ウムラウト文字のコード ポイントは 0x94 です。今では動作します。

CHCP コマンドを使用して、コンソールのコード ページを変更することもできます。

  • コンソールを CHCP 1252 に変更すると、機能します。

ソース コードを読み取るときのコンパイラの動作は、実行文字セットと一致するように標準で義務付けられています。n3797 S2.2.5 を参照してください:

文字リテラルまたは文字列リテラルの各ソース文字セット メンバー、および文字リテラルまたは非生文字列リテラルの各エスケープ シーケンスおよびユニバーサル文字名は、実行文字セットの対応するメンバーに変換されます。

S2.3/3:

基本実行文字セットと基本実行ワイド文字セットには、基本ソース文字セットのすべてのメンバーに加えて、アラート、バックスペース、キャリッジ リターンを表す制御文字、および NULL 文字 (それぞれ、NULL ワイド文字) が含まれます。その表現にはすべてゼロのビットがあります。基本的な実行文字セットごとに、メンバーの値は負ではなく、互いに異なるものでなければなりません。ソースおよび実行の基本文字セットの両方で、上記の 10 進数のリストの 0 の後の各文字の値は、前の値よりも 1 大きくなります。実行文字セットと実行ワイド文字セットは、それぞれ基本実行文字セットと基本実行ワイド文字セットの実装定義のスーパーセットです。

n3797 S2.14.3/1:

u、U、または L で始まらない文字リテラルは、通常の文字リテラルであり、ナロー文字リテラルとも呼ばれます。実行文字セットで表現可能な単一の c-char を含む通常の文字リテラルの型は char で、値は実行文字セットでの c-char のエンコーディングの数値に等しくなります。

n3297 S2.14.5/6:

encoding-prefix で始まらない文字列リテラルは通常の文字列リテラルであり、指定された文字で初期化されます。

実行文字セットは実装定義です。C コンパイラの実装定義の動作に関する Microsoft の声明は、http://msdn.microsoft.com/en-us/library/hx3yt8af.aspx にあります。[C++ 用の個別のものを見つけることができないため、これは両方に当てはまると思います。]

The source character set is the set of legal characters that can appear in source files. For Microsoft C, the source character set is the standard ASCII character set.

言語弁護士の話で申し訳ありませんが、これは、MSVC コンパイラがロケール/エンコーディングに依存せず、コード ページが指定されていない 8 ビット ASCII を実装しているということです。明らかに、標準ライブラリ関数はさまざまな目的でエンコーディングを知る必要があるかもしれませんが、それはまったく別の話です。


最後に、Microsoft C コンパイラの歴史は、Windows より前の約 30 年前にさかのぼります。コード ページ 850 でソース コードを記述し、拡張 (8 ビット) 文字を慎重に処理することを条件として、コンソール上で正しく実行することは常に可能でした。多くの人は今でもそうしています。ここでの問題は、Windows-Ansi または Unicode で記述されたソース コードと、OEM (cp850) コンソールからのキーボード入力です。いずれかを変更して、正しく機能するようにします。

于 2014-04-06T11:24:10.760 に答える
1

実際には、この問題は Windows でのみ発生するため、Windows を想定します。

問題は、C++ の狭い拡張実行文字セット(1) (エンコード) が、コンソール ウィンドウで使用されるエンコードと一致しないことです。「ナロー」はタイプを指しcharます。「実行文字セット」は、C++ 標準で採用されている正式な用語であり、実行可能ファイルに格納されたテキストに想定されるエンコーディングを指します。コンパイラは、ソース コード リテラルをこのエンコーディングに変換します。また、コンソールのエンコーディングとの間の翻訳など、外部エンコーディングとの間の翻訳も想定されています。

      ここに画像の説明を入力

Visual C++ では、コンパイラをだまさない限り、ソース コードのエンコーディングに関係なく、ナロー エンコーディングは常にWindows ANSI (2)です。Visual C++ を使用していると仮定すると、これはご存知の 1 つのエンコーディングです。

コンソール ウィンドウのエンコーディングは、デフォルトで元の IBM PC で使用されているもので、おそらくコードページ 850 (元の IBM PC 英語コードページ 437 の西ヨーロッパ版) です。Windows コマンド インタープリターを実行しますcmd( Windows-key+ R、 type cmd、OK)。入力chcpして、現在のコードページを確認します。入力chcp 1252して Windows ANSI Western に切り替えます。これはおそらく、マシンの Windows ANSI コードページです。プログラム [.exe] ファイルを実行します。たとえば、フル パスを入力するか、ディレクトリに移動して名前だけを入力します。

[H:\dev\test\0046]
> cl /nologo /EHsc /GR encoding.cpp /Fe:b.exe
エンコーディング.cpp

[H:\dev\test\0046]
> chcp & b
アクティブ コード ページ: 850
 Höger elle vänster
höger
                             ここには出力がありません。同等とは比較されませんでした。
[H:\dev\test\0046]
> chcp1252
アクティブ コード ページ: 1252

[H:\dev\test\0046]
> b
 Höger elle vänster
ホーガー
Du valde höger

[H:\dev\test\0046]
> _

cl(元の「Lattice C」の略) は、Visual C++ コンパイラです。

regeditを実行して、次のレジストリ キーに移動すると、コンソール コードページをより永続的に変更できます。

HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Nls\CodePage

右側のペインのリストで、名前が付けられた値 (Original Equipment Manufacturer Code Page の略で、IBM PC を参照) をダブルクリックし、OEMCP1252 に変更するか、より一般的には値と同じ値に変更しACP、マシンを再起動します。 .

また、コンソール ウィンドウのフォントをLucida Console などのTrueType フォントに変更する必要があります。これは、デフォルトが元のコンソール コードページでのみ正しく動作するビットマップ フォント (のエミュレーション) であるためです。コンソール ウィンドウのタイトルを右クリックしてメニューを表示し、[デフォルト] を選択して、デフォルトのフォント、サイズ、色などを設定します。変更は現在のコンソール ウィンドウには影響しませんが、今後のコンソール ウィンドウには適用されます。個別に構成されたものについては(3)

このようなコンソール ウィンドウ構成の代わりに、Console2プログラムを使用することができます。その場合、Windows 7 以降では必ず 64 ビット バージョンを使用してください。そうしないと、64 ビット プログラムへのリンクの呼び出しなど、いくつかのことが機能しなくなります。


要約すると、次のいずれかが可能です

  • コマンドインタープリターからプログラムを実行する (chcpコードページを変更するために使用)、または

  • 上記のように、コンソールのコードページをより恒久的に変更します。

どちらの場合でも、コンソール ウィンドウのフォントを TrueType フォントに変更することをお勧めします。もちろん、これは外観だけでなく機能にも影響します。

追加の Microsoft の不条理についての注意: Windows 7 以降では、コンソール ウィンドウでデフォルトで使用される「システム」フォントは、実際には、舞台裏で、多数のグリフを持つ TrueType フォントですが、古い 16 ビット Windows ビットマップ フォントをエミュレートするために使用されます。 、同じ愚かな制限があるため、他のTrueTypeフォントに変更する必要があります...


(1) C++11 標準 §2.3/3 を参照してください。

(2)「Windows ANSI」は、Windows の構成に依存し、常にGetACPAPI 関数によって指定されたコードページです。実際には、この関数は上記のレジストリ キー/値から値を取得します。ただし、それはほとんど文書化されていません。

(3) Windows XP では、個々のコンソール ウィンドウの構成を保存するかどうかを尋ねられます。Windows Vista 以降では、保存されているという情報も質問もされずに保存されます。このように保存された構成を削除するためのユーザー インターフェイスはありませんが、ショートカット ファイルをプログラムで変更したり、レジストリを編集したりすることで削除できますが、これは非現実的で脆い解決策です。

于 2014-04-06T11:38:56.800 に答える
0

問題は、IDE がソース ファイルをコンパイルするときのソース ファイルのエンコードにあるようです。Visual Studio を使用している場合は、次のようにエンコード設定を変更できます。

ここ

于 2016-01-15T14:06:39.597 に答える