p タグの自動挿入

とんさんのコメント拝見しました。去年の夏以来全然ブログ(ならひよ)が更新されていなくて、どうなったのかな〜と少し気になってはいました。勉強の方頑張っていらっしゃるようで、喜ばしい限りです。

一年生の前期に文法を習って、後期と二年生前期でアルゴリズムって感じでしょうか?それくらいのペースがちょうどいいところです。どちらかというと「データ構造」に的を絞って勉強したほうがアルゴリズムは身につきやすいと思います。気楽に頑張ってください。とんさんとまたブログでコミュニケーションできたらうれしいです。

さて、C言語で日本語を扱うことができるということをつい最近になって知りました。wchar.hの関数を使って何かしてみたいなってことで、普通の日本語テキストファイルに<p>タグを挿入してHTML形式に改めることができたらなぁと。それで自分のブログ更新に役立てようかなと思ってプログラムを書いてみることにしました。

書いてみたソースコードは下のようになりました。大学などでC言語を習ってstdio.h, stdlib.h, string.hは知っていたんですが、locale.hとwchar.hは今回初めて使いました。それでは実際のソースコードを。

#include <stdio.h>
#include <stdlib.h>
#include <wchar.h>
#include <locale.h>
#include <string.h>
#define SIZ 1024
#define MY_LOCALE_SETTING "ja_JP.UTF-8"

int main(int argc, char *argv[])
{
	wchar_t buf[SIZ];
	FILE *in, *out;
	char input[20], output[20];
	int last;
	
	// 引数の個数チェック
	if(argc < 3 )
		exit(1);

	strcpy(input, argv[1]);
	strcpy(output, argv[2]);

	// ファイルチェック
	if( strcmp(input, output) == 0 ) {
		puts("入力ファイル名と出力ファイル名が同一です");
		exit(1);
	}
	if( (in = fopen(input, "r")) == NULL ){
		puts("入力ファイルが開けません");
		exit(1);
	}
	if( (out = fopen(output, "w")) == NULL ) {
		puts("出力ファイルエラー");
		exit(1);
	}

	// ロケールの設定
	setlocale(LC_ALL, MY_LOCALE_SETTING);

	while( fgetws(buf, SIZ, in) != NULL ) {
		// 改行文字を削除する
		last = wcslen(buf) - 1;
		if(buf[last] == L'\n')
			buf[last] = L'\0';
		
		// pタグを挿入して改めて改行
		fprintf(out, "<p>%ls</p>\n", buf);
	}

	fclose(in);
	fclose(out);
	return 0;
}

使い方についてですけど、引数をとれるようにしておいたので、適当にコンパイルしてから、二つの引数をとって実行してやればいいです。

# gcc -o insert_tag insert_tag.c
# ./insert_tag input.txt output.txt

一通り学校でC言語を勉強していれば、こんな感じのプログラムは何度も見かけていると思います。fgetsしつづけてファイルに書き込む……という定番です。

まず引数のチェックを行っています。ファイル名はargv[1], argv[2]を使いつづけるよりは input[], output[]としたほうが分かりやすかったので用意しました。

setlocale()関数はlocale.h内の標準関数です。ソフトウェア開発において各地域や言語に依存する部分などはプログラム本体からはデータベースとして切り離すのが一般的です。そのような設定のことをとよびます。地域や言語ごとのデータをロケールデータといいます。

C言語の標準関数には、ロケール設定によって動作が左右されてしまうものがあります。デフォルトのロケールではマズい場合はsetlocale()関数でロケール設定をしなければなりません。

char *setlocale( int category, const char *locale )

category引数には色々指定できるようですが、ここでは LC_ALL が選ばれています。localeには指定したいロケール名を文字列で指定するわけです。ここでは日本語でunicodeということにしてあります。ロケールの変更が必要ならMY_LOCALE_SETTINGを変更してください。

ワイド文字を扱っているので普通のfgets()が使えません。wchar.h内のfgetwsを使います。取得した文字列を格納するための配列もchar型ではなくwchar_t型である必要があります。

ブログの記事としてテキストを書いていれば、適当なところで改行するのが普通です。しかし、改行してからタグが入ってしまうと後で見づらい……ということで、配列buf[]に含まれている改行文字を削除し、ヌル文字に置き換えてしまいます。

こうしてできたワイド文字の文字列を、pタグで挟み、さらに改行を入れるわけです。これで意図したとおりにpタグを挿入することができました。fprintf()の書式指定子を%lsとすることにも注意が必要です。


コメント

コメントの投稿















管理者にだけ表示を許可

トラックバック

この記事のトラックバックURI
http://wavelet.blog58.fc2.com/tb.php/203-d841b589