(c言語)全角記号を半角記号にしたい

フォーラム(掲示板)ルール
フォーラム(掲示板)ルールはこちら  ※コードを貼り付ける場合は [code][/code] で囲って下さい。詳しくはこちら

トピックに返信する


答えを正確にご入力ください。答えられるかどうかでスパムボットか否かを判定します。

BBCode: ON
[img]: ON
[flash]: OFF
[url]: ON
スマイリー: OFF

トピックのレビュー
   

展開ビュー トピックのレビュー: (c言語)全角記号を半角記号にしたい

Re: (c言語)全角記号を半角記号にしたい

#15

by Timi116 » 5年前

返信遅れて申し訳ありません。
補足のプログラムもありがとうございます。
#8 のテストプログラムの実行結果では、9行目でエラーが出るので動きません。
Charactor too large for encoding charactor literal type とでます。
wchar_t のプログラムは自分で理解できたので説明は大丈夫です。
それと自分でいろいろやってみたときに、wchar_t の部分をwprintfに変更すると
正常に動いていました。

Re: (c言語)全角記号を半角記号にしたい

#14

by かずま » 5年前

ちょっとまずい部分がありました。
次のように修正します。

コード:

	int c;
	while ((c = fgetc(fp)) != EOF) {
		s[0] = c;
		int len = mb_len(s);

Re: (c言語)全角記号を半角記号にしたい

#13

by かずま » 5年前

fgets, fputs の代わりに、fgetc, puthcar を使ってもできますよ。

コード:

#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;
}
#6 の wchar_t を使うプログラムの説明は要りませんか?
また、そのプログラムがモバイルCで正しく動かなかった原因を探る
ため #8 のテストプログラムの実行結果を教えてもらえませんか?

Re: (c言語)全角記号を半角記号にしたい

#12

by Timi116 » 5年前

いろいろお手数おかけしました。
ありがとうございました!

Re: (c言語)全角記号を半角記号にしたい

#11

by かずま » 5年前

UTF-8 は多バイト文字(multi-byte character) です。

コード:

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バイトの先頭バイト
これにより 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]; に変換結果が入るので、それを出力します。

Re: (c言語)全角記号を半角記号にしたい

#10

by Timi116 » 5年前

かずま さんが書きました:
5年前
どんな入力を与えたのですか?
不具合を報告するときは、具体的な情報を示してください。
入力のすべての文字が出力されなかったのか、
半角の - や " が出力されなかったのか、などを含めて。
ファイルの中身は、

コード:

”abc-defg”
です。どの文字も出力はされませんでした。

送っていただいたコードで実行してみたところ無事動作しました。ありがとうございます!
動作はなんとなく分かるのですが、解説いただけるとありがたいです。

Re: (c言語)全角記号を半角記号にしたい

#9

by かずま » 5年前

かずま さんが書きました:
5年前

コード:

    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);
この 2つの printf は、デバッグに使ったものなので削除してください。

Re: (c言語)全角記号を半角記号にしたい

#8

by かずま » 5年前

Timi116 さんが書きました:
5年前
そちらのコード試してみたのですが、エラーは出なかったのですが、文字が出力されませんでした。
どんな入力を与えたのですか?
不具合を報告するときは、具体的な情報を示してください。
入力のすべての文字が出力されなかったのか、
半角の - や " が出力されなかったのか、などを含めて。

元のプログラムのダメだった理由は、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'"');
}
私は次のような結果を予想しています。

コード:

 ef bc 82
00efbc82
ff02
さて、wchar_t を使ってだめなら、次のコードはどうでしょうか?

コード:

#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言語)全角記号を半角記号にしたい

#7

by Timi116 » 5年前

そちらのコード試してみたのですが、エラーは出なかったのですが、文字が出力されませんでした。
かずま さんが書きました:
5年前
元のプログラムがなぜダメだったのか分かりますか?
たぶんですが、buffer==’-’というところがうまく動いていないのが原因だと思うので、-のサイズが
通常のchar型のサイズと違うため比較が出来なかったのではと思っているのですが、どうでしょうか。

Re: (c言語)全角記号を半角記号にしたい

#6

by かずま » 5年前

次のコードでいかがでしょうか?
こちらには、モバイル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言語)全角記号を半角記号にしたい

#5

by Timi116 » 5年前

コンパイラはモバイルCというスマホのやつを使ってます。osはAndroidです。文字コードはUTF-8です

Re: (c言語)全角記号を半角記号にしたい

#4

by かずま » 5年前

フォーラムルールに従って、質問してください。

文字コードに関するプログラミングは、
環境(OS やコンパイラ)に依存するからです。
ソースコード上の全角文字が Shift-JIS か Unicode(UTF-8) か
によって、コンパイル方法が変わったりもします。

Re: (c言語)全角記号を半角記号にしたい

#3

by Timi116 » 5年前

コード:

 
#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言語)全角記号を半角記号にしたい

#2

by あたっしゅ » 5年前

失敗しているプログラムを見せてください。

(c言語)全角記号を半角記号にしたい

#1

by Timi116 » 5年前

初めて質問さてていただきます。
c言語である文字列中の全角の記号(-,"など)を半角(-,")のように変換させるプログラムが組みたいのですがやり方がわからず困っています。1文字ずつ比較して置き換える方法(char c; if(c=='-')c='-';のような感じ)でやってみたんですけど上手く行きません。どのように書けば良いでしょうか?よろしくお願いします。

ページトップ