(c言語)全角記号を半角記号にしたい
(c言語)全角記号を半角記号にしたい
初めて質問さてていただきます。
c言語である文字列中の全角の記号(-,"など)を半角(-,")のように変換させるプログラムが組みたいのですがやり方がわからず困っています。1文字ずつ比較して置き換える方法(char c; if(c=='-')c='-';のような感じ)でやってみたんですけど上手く行きません。どのように書けば良いでしょうか?よろしくお願いします。
c言語である文字列中の全角の記号(-,"など)を半角(-,")のように変換させるプログラムが組みたいのですがやり方がわからず困っています。1文字ずつ比較して置き換える方法(char c; if(c=='-')c='-';のような感じ)でやってみたんですけど上手く行きません。どのように書けば良いでしょうか?よろしくお願いします。
Re: (c言語)全角記号を半角記号にしたい
失敗しているプログラムを見せてください。
VTuber:
東上☆海美☆(とうじょう・うみみ)
http://atassyu.php.xdomain.jp/vtuber/index.html
レスがついていないものを優先して、レスするみみ。時々、見当外れなレスしみみ。
中の人:
手提鞄あたッしュ、[MrAtassyu] 手提鞄屋魚有店
http://ameblo.jp/mratassyu/
Pixiv: 666303
Windows, Mac, Linux, Haiku, Raspbery Pi, Jetson Nano, 電子ブロック 持ち。
東上☆海美☆(とうじょう・うみみ)
http://atassyu.php.xdomain.jp/vtuber/index.html
レスがついていないものを優先して、レスするみみ。時々、見当外れなレスしみみ。
中の人:
手提鞄あたッしュ、[MrAtassyu] 手提鞄屋魚有店
http://ameblo.jp/mratassyu/
Pixiv: 666303
Windows, Mac, Linux, Haiku, Raspbery Pi, Jetson Nano, 電子ブロック 持ち。
Re: (c言語)全角記号を半角記号にしたい
#include<stdio.h>
#include<string.h>
int main()
{
char filename[FILENAME_MAX];
char buffer;
FILE *fp;
printf("ファイル名を入力してください:");
scanf("%s",filename);
if((fp=fopen(filename,"r"))==NULL){
printf("ファイルが見つかりません");
return -1;
}
while ((buffer = fgetc(fp)) != EOF) {
if (buffer == '−')buffer = '-';
if (buffer == '”')buffer = '"';
printf("%c", buffer);
}
fclose(fp);
return 0;
}
Re: (c言語)全角記号を半角記号にしたい
フォーラムルールに従って、質問してください。
文字コードに関するプログラミングは、
環境(OS やコンパイラ)に依存するからです。
ソースコード上の全角文字が Shift-JIS か Unicode(UTF-8) か
によって、コンパイル方法が変わったりもします。
文字コードに関するプログラミングは、
環境(OS やコンパイラ)に依存するからです。
ソースコード上の全角文字が Shift-JIS か Unicode(UTF-8) か
によって、コンパイル方法が変わったりもします。
Re: (c言語)全角記号を半角記号にしたい
次のコードでいかがでしょうか?
こちらには、モバイルC がないので確認できません。
元のプログラムがなぜダメだったのか分かりますか?
こちらには、モバイルC がないので確認できません。
#include <stdio.h> // printf, scanf
#include <wchar.h> // fgetwc, putwchar
#include <locale.h> // setlocale
int main(void)
{
char filename[FILENAME_MAX];
wchar_t buffer;
FILE *fp;
setlocale(LC_ALL, "");
printf("ファイル名を入力してください:");
scanf("%s", filename);
if ((fp = fopen(filename, "r")) == NULL) {
printf("ファイルが見つかりません");
return -1;
}
while ((buffer = fgetwc(fp)) != WEOF) {
if (buffer == L'-') buffer = L'-';
if (buffer == L'"') buffer = L'"';
putwchar(buffer);
}
fclose(fp);
return 0;
}
Re: (c言語)全角記号を半角記号にしたい
どんな入力を与えたのですか?Timi116 さんが書きました: ↑6年前そちらのコード試してみたのですが、エラーは出なかったのですが、文字が出力されませんでした。
不具合を報告するときは、具体的な情報を示してください。
入力のすべての文字が出力されなかったのか、
半角の - や " が出力されなかったのか、などを含めて。
元のプログラムのダメだった理由は、char が 1バイトだからです。
通常の半角文字は1バイトですが、全角文字は 2~3バイトになります。
そして、fgetc は、1バイトを読み込む関数です。
次のテストプログラムでどのように表示されますか?
#include <stdio.h>
int main(void)
{
const char s[] = """;
unsigned char c;
for (const char *p = s; c = *p; p++) printf(" %02x", c);
putchar('\n');
printf("%08x\n", '"');
printf("%04x\n", L'"');
}
#include <stdio.h> // printf, scanf, fgets, fputs
#include <string.h> // strncmp, memcpy
int mb_len(const char *p)
{
unsigned char b = *p;
if (b < 0x80) return 1;
if (b < 0xe0) return 2;
if (b < 0xf0) return 3;
if (b < 0xf8) return 4;
if (b < 0xfc) return 5;
return 6;
}
int main()
{
char filename[FILENAME_MAX];
FILE *fp;
char s1[1024], s2[1024];
int len1 = mb_len("-");
int len2 = mb_len(""");
printf("ファイル名を入力してください:");
scanf("%s", filename);
if ((fp = fopen(filename, "r")) == NULL) {
printf("ファイルが見つかりません");
return -1;
}
while (fgets(s1, sizeof s1, fp)) {
char *p1 = s1, *p2 = s2;
while (*p1) {
printf(" %02x", *p1 & 0xff);
int len = mb_len(p1);
printf("len = %d, len1=%d, len2=%d\n", len, len1, len2);
if (!strncmp(p1, "-", len1)) *p2++ = '-';
else if (!strncmp(p1, """, len2)) *p2++ = '"';
else memcpy(p2, p1, len), p2 += len;
p1 += len;
}
*p2 = 0;
fputs(s2, stdout);
}
fclose(fp);
return 0;
}
Re: (c言語)全角記号を半角記号にしたい
この 2つの printf は、デバッグに使ったものなので削除してください。かずま さんが書きました: ↑6年前
Re: (c言語)全角記号を半角記号にしたい
UTF-8 は多バイト文字(multi-byte character) です。
次のような構造です。
これにより 1文字のバイト数が分かります。
"abあcd\n" を fgets で読み込むと、
char s1[] = { 0x61, 0x62, 0xe3, 0x81, 0x82, 0x63, 0x64, 0x0a, 0x00 };
char *p1 でこの中を指しながら、mb_len で求めたバイト長ずつ進めていけば
1文字ずつ参照できます。
strncmp(p1, "あ", 3) で比較すれば、"あ" かどうか分かります。
"あ" だったら、変換したい文字を p2 の指すところにコピーすればよい。
そうでなければ、p1 の指す文字を p2 の指すところにコピーすればよい。
char s2[1024]; に変換結果が入るので、それを出力します。
1バイト文字
\t \n 09 0a
!"#...-./ 21 22 23 ... 2d 2e 2f
012...9 30 31 32 ... 39
ABC...Z 41 42 43 ... 5a
abc...z 61 62 63 ... 7a
2バイト文字
¢£ c2 a2 c2 a3
αβγ ce b1 ce b2 ce b3
3バイト文字
あいう e3 81 82 e3 81 84 e3 81 86
漢字 e6 bc a2 e5 ad 97
00 - 7f 1バイト文字
80 - bf 多バイト文字の後続バイト
c0 - df 2バイトの先頭バイト
e0 - ef 3バイトの先頭バイト
f0 - f7 4バイトの先頭バイト
f8 - fb 5バイトの先頭バイト
fc - fd 6バイトの先頭バイト
"abあcd\n" を fgets で読み込むと、
char s1[] = { 0x61, 0x62, 0xe3, 0x81, 0x82, 0x63, 0x64, 0x0a, 0x00 };
char *p1 でこの中を指しながら、mb_len で求めたバイト長ずつ進めていけば
1文字ずつ参照できます。
strncmp(p1, "あ", 3) で比較すれば、"あ" かどうか分かります。
"あ" だったら、変換したい文字を p2 の指すところにコピーすればよい。
そうでなければ、p1 の指す文字を p2 の指すところにコピーすればよい。
char s2[1024]; に変換結果が入るので、それを出力します。
Re: (c言語)全角記号を半角記号にしたい
fgets, fputs の代わりに、fgetc, puthcar を使ってもできますよ。
#6 の wchar_t を使うプログラムの説明は要りませんか?
また、そのプログラムがモバイルCで正しく動かなかった原因を探る
ため #8 のテストプログラムの実行結果を教えてもらえませんか?
#include <stdio.h> // printf, scanf, fgetc, putchar
#include <string.h> // strncmp
int mb_len(const char *p)
{
unsigned char b = *p;
if (b < 0x80) return 1;
if (b < 0xe0) return 2;
if (b < 0xf0) return 3;
if (b < 0xf8) return 4;
if (b < 0xfc) return 5;
return 6;
}
int main()
{
char filename[FILENAME_MAX];
FILE *fp;
char s[3];
printf("ファイル名を入力してください:");
scanf("%s", filename);
if ((fp = fopen(filename, "r")) == NULL) {
printf("ファイルが見つかりません");
return -1;
}
while ((s[0] = fgetc(fp)) != EOF) {
int len = mb_len(s);
if (len == 3) {
s[1] = fgetc(fp), s[2] = fgetc(fp);
if (!strncmp(s, "-", 3)) putchar('-');
else if (!strncmp(s, """, 3)) putchar('"');
else putchar(s[0]), putchar(s[1]), putchar(s[2]);
}
else {
putchar(s[0]);
while (--len > 0) putchar(fgetc(fp));
}
}
fclose(fp);
return 0;
}
また、そのプログラムがモバイルCで正しく動かなかった原因を探る
ため #8 のテストプログラムの実行結果を教えてもらえませんか?
Re: (c言語)全角記号を半角記号にしたい
返信遅れて申し訳ありません。
補足のプログラムもありがとうございます。
#8 のテストプログラムの実行結果では、9行目でエラーが出るので動きません。
Charactor too large for encoding charactor literal type とでます。
wchar_t のプログラムは自分で理解できたので説明は大丈夫です。
それと自分でいろいろやってみたときに、wchar_t の部分をwprintfに変更すると
正常に動いていました。
補足のプログラムもありがとうございます。
#8 のテストプログラムの実行結果では、9行目でエラーが出るので動きません。
Charactor too large for encoding charactor literal type とでます。
wchar_t のプログラムは自分で理解できたので説明は大丈夫です。
それと自分でいろいろやってみたときに、wchar_t の部分をwprintfに変更すると
正常に動いていました。