• ベストアンサー

文字コードについて

以下の内容を実行してみました。 #include <stdio.h> #include <stdlib.h> int main (){ char str[256]; printf(getenv("LANG")); printf("\n"); printf("テスト\n"); setenv("LANG","ja_JP.EUC-JP",1); printf(getenv("LANG")); printf("\n"); printf("テスト\n"); return 0; } 結果は ja_JP.utf8 テスト ja_JP.EUC-JP テスト でした。 予想だと文字化けするはずなのですが? どうしてでしょうか? エラー処理がないかもしれないのでよい書き方をご存知でしたらご指摘ください。

  • jqp
  • お礼率80% (24/30)

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

  • ベストアンサー
  • sakusaker7
  • ベストアンサー率62% (800/1280)
回答No.5

iconvは、iconv(1) だけじゃなくて iconv(3) もあります。 後者のことを指したつもりだったのですが… Manpage of ICONV http://www.linux.or.jp/JM/html/LDP_man-pages/man3/iconv.3.html #include <iconv.h> size_t iconv(iconv_t cd, char **inbuf, size_t *inbytesleft, char **outbuf, size_t *outbytesleft);

jqp
質問者

お礼

**の意味がすぐに分かりませんでしたが、ウィキペディアにコーディング例もありました。 ポインタをバッファと別に持ってそのアドレスを渡すってことですね どうもありがとうございます。

その他の回答 (4)

  • sakusaker7
  • ベストアンサー率62% (800/1280)
回答No.4

同じ文字列をeuc-jpとutf-8で出力したいということなら、 gccを使っている環境ということでiconv を使って変換してから 出力すれば良いのではないでしょうか。 使い方は info とか man を当たってください。

jqp
質問者

お礼

これは関数とかではなくてコマンドですね たしかに変換されて "テスト"と言う文字は eucが6バイト utfが9バイト と分かりました。 ありがとうございます。

  • chie65536
  • ベストアンサー率41% (2512/6032)
回答No.3

setlocaleをしようが、環境変数を書き替えようが、printfでは出力される文字列は変化しません。 Cコンパイラは「"」で括った文字の中身が、何のコードであるかは把握していません。 漢字入力がEUC漢字の環境で「テスト」と打ち込んだ場合、 printf("テスト\n"); と書くと、この「テスト」は「EUCで読めるバイト列」としてコンパイルされます。 そして、端末の表示環境がどうなってようが、プロセスの環境がどうなっていようが、そんなことはお構いなしに「EUCで読めるバイト列」をコンソールに吐き出します。 漢字入力がシフトJIS漢字の環境で「テスト」と打ち込んだ場合、 printf("テスト\n"); と書くと、この「テスト」は「シフトJISで読めるバイト列」としてコンパイルされます。 そして、端末の表示環境がどうなってようが、プロセスの環境がどうなっていようが、そんなことはお構いなしに「シフトJISで読めるバイト列」をコンソールに吐き出します。 なので printf(_TEXT("テスト\n")); の「_TEXT()関数」などのように「実行環境、端末の表示環境をリアルタイムに判断し、バイト列を、現在表示可能な漢字コードのバイト列に変換してくれるマクロや関数」を用いて、アプリケーション側が責任を持って漢字コードを変換しなければなりません。

jqp
質問者

補足

失礼しました。環境を記入していませんでした。 gcc(4.3.0)です。 それはマイクロソフトのコンパイラーの場合でしょうか?

  • Yanch
  • ベストアンサー率50% (114/225)
回答No.2

LANGは単なる環境変数なので、LANGを変更するだけでは、出力文字コードは 変わりませんよ。 アプリケーション側で、LANGに応じて、出力文字コードを変更するロジックを 記述してあげる必要があります。

jqp
質問者

お礼

それは確かstrcmpとかでしたか?

jqp
質問者

補足

そうですね、出力文字コード自体は簡単に変更できるのでしょうか?

  • sakusaker7
  • ベストアンサー率62% (800/1280)
回答No.1

setlocale を使わないとプロセスのlocaleの変更にはなりませんし、 質問にあるプログラムでは出力先の環境にお構いなしに同じバイト列を 送ってるだけです。 何がやりたいのかよく把握できないのでこう書けとは書けませんが それではダメなことだけは言えると思います。

jqp
質問者

補足

そうなんですか すいません、やりたいことが確かにはっきりしてませんね とりあえずリダイレクトででもいいからファイルに出力してutfとeucの場合の文字列長を比較したいと思いました。

関連するQ&A

  • 領域の開放がされているかどうかはどうやって調べればいいのでしょう。

    #include <stdio.h> #include <stdlib.h> int main(void){ char *str; printf("&str : %d\n", &str); // ●領域割り当て前のアドレス(NULL) printf("str : %d\n", str); str = (char *)calloc(15, sizeof(char)); // (1)領域割り当て後のアドレス printf("str : %d\n", str); // str領域開放 free(str); // (2)領域解放後のアドレス printf("str : %d\n", str); return 1; } 開放した後は●と同じくNULLになると思っていたのですが、 実際に実験してみて(1)と(2)のアドレスが同じものでした。 アドレスは割り当てたままに見えますが、実際にはちゃんと開放されているのでしょうか? それとも、何か間違えているでしょうか。 よろしくお願いします。

  • どこがちがうのでしょうか?

    以下の二つのプログラムはユーザーが文字を入力し、80文字以下なら ピリオドを追加して表示するというものです。上はうまくいきますが、下はうまくいきません。なぜでしょうか? #include<string.h> #include<stdlib.h> int main() { char str[80]; int i; printf("文字列を入力してください。\n"); gets(str); if(strlen(str)<80) { for(i=strlen(str);i<79;i++) strcat(str,"."); } printf("%s",str); } #include<stdio.h> #include<string.h> #include<stdlib.h> int main() { char str[80]; int i; printf("文字列を入力してください。\n"); gets(str); if(strlen(str)<80) { for(i=strlen(str)+1;i<79;i++) str[i] = "."; } printf("%s",str); }

  • 文字列を関数に渡すぷろぐらむなのですがおかしいです。

    <ソース> #include<stdio.h> #include<stdlib.h> void str(char a[]); int main() { char st[10]="abcde"; str(st); str("ABCabc123"); return 0; } void str(char a[]) { int i; printf("%s\n",a); i=0; while(a[i]){ a[i]=toupper(a[i]); putchar(a[i]); i++; } putchar('\n'); } 分からないところがあるので質問します。 toupperは、大文字にするんですよね。 putcharは、基本的にchar型でしたっけ? putsとgetsは、int型でしたっけ? 後、プログラムが暴走してます。 どこがおかしいんでしょう?

  • 結果が不安定なプログラム

    配列に入れられた文字列を、別の配列に逆にして入れ、表示するというプログラムを作っています。 #include<stdio.h> #include<string.h> #include<stdlib.h> void main() {   char str1[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZ", str2[] = "";   int i = 0, len = strlen(str1);   char *p1 = str1 + len - 1, *p2 = str2;   while(*(p1 - i) != str1[0] - 1) *(p2 + i) = *(p1 - i++);   printf("str1 = %s\n",p1 = str1);   printf("str2 = %s\n",p2); } 実行結果: str1 = ABCDEFGHIJKLMNOPQRSTUVWXYZ str2 = ZYXWVUTSRQPONMLKJIHGFEDCBA と出るのですが、この文字列を例えば"TANGOHYOJI"とかに変えてみると、実行は出来るんですがprintfの部分が表示されません。 また表示できても、文字が違う文字になって表示されたりします。 あと、この場合に使われている<stdlib.h>はどういった役割を果たしているのでしょうか?これがないとこのプログラムは動かなかったのですが・・。 どうかよろしくお願いします。

  • 文字列のコピー

    C言語で、文字列をコピーする関数で、処理が止まってしまいます。 以下が実行したプログラムです。 #include<stdio.h> #include<string.h> void copy(char *str2 ,char *str3){ strcpy(str2,str3); } void input(char* str){ scanf("%s",str); } int main (void){ char *a; char *b="TEST"; printf("%s\n",b); input(a); copy(b,a); printf("%s",b); return(0);} copy(b,a);で処理が止まってしまいます。入力した文字列を表示できるように、御指摘お願いします。

  • ファイルから文字列を読み出して16進数に変換

    test1.txtというファイルから文字列を読み出して16進数に変換、という処理をしたいのですがうまくいきません。どこがどう悪いのでしょうか?ご教授のほどお願いします。 ---------------------- #include <stdio.h> #include <stdlib.h> #include <string.h> int main(void) { FILE *fp; char *fname = "test1.txt"; char str[100]; int num; fp = fopen( fname, "r" ); if( fp == NULL ){ printf( "%s is not open.\n", fname ); return -1; } while( fgets(str, 100, fp ) != NULL ){ num = strtol(str, NULL, 16); printf( "%s", str ); printf("%x\n", num); //ここでうまく出力されません } fclose( fp ); return 0; } ---------------- ちなみに、test1.txtの中身は以下のようになってます。 44DB4147E6075A92E878EB68C44DD51F 5DCE86622D846BF272215A792AF31A3E 46FF69A29D3DF1D4842461B239256C26

  • 文字列をint型へ変換するには?

    c言語初心者です。 こちらのプログラムだとうまく表示されません何故でしょう? わかる方是非教えていただきたいと思います。 #include<stdio.h> #include <stdlib.h> int main() { int  num ;     char sum1[4]; printf("数字 str1 =>"); scanf("%d",&num); num= atoi(sum11); printf("sum1= [%d]\n",num); } コマンドに数字を入力したあとintに変換してnumに表示させたいのですが、、、、

  • 文字列の入力、数値変換について

    入力された数字を数値に変換するプログラムを作ったのですが、うまくいきません。 #include <stdio.h> #include <stdlib.h> #include <math.h> #include <string.h> #include <ctype.h> unsigned long long atollu(char[16]); void main(void){ unsigned long long input; char str[16]; char test[16] = "123456789012345"; int i,j=1; //atollu の動作確認・・・(1) printf("atollu test:%llu\n\n",atollu(test) ); //入力 NG: printf("%d回目 数値を入力(1~100000000000000 終了:exit)>",j); gets(str); input = atollu(str); //str と atollu(str) の確認 printf("%s %llu\n\n",str,atollu(str)); //exitと入力すると終了・・・(2) if(strcmp(str, "exit") == 0){ exit(0); } //数字以外がないか確認・・・(3) else { for( i=0; i<=15; i++){ if(isdigit(str[i]) == 0){ printf("NG\n"); for( i=0; i<=16; i++){ str[i]='\0'; } printf("moji\n"); j++; goto NG; } } } //範囲外 if(input>100000000000000 || input==0){ printf("NG\n"); printf("hani\n"); j++; goto NG; } printf("\n入力値は% llu",input ); } unsigned long long atollu(char str[16]){ unsigned long long t=0; int i,n; n = strlen(str) - 1; for( i=0; i<=15; i++){ if(str[i] == '\0'){ str[i] = 0;} else { t = t + (str[i] - '0') * pow(10.0,n-i);} } str[16] = '\0'; return t; } /* 数字を数値に変換する関数atolluは自分で作りました。 これの動作は(1)でちゃんとした値が出ているのでうまくできているようです。 (2)も"exit"と入力すれば終了するのでうまくいっています。 また、例えば "12" と入力したとき 12 9 NG moji 表示されますが、二回目以降は 12 12 NG moji となり、atollu(str)はうまく出力されている一方で、最後に「moji」と出てきているので、(3)でうまくいっていないようです。 どう直すべきなのか見当もつかないので困っています。 よろしくお願いします。

  • 小文字のみを数える方法

    小文字のみを表示させるプログラミングがいくらやってもできません。範囲指定をどこですれば良いのかわからず、全部の文字数をカウントしてしまいます。 ご指摘お願いします。 #include <stdio.h> #include <string.h> int main(void) { char str[256]; int a; printf("大文字と小文字をランダムに入力\n"); gets(str); printf("小文字の数は%dです\n",strlen(str),a); return(0); }

  • 文字コード EUCとSJISの切り替え

    今までSONYのNEWSというマシンを使ってたのですが、このたび初めてULTRA5(Solaris2.5.1)を使うことになりました。 NEWSでは、  setenv LANG ja_JP.SJIS ; stty sys sjis  setenv LANG ja_JP.EUC ; stty sys euc などとやると、すぐにSJISとEUCの環境を切り替えることができたのですが、Solarisではこの方法が使えませんでした。 ログインする前に文字環境を選べるのは分かるんですが、作業中にいちいちログアウトわけにも行かないので、非常に不便で困っています。 何か良い方法がありましたら、ご教授頂けますようよろしくお願いします。

専門家に質問してみよう