|
|
||
twitterやコメントでたくさん反応をもらったので書き直しました。
ありがとうございます。
格納する変数はintではなくcharで。
K&Rは今のとこ全部intで処理してるな…なんでだろ。
あと本ではポインタが出てきていないので一応配列で書きました。
でも仮引数に配列はよくないみたい。
参考:
http://blog.studiohff.net/200805/post_358.html
http://d.hatena.ne.jp/yuyarin/20080531/1212161875
#include <stdio.h> #include <stdlib.h> /* 読み込む最大の長さ */ #define MAX_INPUT_LENGTH 10 void escape(char s[], char t[]); int main(int argc, char *argv[]) { int i, j; char s[MAX_INPUT_LENGTH+1], t[MAX_INPUT_LENGTH*2+1]; printf("type characters less than %d.\n", MAX_INPUT_LENGTH); /* printf("size:%d\n", sizeof(s)/sizeof(char)); */ /* ->11 */ /* EOFに到達するorMAX_INPUT_LENGTH分まで読む */ i = 0; while((s[i] = getchar()) != EOF && i < MAX_INPUT_LENGTH) { ++i; } /* 文字列の最後 */ s[i] = '\0'; escape(s, t); printf("%s",t); printf("\nend\n"); exit(0); } void escape(char s[], char t[]) { int i, j; /* printf("s: %d, t: %d\n", sizeof(s), sizeof(t)); */ /* -> s: 4, t: 4 */ /* 仮引数を配列にしていてもポインタ扱い */ for (i = 0, j = 0; s[i] != '\0'; ++i) { switch (s[i]) { case '\t': /* strcpyを使った方がきれいに書ける */ /* 追記 */ /* strcpy→strcat */ t[j++] = '\\'; t[j++] = 't'; break; case '\n': t[j++] = '\\'; t[j++] = 'n'; break; default: t[j++] = s[i]; break; } } /* 文字列の最後 */ t[j] ='\0'; }
これでよいかな。
C/C++ ではポインタや配列を関数に渡す際には必ず一緒にサイズを渡すようにする、というのが習慣になってるからなあ。
ほほう。
とりあえず動くんだけど妥当な書き方なのかわからんので貼ってみる。
「ここ変な書き方してるよ!!」とか突っ込み入れてもらえると嬉しいです。
forまわりとか配列初期化とか。(そもそも配列て使うまえに初期化すべきなのか
mainの中に定数入れちゃってるのはキニシナイ
K&R 3-2 改行文字やタブ文字を\nや\tという文字そのものに変えてコピーする関数escape(s, t)を書け
//参照しないなら初期化は不要(@t33f)
//するなら'\0'で(@tyoro)
//これだとtの10,12,14,16,18が初期化されない(id:Kiyoya)
#include <stdio.h> int escape(int s[], int t[]); int main(int argc, char *argv[]) { int i, j; int s[10], t[20]; /* for (i = j = 0; i < 10; ++i, ++j) s[i] = t[i] = t[++j] = 0; //初期化するならこっち(×) s[i] = t[i] = t[j*2] = 0; */ printf("type characters less than 10.\n"); i = 0; while((s[i++] = getchar()) != EOF) ; if(!escape(s, t)) printf("the length of first arg is too long!!\n"); for (i = 0; t[i] != EOF; ++i) printf("%c",t[i]); printf("\nend\n"); return 0; } int escape(int s[], int t[]) { int i, j; /* 5/31 00:24追記 */ /* 逆… */ /* コピー元よりコピー先が小さいときにエラーという意図 */ //if (sizeof(s) < sizeof(t)) { if (sizeof(s) > sizeof(t)) { return 0; } for (i = j = 0; s[i]; ++i, ++j) { switch (s[i]) { case '\t': t[j++] = '\\'; t[j] = 't'; break; case '\n': t[j++] = '\\'; t[j] = 'n'; break; default: t[j] = s[i]; break; } } return 1; }
これだとtの10,12,14,16,18が初期化されないような。
常に false になる気がします。
条件判定と ++ 演算子は分けないと混乱する
for ( i = j = 0, ... → for ( i = 0, j = 0, ...
if, while や for では面倒でも {} を使え
main()からは return しないで exit() を使うべし
この手の文字列処理はそもそも配列じゃなくてポインタで書いたほうが後々楽
文字列関連のstrncpy()とか参考にすべし
あ、そうか。これ引数で渡してるんだ。
CこわいよC。
自分なりに書いてみました。
http://blog.studiohff.net/200805/post_358.html
http://watcher.moe-nifty.com/memo/2008/05/re_c_38b6.html
http://d.hatena.ne.jp/jj1bdx/20080531/p1