• 締切済み

UTF_16で取得しUTF_8で出力したい!!

こんにちは。 C言語初心者です。以前この件で質問させていただいたのですがエラーがとれず、もう一度質問してしまいました。 今回は、C言語でレジストリからデータをUTF_16で取得し、UTF_8で表示すると言うプログラミングを組みたいのですがどうしても下記のコードではエラーが出てしまいどうしていいかわかりません。 エラーの内容としては、16から8に変換する部分のutf8Sizeの部分で上手くいっていないようで、、、 どうしたらいいかわからないので、もし知っている方がいればよろしくお願いします。 #include<windows.h> #include<stdio.h> void QueryValue(void); int main(void){    QueryValue();    return 0; } void QueryValue(void){    HKEY hkey;    DWORD ValueType;    DWORD ValueSize;    wchar_t Value[1000];    char *utf8String = 0; // UTF-8 文字列バッファへのポインタ    size_t utf8Size = 0; // UTF-8 文字列のバイト数 (終端 NUL 含む) int result; // WideCharToMultiByte() の戻り値    /*レジストリキーのオープン*/    RegOpenKeyEx(      HKEY_LOCAL_MACHINE,         L"SOFTWARE\\Hitachi\\JP1/RemoteControlManager",      0,      KEY_ALL_ACCESS,      &hkey);     ValueSize = 1000;   /*レジストリ値の取得*/    RegQueryValueEx(      hkey,      L"ProgramName",      NULL,      &ValueType,      (LPBYTE)Value,      &ValueSize);    /*結果の表示(シフトJIS変換’%S’)*/    if(ValueType == REG_SZ) printf("%S\n",Value);    else printf("....can't read\n"); /*****************************************************/    //UTF_16からUTF_8変換を行う    result = WideCharToMultiByte(      CP_UTF8,      WC_NO_BEST_FIT_CHARS,      Value,      -1,      utf8String,      utf8Size,      NULL,      NULL);    if(result <= 0){      fprintf(stderr,"UTF_16→UTF_8変換エラー(%lu)\n",GetLastError());    }    /*結果の表示()*/    if(ValueType == REG_SZ) printf("%s\n",utf8String);    else printf("....can't read\n");    /*UTF_8文字列バッファを開放する*/    free(utf8String); /************************************************/    /*終了*/    RegCloseKey(hkey); }

noname#153284
noname#153284

みんなの回答

  • noocyte
  • ベストアンサー率58% (171/291)
回答No.3

あのーーー 前回の回答をちゃんと理解してコードを書いてますか? http://oshiete.nikkeibp.co.jp/qa3405779.html >   /*結果の表示(シフトJIS変換’%S’)*/ >   if(ValueType == REG_SZ) printf("%S\n",Value); >   else printf("....can't read\n"); シフト JIS じゃなくて UTF-8 で表示したいんじゃなかったの? > /*****************************************************/ >    //UTF_16からUTF_8変換を行う UTF-8 文字列用のバッファを確保してないし…. >   /*結果の表示()*/ >   if(ValueType == REG_SZ) printf("%s\n",utf8String); Value が REG_SZ 型であることを確認する前に UTF-16 → UTF-8 変換しようとしてるし…. /*--------------------------------------------------------------------------*/ #include <windows.h> #include <stdio.h> int QueryValue(HKEY rootKey, const wchar_t *subKeyName, const wchar_t *valueName) {  HKEY hkey = NULL;  DWORD valueType, valueSize;  wchar_t value[1000];  char *utf8String = NULL;  size_t utf8Size;  LONG result;  result = RegOpenKeyEx(rootKey, subKeyName, 0, KEY_READ, &hkey);  if(result != ERROR_SUCCESS) {   fprintf(stderr, "RegOpenKeyEx() 失敗 (%ld)\n", result);   goto Error;  }  result = RegQueryValueEx(hkey, valueName, NULL, &valueType, (BYTE*)value, &valueSize);  if(result != ERROR_SUCCESS) {   fprintf(stderr, "RegQueryValueEx() 失敗 (%ld)\n", result);   goto Error;  }  printf("valueType: %ld\n", valueType);  if(valueType == REG_SZ) {   // UTF-8 文字列のバイト数を取得する.   result = WideCharToMultiByte(CP_UTF8, 0, value, -1, NULL, 0, NULL, NULL);   if(result <= 0) {    fprintf(stderr, "UTF-8 文字列サイズ取得エラー (%ld)\n", GetLastError());    goto Error;   }   utf8Size = (size_t)result;   // UTF-8 文字列バッファを確保する.   if((utf8String = malloc(utf8Size)) == NULL) {    fprintf(stderr, "UTF-8 文字列バッファ確保エラー (%ld)\n", GetLastError());    goto Error;   }   // UTF-16 → UTF-8 変換を行う.   result = WideCharToMultiByte(CP_UTF8, 0, value, -1, utf8String, (int)utf8Size, NULL, NULL);   if(result <= 0) {    fprintf(stderr, "UTF-16 → UTF-8 変換エラー (%ld)\n", GetLastError());    goto Error;   }   // UTF-8 文字列を出力する.   printf("\"%s\"\n", utf8String);   free(utf8String);  } else {   fprintf(stderr, "Value は REG_SZ 型じゃないよ.\n");  }  RegCloseKey(hkey);  return 0; Error:  if(utf8String != NULL) free(utf8String);  if(hkey != NULL) RegCloseKey(hkey);  return -1; } int wmain(void) {  static const wchar_t rootKeyName[] = L"HKEY_LOCAL_MACHINE";  static const wchar_t subKeyName[] = L"SOFTWARE\\TrendMicro\\PC-cillin\\15\\WSC";  static const wchar_t valueName[] = L"PCC_Launch";  printf("%S\\%S\\%S\n", rootKeyName, subKeyName, valueName);  QueryValue(HKEY_LOCAL_MACHINE, subKeyName, valueName);  return EXIT_SUCCESS; } /*-------------------------------------------------------------------------- 実行結果 (UTF-8) --------------------------------------------------------------------------*/ HKEY_LOCAL_MACHINE\SOFTWARE\TrendMicro\PC-cillin\15\WSC\PCC_Launch valueType: 1 "ウイルスバスターを起動"

  • Wr5
  • ベストアンサー率53% (2177/4070)
回答No.2

> エラーの内容としては、16から8に変換する部分のutf8Sizeの部分で上手くいっていないようで、、、 MSDNちゃんと読みました? 第6引数に0を指定している(utf8Size = 0)ので、WideCharToMultiByte()の戻り値で必要なバイト数が返されます。 > cchMultiByte > lpMultiByteStr が指すバッファのサイズをバイト単位で指定します。0 を指定すると、バッファに必要なバイト数が返ります(その場合、lpMultiByteStr が指すバッファは使われません)。 > 戻り値 > cchMultiByte に 0 を指定して関数が成功すると、変換後の文字列を受け取るために必要なバッファのサイズ(バイト数)が返ります。 戻り値で指定されたサイズ以上のメモリを確保し、そのメモリの先頭アドレスを第5引数に、メモリのサイズを第6引数に入れて、再度呼び出します。    //UTF_16からUTF_8変換を行う    utf8Size = WideCharToMultiByte(      CP_UTF8,      WC_NO_BEST_FIT_CHARS,      Value,      -1,      NULL,      0,      NULL,      NULL);    utf8String = malloc(utf8Size);    result = WideCharToMultiByte(      CP_UTF8,      WC_NO_BEST_FIT_CHARS,      Value,      -1,      utf8String,      utf8Size,      NULL,      NULL);

  • SAYKA
  • ベストアンサー率34% (944/2776)
回答No.1

答えじゃないんだけれど iconv を利用するとか そういうのはダメかな?

関連するQ&A

  • 別ターミナルへのprintf出力

    LinuxでC言語プログラムから新しいターミナルを開き、そこにprintfで文字を出力したいのですがどうやったら良いのでしょうか?下記プログラムを作ってみましたが、新しいターミナルが開くだけで文字が出力されません #include <pthread.h> #include <stdio.h> #include <unistd.h> #include <signal.h> void* thread(void* arg) {  int pid=0;  pid = fork();  if(pid==0)  {    execlp("gnome-terminal","gnome-terminal",NULL);     printf("Hello World!!\n");  } } int main() {   pthread_t th;  void* result;   pthread_create(&th, NULL,thread, NULL);  pthread_join( th,&result); }

  • フィボナッチ数列

    C言語の問題です。 フィボナッチ数列について。 以下のプログラムはある整数を入力し、その整数以下のもっとも大きなフィボナッチ数列に含まれる整数を返すものである。 #include <stdio.h> int main(void){ int limit,new=1,pre=0,work result; scanf("%d", &limit); while(new<=limit){ /*printf("%d %d\n,pre,new);トレース用*/ work=new; new=work+pre; pre=work; } result =pre; printf("%d\n", result); } 以下を参考に、このプログラムの一部を関数にして書き換えなさい。 #include <stdio.h> /*ここに関数を記述*/ int main(void){ int limit,result; scanf("%d",&limit); result = fibnum(limit); printf("%d\n", result); } という問題です。 私は以下のように考えたのですが… #include <stdio.h> void fibnum(int limit){ int f0, f1; f0 = 0; f1 = 1; printf("%d\n", f0); printf("%d\n", f1); while(1){ f0 += f1; if (f0 > limit)return; printf("%d\n", f0); f1 += f0; if (f1 > limit)return; printf("%d\n", f1); } } int main(void){ int limit, result; scanf("%d",&limit); result = fibnum(limit); printf("%d\n", result); return result; } 実行すると 「S:\デスクトップ\v\v.cpp(30) : error C2440: '=' : 'void' から 'int' に変換することはできません。(新しい動作 ; ヘルプを参照) void 型の式は他の型へ変換できません。 cl.exe の実行エラー」 と出てきてしまいます。 考えてみたのですが、エラーの理由がよくわかりません。 どこが間違っているのかなど、ご指摘いただければ嬉しいです。

  • cygwinを使ってcsvファイルを読み込み、出力させようとしています

    cygwinを使ってcsvファイルを読み込み、出力させようとしています。 とりあえず、読み込みのみのプログラムを作成し、 実行させてみたのですが(run ファイル名.csv と入力) 「Error: could not start C:\cygwin\home\ユーザー名ファイル名.csv」 と出力され、読み込みができず、困っています。 プログラム初心者です。 恐縮ですがご回答よろしくお願いします。 以下に、読み込みプログラムとcsvファイルを記載します。 (プログラムは拾い物です。) <プログラム> #include <stdio.h> #define MAX_ITEM_SIZE 100 #define MAX_LINE_SIZE 1024 char *GetCSVItem(char *wp, char *buff, int size); void main(int argc, char *argv[]) { FILE *fp; char buff[MAX_LINE_SIZE], *wp, item[3][MAX_ITEM_SIZE]; int i1, len; if(argc != 2){ printf("comand error nyuuryoku keishiki\n"); return; } fp = fopen(argv[1], "r"); if(fp == NULL){ printf("can not open file[%s].\n", argv[1]); return; } for(;;){ if(fgets(buff, MAX_LINE_SIZE, fp) == NULL) break; len = strlen(buff); if(len == 0 || buff[len-1] != '\n'){ if(feof(fp) == 0){ printf("data error[%s].\n", buff); return; } } buff[len-1] = '\0'; wp = buff; if((wp = GetCSVItem(wp, item[0], MAX_ITEM_SIZE)) == NULL){ printf("error(1)\n"); break; } if((wp = GetCSVItem(wp, item[1], MAX_ITEM_SIZE)) == NULL){ printf("error(2)\n"); break; } if((wp = GetCSVItem(wp, item[2], MAX_ITEM_SIZE)) == NULL){ printf("error(3)\n"); break; } if(*wp != '\0'){ printf("error(4)\n"); break; } for(i1 = 0; i1 < 3; i1++){ printf("%d:%s\n", i1+1, item[i1]); } } fclose(fp); } char *GetCSVItem(char *wp, char *buff, int size) { int i1; buff[0] = '\0'; while(*wp == ' ' || *wp == '\t') wp++; if(*wp == '\0'){ return(NULL); } for(i1 = 0; i1 < MAX_ITEM_SIZE; i1++, wp++){ if(i1 >= size) return(NULL); buff[i1] = *wp; if(*wp == '\0'){ buff[i1] = '\0'; return(wp); } if(*wp == ','){ wp++; buff[i1] = '\0'; break; } } return(wp); } <csvファイル> 1,2,3 11,12,13 21,22,23

  • ポインタと配列

    次のソースで、結果表示でポインタを使いたいのですが、うまくいきません。1件しか表示されないのです。 ポインタの扱いがおかしいのだと思いますが、どうしたらよいでしょうか? #include <stdio.h> #include <string.h> int search(char key[256],FILE *fp,char *result[256][256]); main(void) { FILE *fp; int rep,n,i; char x[256],key[256],*result[256][256]; printf("検索キーワードを入力してください。\n" "キーワード>"); gets(key); if((fp=fopen("personal.txt","r"))==NULL) { printf("ファイルをオープンできません\n"); exit(1); } printf("=====検索結果=====\n"); n=search(key,fp,result); for(i=0;i<n;i++) { printf("%s\n",result[i]); } printf("検索結果:%d件です。\n",n); fclose(fp); } int search(char key[256],FILE *fp,char *result[256][256]) { int n=0; char *p,word[256],*name; while((p=fgets(word,256,fp))!=NULL) { if(strstr(word,key)!=NULL) { name=strtok(p," "); strcpy(result[n],name); n++; } } return n; } 実行すると、下の警告がでます。 illegal pointer combination(param)

  • NSString文字列をprintfで出力するには

    Objective-CでNSStringクラスの文字列をprintf関数で出力しようとするとコンパイルエラーになります。 どうすればprintfで出力できるようになるでしょうか。 実行環境はMacOSX。Xcodeをインストールしています。 ソースコードとエラーメッセージは以下です。 #import <Foundation/NSObject.h> #import <stdio.h> int main(void){ NSString *str01 = @"test"; printf("%s\n", [str01 UTF8String]); return 0; } <コンパイルエラーメッセージ> warning: format ‘%s’ expects type ‘char *’, but argument 2 has type ‘id’

  • strtokでの空文字への置き換え

    大したことじゃないと言えばそうかもしれませんが、ちょっと氣になるんで質問させてください。 C言語でstrtokという函數ありますよね。 第1引數の文字列を、第2引數の文字列を構成する文字で區切る。 第2引數の文字を見つけたら、それを空文字('¥0')に置き換える。 字句の最初の文字へのポインタを返す。 このようなものだと理解しています。 次のプログラムを實行してみました。 #include <stdio.h> #include <string.h> int main(void) { char string[]="XYZ1231ABC"; int i; printf("%s\n", string); putchar('\n'); printf("%s\n", strtok(string, "1A")); printf("%s\n", strtok(NULL, "1A")); printf("%s\n", strtok(NULL, "1A")); printf("%s\n", strtok(NULL, "1A")); putchar('\n'); for(i=0; i<=10; i++) printf("string[%d]=%c\n", i, string[i]); return 0; } 結果 XYZ1231ABC XYZ 23 BC (null) string[0]=X string[1]=Y string[2]=Z string[3]= string[4]=2 string[5]=3 string[6]= string[7]=A string[8]=B string[9]=C string[10]= 私が思うには、string[7]は空文字に置き換わってしまうはずだと思うんですが、 結果は'A'のままです。 ここが '¥0'に置き換わるかどうかは しょり系によって異なるのでしょうか。

  • C言語 ファイルの出力

    こんにちは。 現在C言語学習中でファイルの出力でエラーが発生したのですが、どのようにエラーを起こしているのかわかりません。 ご指摘をお願いします。 #include<stdio.h> int main(void) { FILE *fp = NULL; fp = fopen("test1.txt", "w"); if(fp == NULL){ printf("ファイルをオープンでいませんでした。\n"); return -1; } else{ printf("ファイルをオープンしました。\n"); } fputs("Hello!\n", fp); fputs("Hello World!\n", fp); printf("ファイルに書き込みました。\n"); fclose(fp); printf("ファイルをクローズしました。\n"); int i; scanf("%d", &i); return 0; } エラーの内容は 1>LINK : fatal error LNK1104: ファイル 'C:\Users\拓哉\Documents\Visual Studio 2010\Projects\sample.c\Debug\sample.c.exe' を開くことができません です。現在使用中のC言語環境は上記の通り、Visual Studio 2010です。 学習仕立てで、あまりプログラミングについて知りません。 よろしければ、他に何か間違いがあればご指摘お願いします。

  • 長い文字列を配列に入れるには?

    VBから長い文字列を送って,c言語で受け取りたいのですが,うまく配列に入れることが出来ません.文字列サイズは最低でも4000バイト必要です. #include <stdio.h> #include <stdlib.h> #include <string.h> //VBから送られてくるデータ char getch[4000]="start1T\tpose 0 0 -5 0 -5 0 -5 0 -5 0 0 0 0 0\ ..省略.. 25\t\n"; void main(void){ char *token; char seps[]="\t\n"; FILE *pose; pose=fopen("pose.txt","a"); if((token=strtok(getch,"\t"))==NULL){ printf("Error File1\n"); exit(1); } printf("%s\n",token); while(strcmp(token,"\n")!=0){ token=strtok(NULL,"\t"); fputs(token,pose); fputs("\n",pose); printf("%s\n",token); } fclose(pose); }

  • UTF-8とUTF-16について質問です。

    まず、【あ】という文字をUTF-16というエンコーディング方式で バイト配列化すると [0] => 66 [1] => 48 というバイト値が帰ってきます。 これはとりあえずC#で処理を行いました。 Encoding encode = Encoding.GetEncoding("UTF-16"); String value = "あ"; Byte [] byteData = encode.GetBytes(value); それでは【あ】という文字の文字集合のコードポイントは右記となります。【0x3042】 これは、出力された 66、48という数値を16進数に変換すると 66=>42 48=>30 となり、リトルエンディアン環境で 0x4230という16進数であらわされるようです。 この点も不思議なのですが今回知りたいのはUTF-16でエンコーディングされた バイト配列はこのように文字集合のコードポイントに復帰?させることができますよね? ではUTF-8でエンコーディングされた【あ】という文字の バイト配列 [0] => 227 [1] => 129 [2] => 130 というバイト配列を上記のような文字集合のコードポイントの値へ復帰させることは できるのでしょうか? それに伴いUTF-8でつかわれる文字集合もUTF-16と同じコードポイントなのでしょうか? 上記 1.UTF-8でエンコーディングされた文字列をバイト配列にした場合 元の文字集合に戻せるのか?戻せるならばその戻し方は? 2.UTF-8がさす文字集合とUTF-16がさす文字集合はおなじものですよね? 上記二点よろしくご教授ください。

  • WinInetのInternetOpenUrl関数が正常に動作しない。

    ネットワーク上のHTMLソースを取得しようとしています。InternetOpenUrl関数が動作せず、常にNULLが返ってきます。 環境は、WindowsXP、WindowsCE Platform Builder です。 void Get_HTML(){ HINTERNET hInternet; HINTERNET hFile; char Buff[1000]; DWORD ReadSize; BOOL bResult; //WinInetの初期化 char *agent ="WININET Sample Program"; hInternet = InternetOpen( (LPCWSTR)agent, INTERNET_OPEN_TYPE_DIRECT, NULL, NULL, 0 ); if( hInternet == NULL ){ printf("InternetOpen Error \n"); } //ネット接続チェック if( InternetAttemptConnect(0) != ERROR_SUCCESS { printf("インターネットに接続できません。\n"); } else{ printf("インターネットに接続できる\n"); } //URLオープン char open_url="http://www.sample.com/sam1.html"; hFile = InternetOpenUrl( hInternet, (LPCWSTR)open_url, NULL, 0, INTERNET_FLAG_RELOAD, 0 ); printf("%s",(LPCWSTR)open_url); if( hFile == NULL ){ printf(" InternetOpenUrl ERROR \n"); } } InternetOpenUrl関数の戻り値がNULLになりReadを することが出来ません。 解決方法よろしくお願い致します。