2011-10-20 15 views
0

C++ WinAPIで各文字のint値を合計して文字列を数値に変換しようとしています。だからASCIIで; std :: string "AA"は130(65 + 65)と等しくなりますstd :: string&std :: wstringからchar整数値を取得する

文字列はstd :: stringまたはstd :: wstringのいずれかです。

なぜ、次の関数は、入力した文字にかかわらず常にゼロの値を返しますか?文字のASCIIまたはUnicodeの整数値を返してはいけませんか?

printf("TEST a: %d \n", _tstoi(_T("a"))); 
printf("TEST A: %d \n", _tstoi(_T("A"))); 
printf("TEST b: %d \n", _tstoi(_T("b"))); 

マイVC++アプリケーションは、Unicodeで現在&以前のコードでは、各文字のためのゼロを出力します。私はUnicodeがASCII文字列と非常に異なっていることを聞いたことを覚えています。Unicode以外のものが何であるかを明確にすることができますか?ASCIIは256ですが、30,000のような文字のライブラリがあります。

+3

、ジョエルの「絶対最小すべてのソフトウェア開発絶対に、Unicodeとキャラクタセットについて(弁解を!)知らない必要がある」http://www.joelonsoftware.com/articles/Unicode.html – HostileFork

答えて

1

* toiファミリーの関数は、文字列表現を整数表現に変換します。つまり、「10」は10になります。実際に何をしたいのかは全く変換されません。それを変更します。ユニコードについては

 
printf("TEST a: %d \n", _T('a')); 
printf("TEST A: %d \n", _T('A')); 
printf("TEST b: %d \n", _T('b')); 

、基礎となる表現がエンコーディングに依存して(たとえば、UTF-8、非常に人気のあるため、LSB ASCIIテーブルにマップします)。

+0

だから、文字列の合計を得るためにこれを行うことは大丈夫でしょうか?int x + =(int)_T( "a"); ?または、私は長いキャストまたはunsigned intキャストを行う必要がありますか?または静的なキャストさえも可能ですか? –

+0

すべてのchar型は符号なしの整数型です。ビット幅の違いに関連するコンパイラの警告を抑制するためにstatic_castを超えて変換する必要はありません。符号なしint x = _T( 'a');たとえば、うまくいくはずです。 _T( "a")はNULL終端文字を含み、実際には2長の配列です。 – Ylisar

3

MSDNの記事は述べています:

は、「入力文字列が指定された型の数値として を解釈できる文字列です機能は、最初の文字で入力文字列を 読んで停止します。数字の部分に と認識されません。

あなたは、実際の数字を含むUnicode文字列を使用してコードをテストする場合は、正しい出力表示されます:@Ylisarは* TOI、言ったように

TEST 1: 1 

printf("TEST 1: %d \n", _tstoi(_T("1"))); 

出力を関数を使用して数値値を文字列から整数変数に変換します。

次のコードは、代わりに数値表現を出力しますが、const変数のポインタ表現に注意してください。

printf("TEST 1: %d \n", _tstoi(_T("1"))); 
    printf("TEST a: %d \n", _tstoi(_T("a"))); 
    WCHAR* b(_T("b")); 
    printf("TEST A: %d \n", _T("A")); 
    printf("TEST b: %d \n", *b); 

出力::あなたは(累積)の値を合計したい場合

TEST 1: 1 
TEST a: 0 
TEST A: 13457492 
TEST b: 98 

http://msdn.microsoft.com/en-us/library/yd5xkb5c%28v=vs.80%29.aspx

でより多くのチェックアウト、あなたは違いを見ることができるように私は両方のバージョンを残してきましたそのようなことに不思議なSTLレンジ機能をチェックすることをお勧めします。例えば

#include <numeric> 
#include <string> 

printf("TEST a: %d \n", *_T("a")); // 97 
printf("TEST b: %d \n", *_T("b")); // 98 

wstring uString(_T("ba")); 
int result = accumulate(uString.begin(), uString.end(), 0); 
printf("TEST accumulated: %d \n", result); 

結果:

TEST a: 97 
TEST b: 98 
TEST accumulated: 195 

この方法であなたは、forループのすべての値を通過する必要はありません。範囲関数は実際にこのようなものにはうってつけです。

以上でご覧ください:http://www.sgi.com/tech/stl/accumulate.html

+0

thx、それを見逃して、答えを更新しました – AzP

+0

+1 std :: accumulate –

0

intenedが既にYlisarによって回答されているようのprintf が動作しない理由は最初の質問を。文字の16進表現の合計についてのもう1つの質問はもう少し複雑です。指定された文字列が "123"のような数字を123に変換した場合にのみ_tstoi()関数で文字列から数値への変換が機能します。文字表現の合計が必要です。

0x7F(0 ... 127)より小さいUnicodeコードポイントの場合、これは単純に1バイトのUTF-8表現の合計です。しかし、UNICODEフラグでコンパイルされたWindowsでは、1文字あたり2バイトの表現が使用されます。デバッガで次のコードを実行すると、これが反映されます。関心のおそらく

// ASCII 1 Byte per character 
const char* letterA = "A"; 
int sumOfLetterA = letterA[0] + letterA[0]; // gives 130 

// 2 Bytes per character (Windows) 
const wchar_t* letterB = TEXT("B"); 
int sumOfLetterB = letterB[0] + letterB[0]; // gives 132 
+0

Windows _always_は2バイトのUnicode表現を 'WCHAR'に使用し、_always_は1バイトのASCII +エンコーディングを' char'に使用します。 'UNICODE'マクロは' TCHAR'型定義と関数マクロの束を変更します。 – MSalters

+0

はい私は十分正確ではありませんが、 "UNICODEフラグ付きでコンパイルされた"と言い、文字列がマクロL()またはT()のいずれかで生成されるという仮定は2バイトです。 –

関連する問題