C++初心者の困りごと!ハードウェアからの文字列受信で文字化けしてしまう問題

このQ&Aのポイント
  • C++初心者がJavaから呼び出したC++プログラムでハードウェアから文字列を受け取る際に文字化けが発生してしまう問題に困っています。
  • 現在の状況としては、C++プロジェクトのプロパティでマルチバイト文字を使用する設定をした上で、ハードウェアにコマンドを送信し、結果を文字列として取得しています。
  • しかし、取得した文字列が文字化けしてしまい、正常な結果を得ることができません。WideCharToMultiByteの使い方に問題がある可能性がありますが、解決策がわかりません。助けていただけると幸いです。
回答を見る
  • ベストアンサー

C++ ハードウェアから文字列受信 文字化け

C++初心者のため大変困っております。 正直に申し上げますと、だれか助けて下さい。 どなたかご教授宜しくお願いいたします。 まずは簡単な仕様から JavaでC++を呼び出し、C++でハードウェアを動かします ハードウェアから文字列を受け取り、Javaに返すというプログラムを開発しております。 以下に現在の状況を示します ・C++のプロジェクト→プロパティ→マルチバイト文字を使用する にチェックを入れました ・ソースです↓ 以下をJavaから呼び出し、戻り値を取得しています printfがたくさんありますが、文字列をチェックするためのものです。ご了承ください。 JNIEXPORT jstring JNICALL Java_rewritecard_JNI001_DT(JNIEnv *env, jobject obj) { BSTR s1 = ::SysAllocString(L"s1"); BSTR s2 = ::SysAllocString(L"s2"); BSTR s3 = ::SysAllocString(L"s3");     //ハードウェアにコマンドを送信する関数です     //レスポンスが、s3のアドレスに格納されます。      crwSendCommandRR(           4,        //ポート番号           1,        //ポーリングフラグ           10000,     //タイマー           0,        //タイマー           1,        //DSR信号線チェックフラグ           "DT",     //コマンドコード           ":1",      //ハードウェアに送信するパラメータ           2,        //パラメータの長さ           &s1,      //レスポンスを格納するアドレス 1            &s2,      //レスポンスを格納するアドレス 2           &s3      //レスポンスを格納するアドレス 3    ); printf("s3:\n", s3); printf("s3:%d\n", s3); printf("s3:%x\n", s3); printf("s3:%s\n", s3); //BSTR を char に変換---------------------------------------------- char buf[64]=""; WideCharToMultiByte( CP_ACP,           // コードページ ANSI コードページ WC_NO_BEST_FIT_CHARS,// 処理速度とマッピング方法を決定するフラグ (OLECHAR*)s3,      // ワイド文字列のアドレス -1,             // ワイド文字列の文字数 buf,            // 新しい文字列を受け取るバッファのアドレス sizeof(buf) - 1,    // 新しい文字列を受け取るバッファのサイズ NULL,          // マップできない文字の既定値のアドレス NULL           // 既定の文字を使ったときにセットするフラグのアドレス ); int len = strlen(buf); for(int i = 0; i < len; i++) { printf("\nbuf:", buf[i]); printf("\nbuf:%d", buf[i]); printf("\nbuf:%x", buf[i]); } char* src = buf; printf("\nsrc:",src); printf("\nsrc:%d",src); printf("\nsrc:%x",src); printf("\nsrc:%s",src); jstring jstr = env->NewStringUTF(src); printf("\njstr:", jstr); printf("\njstr:%d", jstr); printf("\njstr:%x", jstr); printf("\njstr:%s", jstr); ::SysFreeString(s1); ::SysFreeString(s2); ::SysFreeString(s3); return jstr; } ・実行結果 Java側 ?????   //?になります。本来なら 1:19900309 C++側  s3: s3:3150196 s3:301174 s3:1:19900309 c: c:3150196 c:301174 c:1:19900309 buf: buf:63 buf:3f buf: buf:63 buf:3f buf: buf:63 buf:3f buf: buf:63 buf:3f src: src:71756992 src:446ecc0 src:???? jstr: jstr:65927816 jstr:3edfa88 jstr:Pァ$@ヌ#@ヌ#@ヌ#(CO どうもWideCharToMultiByteの使い方が悪いのかと思うんですが C++初心者のため、どこがどうおかしいのか答えが出せずにおります 他に何かございましたら補足致しますので宜しくお願い致します。

質問者が選んだベストアンサー

  • ベストアンサー
  • wormhole
  • ベストアンサー率28% (1621/5657)
回答No.1

実行結果の >s3:1:19900309 からするとs3はWideCharToMultiByte()を使うまでもなくマルチバイトキャラクターだと思いますが。 s3がワイドキャラクターならprintf()ではまともに出力できませんから。 そこから考えるとcrwSendCommandRR()の使い方も間違ってそうな気がします。 >C++初心者のため大変困っております。 内容からするとC++はあんまり関係ないと思う(C++の機能ぽいのほとんど使われてないし) ひとまず ・ハードウェアから文字列受信 ・JNIを使ってCからJavaに文字列を渡す のをそれぞれに出来るようにしてから組み合わせた方がいいと思いますよ。

pokeman-v
質問者

お礼

ご回答ありがとうございます たしかに仕様書には BSTR* 32ビットの文字ポインタ としか書いてありませんでした。 どこかで勘違いをしていたと思います。 ありがとうございます。 ・ハードウェアからの文字列受信 ・JNIを使ってCからJavaに文字列を渡す どちらも簡易的に行いましたが BSTRが絡むと急にできなくなります。 BSTRについてもう少し調べてみようと思います ありがとうございます。

pokeman-v
質問者

補足

ああ・・・ わたしは何とバカなことを・・・ 以下のような簡単な処理で解決いたしました・・・ ご回答ありがとうございました。 やはりWideChartoなんたらは使う必要がなかったです。 ありがとうございました。 JNIEXPORT jstring JNICALL Java_rewritecard_JNI001_DT(JNIEnv *env, jobject obj) { BSTR s1 = ::SysAllocString(L"s1"); BSTR s2 = ::SysAllocString(L"s2"); BSTR s3 = ::SysAllocString(L"s3"); ret = crwSendCommandRR(4,1,10000,0,1,"DT",":1",2,&s1,&s2,&s3); printf("s3:\n", s3); printf("s3:%d\n", s3); printf("s3:%x\n", s3); printf("s3:%s\n", s3); //BSTR を char に変換---------------------------------------------- char* src = (char*)s3;   ←これだけ!!!!!!! printf("\nsrc:",src); printf("\nsrc:%d",src); printf("\nsrc:%x",src); printf("\nsrc:%s",src); jstring jstr = env->NewStringUTF(src); printf("\njstr:", jstr); printf("\njstr:%d", jstr); printf("\njstr:%x", jstr); printf("\njstr:%s", jstr); ::SysFreeString(s1); ::SysFreeString(s2); ::SysFreeString(s3); return jstr; } java側 1:19900309 C++側  s3: s3:1898084 s3:1cf664 s3:1:19900309 c: c:1898084 c:1cf664 c:1:19900309 check src: src:1898084 src:1cf664 src:1:19900309 jstr: jstr:66212024 jstr:3f250b8 jstr:弄$@ヌ#@ヌ#@ヌ#(CO

その他の回答 (1)

  • wormhole
  • ベストアンサー率28% (1621/5657)
回答No.2

>以下のような簡単な処理で解決いたしました・・・ 解決したと思われてるようですが >char* src = (char*)s3;   ←これだけ!!!!!!! 上記で済んでWideCharToMultiByte()を使う必要がないということは crwSendCommandRR()は第11引数にBSTR*を要求してるにもかかわらずBSTRでないものを格納している(正しいBSTRならワイドキャラクタ文字列なのでWideCharToMultiByte()を使う必要がある)ということなので crwSendCommandRR()の処理がおかしいということになりますが・・・ crwSendCommandRR()を作成された方に仕様を確認した方がよいと思いますよ。

関連するQ&A

  • 空白を含んだ文字列がうまく格納(表示)できない

    こんにちわ。 空白(スペース)の入った文字列の格納(表示)について質問させてください。 以下のプログラムを実行すると、空白の含む文字列がうまく表示されません。 例えば、 in the worldと入力しても、inしか格納されていないみたいです。それはなぜでしょうか? また、どうすればそれを格納、表示させることができるのでしょうか?教えてください。よろしくお願いいたします。 #include <stdio.h> #include <string.h> main() { char buf[BUFSIZ]; char moji[31]; int i; printf("Input string: "); fgets(buf, sizeof(buf), stdin); moji[31] = '?0'; sscanf(buf, "%s", moji); i = 0; while (moji[i] != '?0') { printf("%c",moji[i]); i = i + 1; } printf("?n"); printf("%d letters?n", i); } 【実行例】 csx01:~> gcc prog.c csx01:~> a.out Input string: in the world in 2 letters

  • Cの文字列関連の質問です。よろしくお願いします。

    Cの文字列関連の質問です。よろしくお願いします。 『読み込んだ文字列がナル文字を含めて15文字以下であれば、その文字列をそのまま格納し、そうでない場合、読み込んだ文字列の先頭14文字とナル文字を格納する』 という条件を満たすプログラムを作成しました。 #include <stdlib.h> #include <string.h> #include <stdio.h> int main(void) { int num; char (*p)[15]; printf("文字列の個数: "); scanf("%d", &num); p = (char (*)[15])malloc(num * 15); if (p == NULL) puts("記憶域の確保に失敗"); else { int i; char tmp[100]; /* 書込み */ for (i = 0; i < num; i++) { printf("p[%d]: ", i); scanf("%s", tmp); sprintf(p[i], "%.14s", tmp); } /* 表示 */ for (i = 0; i < num; i++) printf("p[%d]: %s\n", i, p[i]); free(p); } return 0; } この場合は、ちゃんと条件を満たした結果が出ました。 ここで24行目の『sprintf(p[i], "%.14s", tmp);』を『strncpy(p[i], tmp, 14);』に変更する明らかに結果がおかしくなります。 strncpyを使った方法に変更する場合、どのように修正を行えばいいのでしょうか? 長々と書いてしまいましたが、よろしくお願い致します。

  • 文字列を後ろから1文字ずつ表示する

    初歩的なプログラミングです。 C言語の勉強中で、タイトルの通りの プログラムを作りたいのですが、 何かヒントを頂けないでしょうか。 自分で書いてみて失敗したのは下記の 通りです。 char s[11]; int i=0; printf("文字列入力(10文字以内-->)"); gets(s); printf("s=%s",s); while(s[i]!='\0'){ i++; } while(i=0){ printf("%c\n",s[i-1]); i--; } 宜しくお願いします。

  • 文字列の比較に関する質問

    文字列をif文で比較したいのですが、まず下記の例だと char *a a="a"; if(a=="a"){ printf("等しい"); }else{ printf("等しくない"); } 文字列は等しくなるのですが下記の例ではなりません 何故なのでしょうか。 read(s_sock,&buf,sizeof(buf)) if(a=="GET"){ printf("TRUE") }else{ printf("FALSE"); }

  • C言語 文字列格納

    テキストファイルから整数データ又は文字列を読み込んで配列に格納する動作についての質問です。 テキストファイルが1行区切りの整数型なら1次元配列で for(i = 0; i < maxSize; i++) { fscanf(fp,"%d", &data[i]); } テキストファイルが1行区切りの文字列なら2次元配列で for(i = 0; i < MAXSIZE; i++) { if (fscanf(fp,"%s", &data[i][300]) == EOF) break; } for(j = 0; j < i; j++) printf("%s\n", data[j]); みたいな具合に格納できたんですが、 テキストファイルが1行区切りのデータではなく、空白文字区切りの文字データだった場合、それぞれどのようにして配列に格納すればいいかがわかりません。 イメージとしては、1文字目から見ていって空白が出ればそこで切って格納していくというかんじなのですが・・・ 質問の内容がわかりにくいかもしれませんが、是非教えてください。お願いします。

  • Cでは文字列をどのように認識するのでしょうか?

    C言語には文字列型というものは存在しないと教わりました。 文字列の終わりはヌル文字で認識できますが、 文字列型というものが存在しないのに何故次のバイトを読もうとするのですか? たとえばchar str[] = "abc";、あるいはchar *p = "abc";とあったとして printf(str);あるいはprintf(p); でなぜabcが出力されるのでしょうか?なぜaの次にbがbの次にcがあるとわかるのでしょうか? char型で先頭アドレスが渡された場合、ヌル文字を見つけるまでアドレスをインクリメントし続けるという決まりでもあるのでしょうか? それに文字列型というものが存在しないなら''と""を分ける意味もないのでは??

  • C言語の課題で困っています;

    C言語の課題で困ってます; 学校の課題で、キーボードから文字を入力する(最大80文字)。入力された文字列と、入力した文字列を逆順にした文字列を表示する。(malloc,freeを使って作成して下さい) ヒントで #invlude <stdio.h> void main(void){ char *buf; //入力文字列用 char *seq; //入力文字列用コピー用 char *rev; //逆順文字列用 int lec, i; buf =(char*)malloc(81); printf("文字列を入力:"); scanf("%s"buf ); for(i = 0; buf[i] ??? '\0'; i++){ } Ien = i; /* lenに文字列の長さが入る */ seq = ???(??? + 1); /* len+1文字文確保*/ for(i = 0; ???; i++){ seq[0] = buf[0]; } free(buf); rey = ???(len + 1); for(i = 0; < len; i++){ rev[len - i - 1] = seq[i]; } ren[i] ~ '\0'; printd("入力文字列 : %s\n",sep); でたんですが、全然分からなくて足りない部分の答えを教えてもらえると助かります;

  • createTextNode実行後の文字化けについて

    こんにちは。現在、XMLファイルをC++で変換し、HTMLファイルを生成するプログラムを作成しています。(2)のソースから(1)の関数を呼んで文字列の変換を行った後、テキスト要素の作成、追加を行っていますが、「全角文字列」という文字列が「蜈ィ隗呈枚蟄怜・」と出力されてしまいます。解決方法についてご教示願います。 (1)BSTR AsciiToBSTR(const char* ascstr)  {   WCHAR wszURL[MAX_PATH];   ::MultiByteToWideChar(CP_ACP, 0, ascstr, -1, wszURL, MAX_PATH);   return SysAllocString(wszURL);  } (2)  IXMLDOMDocument* pHTMLDoc  IXMLDOMNode * pNewNode;  BSTR bstrText;  bstrText = AsciiToBSTR("全角文字列");  pDoc->createTextNode(bstrText, &pNewNode);  pHTMLDoc->appendChild(pNewNode, NULL);

  • C言語 説明文

    C言語(文字列のコピーについて) /* 文字列のコピーを行う関数の実現例 動作原理のコメントを書き入れる */ #include <stdio.h> /*-----文字列のコピー(1)-----*/ char *scpy1 (char *d, const char *s) { int i = 0; while ((d[i] = s[i]) != '\0') { i++; } return(d); } /*-----文字列のコピー(2)-----*/ char *scpy2 (char *d, const char *s) { char *p = d; while ((*d = *s) != '\0') { d++; s++; } return(p); } /*-----文字列のコピー(3)-----*/ char *scpy3 (char *d, const char *s) { char *p = d; while ((*d++ = *s++) != '\0') { ; } return(p); } /*-----文字列のコピー(4)-----*/ char *scpy4 (char *d, const char *s) { char *p = d; while (*d++ = *s++) { ; } return(p); } int main(void) { char astr[] = "ABC"; char bstr[8], cstr[8], dstr[8],estr[8]; scpy1 (bstr, astr); scpy2 (cstr, astr); scpy3 (dstr, astr); scpy4 (estr, astr); printf("astr = %s\n" , astr); printf("bstr = %s\n" , bstr); printf("cstr = %s\n" , cstr); printf("dstr = %s\n" , dstr); printf("estr = %s\n" , estr); return (0); } ----------------------- このプログラムに、この行で何をやっているのかわかるように 一言くらいの説明文を入れる問題です。 ところどころはわかるのですが、わからないところの方が多いです。 プログラムが長くて大変かとは思いますが、どうかよろしくお願いいたします。 このプログラム自体はちゃんとコンパイルでき、実行もできたので おそらく間違いないと思います。

  • C言語の文字列の取り扱いが分かりません

    こんにちは。 C言語で分からないことがあり、質問させていただきました。 学校で、文字列の取り扱いを習いました。 そこで質問なんですが、以下のソースコードをstrcpy , strcat , strcmp , strlen を使わずに書くことってできないですか? 先生に質問したところ、ポインタとかいうのを使うのだそうですが、それを使わずに書くことってできるんですか?もしよろしければお願いします。 以下のプログラムですが、ユーザーから2つの文字列を受けて、そこから4つの文字列関数を使ってみましょう、というやつです。実行結果も貼っておきますね。 #include <string.h> #include <stdio.h> int main(void) { char str1[80], str2[80]; int i; printf("INPUT 1st word-line. : "); gets(str1); printf("INPUT 2nd word-line. : "); gets(str2); /*文字列(word-line)の長さを確認します。*/ printf("%s is %d moji long.\n", str1, strlen(str1)); printf("%s is %d moji long.\n", str2, strlen(str2)); /*文字列を比較します。*/ i = strcmp(str1, str2); if (!i) printf("two word-lines are same length.\n"); else if (i < 0) printf("%s is smaller than %s.\n", str1, str2); else printf("%s is bigger than %s.\n", str1, str2); /*十分なスペースがあるのなら、str2をstr1の最後に結合させます。*/ if((strlen(str1) + strlen(str2)) < 80 ){ strcat(str1, str2); printf("%s\n", str1); } /*str2をstr1にコピーする*/ strcpy(str1, str2); printf("%s %s\n", str1, str2);

専門家に質問してみよう