• ベストアンサー

ユニコード文字の変換について

文字列が書かれたテキストファイルを読み込み、ユニコード部分だけを変換して画面に表示するプログラムを作りたいと思っています。 つまり、 \u305d\u306eaiueo と書かれたテキストファイルがあれば そのaiueo(←『\u305d』は『そ』、『\u306e』は『の』なので) と表示するプログラムを作りたいのですが、fgetsで読み込みprintfで表示するだけではそのまま「\u305d\u306eaiueo」となってしまい困っています。 \を文字(\\)として読み込んでるからだろうとは思うのですが… また、 char a[]="\u305d\u306eaiueo"; と定義した文字列を printf("%s",a); とすると「そのaiueo」と表示されますが、何故こちらは表示されて、前述の方法では表示されないのかも理解できていません。 どのような考え方、方法であれば解決するのでしょうか?

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

  • ベストアンサー
  • titokani
  • ベストアンサー率19% (341/1726)
回答No.5

>wchar_tやmbstowcs関数を使用して『\u305d』→『そ』が表現できるということなのでしょうか? mbstowcsは使いません。wchar_tは使います。 要するに、『\u305d』を自前で『そ』に変換するんです。 例えば、char *pに\のアドレスが入っているとすると、 if( *p == '\\' && *(p+1) == 'u' ){   p+=2; wchar_t wc=strtoul(p,&p,0); : : } とか、そうやって地味に変換するということです。

popokoku
質問者

お礼

諸事情で返答が遅れてしまいました、申し訳ありません。 strtoul()なんていう変換関数があったんですね、今回初めて知りました。 wchar_t wc=strtoul(p,&p,0); だと、「305d」の「d」が変換不可能な文字とみなされてしまったので、基数の0を16として wchar_t wc=strtoul(p,&p,16); setlocale(LC_ALL, ""); printf("%wc",wc); とした所、ちゃんと「そ」と画面に表示することができました。 お陰様で引っかかっていたものがスッキリしました。ありがとうございます!

その他の回答 (4)

  • jacta
  • ベストアンサー率26% (845/3158)
回答No.4

Visual C++では、国際文字名に相当する部分をいったんwchar_t型に格納してから多バイト文字に変換するのがよいでしょう。その際、ロケールを適切に設定してください。 なお、\u1234の形式であれば簡単ですが、\U00123456の形式の場合には、サロゲートペアに置き換えるなどしなければなりません。

popokoku
質問者

お礼

諸事情で返答が遅れてしまいました、申し訳ありません。 \u305dとは異なる形式もあるんですね。「サロゲートペア??」な状態だったので少し調べてみました。 「文字コードは5文字だけどデータは4バイト」 これにも対応するとなるとまた一手間かかりそうですね… 私はほとんど趣味の領域でプログラムを組んでるので対応しなくても全然問題ないですが、 開発者の方達はこういった環境のことも配慮しなくてはいけないとなると大変ですね。

  • jacta
  • ベストアンサー率26% (845/3158)
回答No.3

処理系に依存しない一般的な実現方法は、Unicodeの全ての文字に対応した表を作る方法だけです。 > char a[]="\u305d\u306eaiueo"; は国際文字名ですので、\nや??=などと同じで、コンパイル時に実行文字集合に変換されます。

popokoku
質問者

お礼

回答ありがとうございます。 >処理系に依存しない一般的な実現方法は、Unicodeの全ての文字に対応した表を作る方法だけです 処理系に依存しないことを考えるとなるとそこまでしないといけないとは… 全ての文字の対応表を作るとしたら本筋とは違う部分に力を注ぐことになりそうなので、今回は避けようと思います。

  • titokani
  • ベストアンサー率19% (341/1726)
回答No.2

\の処理はコンパイラがよろしくやってくれる処理です。 コンパイラはソースコードにかかれている文字列については処理してくれますが、さすがにテキストファイルにかかれている文字列の面倒まではみてくれません。 したがって自分のプログラムで処理しなくてはなりません。 一文字ずつ読みながらワイド文字に変換するのが楽だと思います。 あと、処理系が書かれていませんね。 VC++であれはprintfで直接ワイド文字列を出力できますが、他の処理系では一工夫いるかもしれません。

popokoku
質問者

お礼

回答ありがとうございます。 処理系ですが、Visual C++ 2008 Express Editionで処理しています。 「一文字ずつ読みながらワイド文字に変換」という部分をプログラムでどう表現してよいのかが、私の頭では思いつきませんでした。 wchar_tやmbstowcs関数を使用して『\u305d』→『そ』が表現できるということなのでしょうか? (作成してるプログラムの一部でユニコードで書かれたテキストファイルを読む必要が生じたため質問したのですが、改めてプログラム全体を試行錯誤した結果、ユニコードで書かれたテキストファイルの読み込みこむ必要性が無くなりそうです。 とはいえ、この問題を宙ぶらりんにするのも気持ちが悪いので、もしよろしければお教え下さい)

  • Tacosan
  • ベストアンサー率23% (3656/15482)
回答No.1

前者は想像の通りで, プログラムで a[] = "\\u305d\\306eaiueo"; と書いたのと結果的に同じですからねぇ. 後者はコンパイラがよろしくしています. ということで, 「\u+16進4桁」の部分を実際の値にすればいいんだけど, UTF-8 にしないとダメかなぁ? 後者の方で a[0] の値がわかればなんとかなるかもしれんけど....

popokoku
質問者

お礼

回答ありがとうございます。 コンパイラの関係で出力される表現が違っていたわけですか。 これまでソースとファイルに対する扱いは同じようなものだと勝手に思っていました。

関連するQ&A

  • 文字列の検索

    プログラミングの勉強の際に下のプログラムを作りました。 最初にある文字列を入力して、その後別の文字列を入力して、 後に入力した文字列が最初に入力した文字列に含まれていれば1、 含まれていなければ0と表示するプログラムです。 コンパイルは通るのですが、文字列を2つ入力すると 「セグメンテーション違反です」と表記されます… どこが悪いのでしょうか? どなたか解説・指摘・模範解答などおねがいします。 (使用するのは#include<stdio.h>のみ、ポインタ変数必須です) #include<stdio.h> char *mystrfin(char *a, char *b); int main(void) { char str1[100],str2[100]; printf("1>>"); fgets(str1,100,stdin); printf("2>>"); fgets(str2,100,stdin); *mystrfin(c,d); } char *mystrfin(char *a,char *b){ char *c,*d; while(*c!='\0'){ c=a; d=b; while(*c!='\0' && *d!='\0') if(*c!=*d) printf("0"); break; c++; d++; } if(*d='\0') printf("1"); a++; return a; return NULL; }

  • 文字列の検索

    先日同じ質問をして、プログラムの内容を修正したのですが、今度は2つ文字列を入力した後0が無限にでてきます… どなたか解説・指摘・模範解答などおねがいします。 内容は最初にある文字列を入力して、その後別の文字列を入力して、 後に入力した文字列が最初に入力した文字列に含まれていれば1、 含まれていなければ0と表示するプログラムです。 (使用するのは#include<stdio.h>のみ、ポインタ変数必須です) #include<stdio.h> char *mystrfin(char *a, char *b); int main(void) { char *c,*d; char str1[100],str2[100]; printf("1>>"); fgets(str1,100,stdin); printf("2>>"); fgets(str2,100,stdin); *mystrfin(c,d); } char *mystrfin(char *a,char *b){ char *c,*d; while(c!='\0'){ c=a; d=b; while(c!='\0' && d!='\0'){ if(c!=d) printf("0"); break; c++; d++; } } if(d='\0') printf("1"); a++; return a; return NULL; } 例 検索対象文字列:asdfghjkl 検索文字列:sdf 1と出力 検索対象文字列:asdfghjkl 検索文字列:qwer 0と出力

  • ユニコードへの変換について

    JavaScript で %82%A0 ・・・といったデコードされた 文字列から、ユニコード %u3042・・・ へ変換する 方法を教えてください。なにとぞお願いします。

  • fgets関数を使用したときの文字あふれについて

    fgets関数を用いて文字列を入力し、その長さを測るプログラムを作っています。 #include <stdio.h> #include <string.h> #define MAX 256 int main ( int, char *[] ); int main ( argc, argv ) int argc; char *argv[]; { char buf[( MAX )]; while ( 1 ){ memset ( buf, 0, sizeof( buf )); fgets ( buf, MAX, stdin ); if( fgets == NULL ){ break; } printf("入力した文字列の長さは%dです\n" ,strlen( buf )); } return 0; } このプログラムでは、256までしか文字列の長さを測ることができません。 もしこのプログラムで256を超える文字列を入力してしまうと、文字のあふれが発生し、 「入力した文字列の長さは256です」 「入力した文字列の長さは(あふれた文字列の長さ)です」 とこのようになってしまいます。 このプログラムで256以上の文字を読み捨てて、 「入力した文字列の長さは(あふれた文字列の長さ)です」 を表示しないようにできるのでしょうか? また読み捨てた文字列の長さを知ることはできるのでしょうか? もしかしたらfgets関数を使用すると不可能なのではないか?と思っています。 分かる方が居ましたらどうか教えて下さい。 よろしくお願いします。

  • unicode と shift_jis

    テキストファイルを読み込みデータを作成して出力するプログラムを作成しているのですが国際化させることになりました。そこで問題が‥テキストファイルが日本用はshift_jis、海外用はunicodeで構成されています。shift_jisでの文字列操作は良いとしてunicodeが全然わかりません。海外向けを想定したときに気をつけなければならないこともわかりません。なんでもいいので教えてください。お願いします。特に、unicodeの文字列操作はまったくよくわかりませんので細かい点から教えていただけると光栄です。よろしいお願いします。

  • Unicodeの文字がどれか、調べたいです

    ある文章をメモ帳で保存しようとしたら「このファイルはANCIテキストファイルで保存すると失われてしまうUnicode形式の文字を含んでいます。Unicodeの情報を保存するには、[文字コード]から[Unicode]を選択してください」と出ました。どれがUnicodeの文字なのかを調べる方法を探しましたが、アテになるのが全くありません。また、「[文字コード]から[Unicode]を選択する」という言葉の意味も分かりません。文字コード表を開きましたが、その後詰まりました。 限りなく分かりやすい説明をお願いします!

  • C言語でファイルから特定の文字を抽出

    現在C言語でプログラム開発しています。 文字列が並んだテキストファイルから特定の部分のみを抽出したいのですが、うまくいきません。 お力を貸していただけないでしょうか。 テキストファイルの構造はこんな感じです。 ーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーー 文字列 文字列 文字列badresult=*****文字列badresult=*****文字列badresult=*****文字列result=***** ーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーー これが10セット程記述されたファイルです。 ここから全てのbadresultの数値とresultの数値を抽出したいのです。 私が現段階で作成したプログラムがこちらです。 #include <stdio.h> #include <string.h> #include <stdlib.h> #define MAXLINE 2084 int main(void){ FILE *fp; char line[MAXLINE]; char s1[]="badresult"; char s2[]="result="; char *r; if ((fp = fopen( "テキストファイルへのダイレクトパス", "r" )) == NULL){ printf("エラーメッセージB\n"); exit(1); } while (fgets(line, MAXLINE, fp) != NULL){ if(strstr(line,s1)!=NULL){ printf("%.27s",strstr(line, s1),"\n"); printf(" "); printf(strstr(line, s2)); } } } ですがこれだと1行に全てのbadresultが含まれているため、結果は ----------------------------- badresult=***** result=****** ----------------------------- とbadresultは1つしか出てきません。 strstrのポインタをどうにかできないかと考えたのですが、 私のC言語の知識も浅いためなかなかうまくできません。 Cプログラミングに精通している方、どうか改善策を教えていただけないでしょうか。 できればなるべく簡単な方法ですと助かります。

  • 文字列の入力

    文字列(名前)と誕生日を読み込み、表示するプログラムです。文字列を読み込むときに空行を入力すると、読み込みを終了して表示するようにしたのですが、うまくいきません。読み込む時に使う関数が違うのだと思います。scanfとgets、fgetsは試したのですが、だめでした。 教えてください。 #include <stdio.h> #include <stdlib.h> #include <string.h> #define DATA 3 int main() { char *name[DATA]; char work[31]; int month[DATA]; int day[DATA]; int count1,count2; printf("Data #1\n"); printf("name ="); fgets(work,31,stdin); for(count1=0;(work[0]!='\n')&&(count1<DATA);count1++){ printf("month ="); scanf("%d",&month[count1]); printf("day ="); scanf("%d",&day[count1]); name[count1]=(char *)malloc((strlen(work)+1)*sizeof(char)); strcpy(*(name+count1),work); printf("\n"); if(count1<DATA-1){ printf("Data #%d\n",count1+2); printf("name ="); fgets(work,31,stdin); } } for(count2=0;(count2<DATA)&&(count2<count1);count2++){ printf("Data #%d\n",count2+1); printf(" name: %s\n",*(name+count2)); printf(" birthday: %2d %2d\n",month[count2],day[count2]); } }

  • Unicode

    先日は文字コードについて色々助言してくださりありがとうございました。 おかげさまでJIS,EUC,SJISの変換はできましたが、 Unicodeについて詰まっているところがあります。 SJIS→UnicodeはSJISにあったU+XXXXに変換し、 それを1~4バイトにさらに変換して文字表記されることで出来ます。 後者の1~4バイトにさらに変換するやり方は出来ているのですが、 前者のSJISにあったU+XXXXに変換するところで詰まっています。 ##SJIS Unicode Name Note 0x00 U+0000 # <control> 0x01 U+0001 # <control> 0x02 U+0002 # <control> 0x03 U+0003 # <control> 0x04 U+0004 # <control> 0x05 U+0005 # <control> 0x06 U+0006 # <control> 0x07 U+0007 # <control> : : こういった変換表(テキストファイル)があるのですが、 どのようにしたらこのファイルをプログラム上で操作? できるのでしょうか? 例)SJISで0x07→U+0007→1~4バイト変換の 0x07→U+0007部分についてです。 また、逆に変換する際の0x07←U+0007についても わからないでいます。 何かヒントをください。

  • 文字列変換のプログラムについて

    こんにちは。 C言語で以下のようなプログラムを作りたいと考えているのですが、うまく実装できず困っています。 入力ファイルには、【単語(ひらがな)+Tab+その読み(音素列)】が書かれているとします。 例: あいうえお(Tab)a i u e o かきくけこ(Tab)ka ki ku ke ko ・・・ (音素は半角空白で分けられているものとします) このファイルを読み込んで、【単語(ひらがな)+Tab+単語(カタカナ)+Tab+その読み(音素列)】を別のファイルに書き込む  例: あいうえお(Tab)アイウエオ(Tab)a i u e o かきくけこ(Tab)カキクケコ(Tab)ka ki ku ke ko ・・・ というプログラムを作りたいと考えています。 アルゴリズムとして、 (1) ファイルから1行読み込む (2) Tab文字がくるまでの文字列を配列に保存(例でいう「あいうえお」の部分です) (3) Tab文字の次の文字から行末までの文字列を配列に保存(例でいう「a i u e o」の部分です) (4) (2)の1文字ずつをカタカナに変換(ASCIIコードの変換で可能?) (5) (2)(3)(4)を用いて出力用ファイルに書きこむ という流れを考えたのですが、(2)の部分でまず手こずっています。 #include<stdio.h> main(){ FILE *fin; FILE *fout; char buff[200]; char word[200]; int i=0; /*読み込み用ファイルを開く*/ fin = fopen("input.txt", "r"); if( fin == NULL ){ printf( "File open error\n" ); return; } /*書き込み用ファイルを開く*/ fout = fopen("output.txt", "w"); if( fout == NULL ){ printf( "File open error\n" ); return; } /*1行ずつ読み込む*/ /*読み込める間繰り返す*/ while(fgets(buff,200,fin) != NULL){ /*タブ文字がくるまで拾う*/ while(buff[i] != '\t'){ /*文字列を配列wordに保存*/ word[i] = buff[i]; i++; } /*保存できているかの確認*/ printf("%s",word); fclose(fin); fclose(fout); } 実行後、wordの中身が表示されるのですが、 あいうえお,(文字化け)(文字化け) というように、【,(文字化け)(文字化け)】という謎の文字がついてしまいます。 また、入力ファイルの中身が2行以上でも、 あいうえお,(文字化け)(文字化け) あいうえお,(文字化け)(文字化け)・・・ というように、1行目の結果しか出てこないです。 どこを直せばいいのでしょうか? (というかそもそもCよりPerlとかで作ったほうがもっと楽なのかもしれないですが・・・) 教えて頂けると助かります。よろしくお願いします。

専門家に質問してみよう