idea0002
をテンプレートにして作成
[
トップ
] [
新規
|
一覧
|
単語検索
|
最終更新
|
ヘルプ
]
開始行:
* 川合のプログラミング言語自作のためのアイデア#0002
-(by [[K]], 2019.03.17)
** (10) テーマ#5: ささいな関数群こそがプログラマを救う?
-私たちプログラマは、たいていは「すごいライブラリ」を作り...
-そういうものはもちろん便利です。でもそういうものしか作っ...
-私が先日作っていたプログラムの一部を例にします。これはHT...
char last = 0;
while (*p != '\0') {
if (*p == '<') {
if (strncmp(p, "<br />", 6) == 0) { p += 6; putc...
if (strncmp(p, "<strong>", 8) == 0) { p += 8; co...
if (strncmp(p, "</strong>", 9) == 0) { p += 9; c...
if (strncmp(p, "<div>", 5) == 0) { p += 5; conti...
if (strncmp(p, "</div>", 6) == 0) { p += 6; cont...
if (strncmp(p, "<h3>", 4) == 0) { p += 4; putcha...
if (strncmp(p, "</h3>", 5) == 0) { p += 5; putch...
(似たような処理がまだたくさん続くが面倒なので省...
}
if (*p == ' ' || *p == '\r' || *p == '\n' || *p == '...
p++;
if (last != ' ')
putchar(last = ' ');
} else
putchar(last = *p++);
}
-まあ普通のプログラムです。でももしstrncmpSkip()という関...
int strncmpSkip(const char **p, const char *s)
{
int l = strlen(s);
if (strncmp(*p, s, l) == 0) {
*p += l;
return 1;
}
return 0;
}
-書き換え結果:
char last = 0;
while (*p != '\0') {
if (*p == '<') {
if (strncmpSkip(&p, "<br />")) { putchar('\n'); ...
if (strncmpSkip(&p, "<strong>")) continue;
if (strncmpSkip(&p, "</strong>")) continue;
if (strncmpSkip(&p, "<div>")) continue;
if (strncmpSkip(&p, "</div>")) continue;
if (strncmpSkip(&p, "<h3>")) { putchar('\n'); co...
if (strncmpSkip(&p, "</h3>")) { putchar('\n'); c...
(似たような処理がまだたくさん続くが面倒なので省...
}
if (*p == ' ' || *p == '\r' || *p == '\n' || *p == '...
p++;
if (last != ' ')
putchar(last = ' ');
} else
putchar(last = *p++);
}
-この書き方は以下の点で優れています。・・・strncmpで比較...
-まあこの文脈におけるstrncmpSkipの有用性は疑いないと思い...
-まずこの関数に一般性はあるでしょうか。私は結構一般性があ...
-まあそういうときはその都度アプリ側でこの関数を作ればいい...
-私はつい数か月前までは、こういう関数をライブラリ化するな...
** (11) AutoReleasePoolとtmpPrintf
-これは些細な関数をライブラリ化してかなりうまく行ったと感...
-まず、以下の関数群を作りました。4つもあるので少し長く見...
typedef strcut AutoReleaseNode_ {
void *p, *next;
} AutoReleaseNode;
typedef struct AutoReleasePool_ {
void *oldPool;
AutoReleaseNode *node;
} AutoReleasePool;
AutoReleasePool *AutoReleasePool_defalut = 0;
AutoReleasePool *AutoReleasePool_open()
{
AutoReleasePool *w = malloc(sizeof (AutoReleasePool));
w->oldPool = AutoReleasePool_defalut; // デフォルト...
w->node = 0;
return w;
}
void AutoReleasePool_add(AutoReleasePool *w, void *p)
{
AutoReleaseNode *n = malloc(sizeof (AutoReleaseNode));
if (w == 0) w = AutoReleasePool_defalut; // 0ならデ...
n->p = p;
n->next = w->node;
w->node = n;
}
void AutoReleasePool_remove(AutoReleasePool *w, void *p)
{
AutoReleaseNode *n;
if (w == 0) w = AutoReleasePool_defalut; // 0ならデ...
for (n = w->node; n != 0; n = n->next) {
if (n->p == p) {
n->p = 0;
return;
}
}
fprintf(stderr, "AutoReleasePool_remove: remove erro...
exit(EXIT_FAILURE);
}
void AutoReleasePool_close(AutoReleasePool *w)
{
AutoReleaseNode *n, *nn;
if (w != AutoReleasePool_defalut) {
fprintf(stderr, "AutoReleasePool_close: nesting ...
exit(EXIT_FAILURE);
}
for (n = w->node; n != 0; n = nn) {
nn = n->next;
if (n->p != 0)
free(n->p);
free(n);
}
AutoReleasePool_defalut = w->oldPool;
free(w);
}
--AutoReleaseNode: たった8バイトの小さな構造体
--AutoReleasePool: たった8ナイトの小さな構造体
--AutoReleasePool_open(): 自動リリースプールを準備する
--AutoReleasePool_close(): 自動リリースプールを片付ける(...
--AutoReleasePool_add(): 自動リリースプールにポインタを一...
--AutoReleasePool_remove(): 自動リリースプールに登録され...
-その上で以下の関数を作りました。
char *tmpPrintf(const char *f, ...)
{
char buf[1024 * 1024];
va_list arg;
int l;
char *s;
va_start(arg, f);
l = vsnprintf(buf, sizeof buf, f, arg);
if (l < 0 || (int) (sizeof b) <= l) {
fprintf(stderr, "tmpPrintf: buffer error\n");
exit(EXIT_FAILURE);
}
va_end(arg);
s = malloc(l + 1);
memcpy(s, buf, l + 1);
AutoReleasePool_add(0, s);
return s;
}
-この関数は、sprintf()みたいなものなのですが、格納先のメ...
-この関数tmpPrintf()のミソは、mallocしたポインタをAutoRel...
-もう「確保したメモリは忘れずに解放しなくちゃ!」みたいな...
-忘れちゃいけないのは、関数に入ったらAutoReleasePoolをope...
-私はこんな風に使っています。
for (i = 0; i < 100; i++) {
FILE *fp = fopen(tmpPrintf("file%04d.txt", i), "rt");
...
fclose(fp);
}
-まあもちろん
for (i = 0; i < 100; i++) {
char tmp[16];
sprintf(tmp, "file%04d.txt", i);
FILE *fp = fopen(tmp, "rt");
...
fclose(fp);
}
-と書いてもいいのですが、上記の書き方よりも2行も多いです...
-変数名を考えるのって時にはめんどくさいですし、このtmpの...
** (12) strstr2
-すごくくだらない名前ですが、我ながらなかなかに有用だった...
-あるフレーズを見つけたら、その先にある別のフレーズまで読...
char *strstr2(const char *s, const char *t, const char *u)
{
char *p = strstr(s, t);
if (p != 0) {
p = strstr(p + strlen(t), u);
if (p != 0)
p += strlen(u);
}
return p;
}
-これはどうやって使うのかというと、例えばHTMLのテキストを...
p = HTMLの先頭;
for (;;) {
p = strstr2(p, "<a href=", ">");
if (p == 0) break;
q = strstr(p, "</a>");
if (q == 0) break;
printf("%.*s\n", q - p, p);
}
-とやるだけで、リンクしている文言を全部取り出せるわけです。
-まあ本当にくだらない関数なんですが、でもこれが結構便利だ...
** 次回に続く
-次回: [[idea0003]]
*こめんと欄
#comment
終了行:
* 川合のプログラミング言語自作のためのアイデア#0002
-(by [[K]], 2019.03.17)
** (10) テーマ#5: ささいな関数群こそがプログラマを救う?
-私たちプログラマは、たいていは「すごいライブラリ」を作り...
-そういうものはもちろん便利です。でもそういうものしか作っ...
-私が先日作っていたプログラムの一部を例にします。これはHT...
char last = 0;
while (*p != '\0') {
if (*p == '<') {
if (strncmp(p, "<br />", 6) == 0) { p += 6; putc...
if (strncmp(p, "<strong>", 8) == 0) { p += 8; co...
if (strncmp(p, "</strong>", 9) == 0) { p += 9; c...
if (strncmp(p, "<div>", 5) == 0) { p += 5; conti...
if (strncmp(p, "</div>", 6) == 0) { p += 6; cont...
if (strncmp(p, "<h3>", 4) == 0) { p += 4; putcha...
if (strncmp(p, "</h3>", 5) == 0) { p += 5; putch...
(似たような処理がまだたくさん続くが面倒なので省...
}
if (*p == ' ' || *p == '\r' || *p == '\n' || *p == '...
p++;
if (last != ' ')
putchar(last = ' ');
} else
putchar(last = *p++);
}
-まあ普通のプログラムです。でももしstrncmpSkip()という関...
int strncmpSkip(const char **p, const char *s)
{
int l = strlen(s);
if (strncmp(*p, s, l) == 0) {
*p += l;
return 1;
}
return 0;
}
-書き換え結果:
char last = 0;
while (*p != '\0') {
if (*p == '<') {
if (strncmpSkip(&p, "<br />")) { putchar('\n'); ...
if (strncmpSkip(&p, "<strong>")) continue;
if (strncmpSkip(&p, "</strong>")) continue;
if (strncmpSkip(&p, "<div>")) continue;
if (strncmpSkip(&p, "</div>")) continue;
if (strncmpSkip(&p, "<h3>")) { putchar('\n'); co...
if (strncmpSkip(&p, "</h3>")) { putchar('\n'); c...
(似たような処理がまだたくさん続くが面倒なので省...
}
if (*p == ' ' || *p == '\r' || *p == '\n' || *p == '...
p++;
if (last != ' ')
putchar(last = ' ');
} else
putchar(last = *p++);
}
-この書き方は以下の点で優れています。・・・strncmpで比較...
-まあこの文脈におけるstrncmpSkipの有用性は疑いないと思い...
-まずこの関数に一般性はあるでしょうか。私は結構一般性があ...
-まあそういうときはその都度アプリ側でこの関数を作ればいい...
-私はつい数か月前までは、こういう関数をライブラリ化するな...
** (11) AutoReleasePoolとtmpPrintf
-これは些細な関数をライブラリ化してかなりうまく行ったと感...
-まず、以下の関数群を作りました。4つもあるので少し長く見...
typedef strcut AutoReleaseNode_ {
void *p, *next;
} AutoReleaseNode;
typedef struct AutoReleasePool_ {
void *oldPool;
AutoReleaseNode *node;
} AutoReleasePool;
AutoReleasePool *AutoReleasePool_defalut = 0;
AutoReleasePool *AutoReleasePool_open()
{
AutoReleasePool *w = malloc(sizeof (AutoReleasePool));
w->oldPool = AutoReleasePool_defalut; // デフォルト...
w->node = 0;
return w;
}
void AutoReleasePool_add(AutoReleasePool *w, void *p)
{
AutoReleaseNode *n = malloc(sizeof (AutoReleaseNode));
if (w == 0) w = AutoReleasePool_defalut; // 0ならデ...
n->p = p;
n->next = w->node;
w->node = n;
}
void AutoReleasePool_remove(AutoReleasePool *w, void *p)
{
AutoReleaseNode *n;
if (w == 0) w = AutoReleasePool_defalut; // 0ならデ...
for (n = w->node; n != 0; n = n->next) {
if (n->p == p) {
n->p = 0;
return;
}
}
fprintf(stderr, "AutoReleasePool_remove: remove erro...
exit(EXIT_FAILURE);
}
void AutoReleasePool_close(AutoReleasePool *w)
{
AutoReleaseNode *n, *nn;
if (w != AutoReleasePool_defalut) {
fprintf(stderr, "AutoReleasePool_close: nesting ...
exit(EXIT_FAILURE);
}
for (n = w->node; n != 0; n = nn) {
nn = n->next;
if (n->p != 0)
free(n->p);
free(n);
}
AutoReleasePool_defalut = w->oldPool;
free(w);
}
--AutoReleaseNode: たった8バイトの小さな構造体
--AutoReleasePool: たった8ナイトの小さな構造体
--AutoReleasePool_open(): 自動リリースプールを準備する
--AutoReleasePool_close(): 自動リリースプールを片付ける(...
--AutoReleasePool_add(): 自動リリースプールにポインタを一...
--AutoReleasePool_remove(): 自動リリースプールに登録され...
-その上で以下の関数を作りました。
char *tmpPrintf(const char *f, ...)
{
char buf[1024 * 1024];
va_list arg;
int l;
char *s;
va_start(arg, f);
l = vsnprintf(buf, sizeof buf, f, arg);
if (l < 0 || (int) (sizeof b) <= l) {
fprintf(stderr, "tmpPrintf: buffer error\n");
exit(EXIT_FAILURE);
}
va_end(arg);
s = malloc(l + 1);
memcpy(s, buf, l + 1);
AutoReleasePool_add(0, s);
return s;
}
-この関数は、sprintf()みたいなものなのですが、格納先のメ...
-この関数tmpPrintf()のミソは、mallocしたポインタをAutoRel...
-もう「確保したメモリは忘れずに解放しなくちゃ!」みたいな...
-忘れちゃいけないのは、関数に入ったらAutoReleasePoolをope...
-私はこんな風に使っています。
for (i = 0; i < 100; i++) {
FILE *fp = fopen(tmpPrintf("file%04d.txt", i), "rt");
...
fclose(fp);
}
-まあもちろん
for (i = 0; i < 100; i++) {
char tmp[16];
sprintf(tmp, "file%04d.txt", i);
FILE *fp = fopen(tmp, "rt");
...
fclose(fp);
}
-と書いてもいいのですが、上記の書き方よりも2行も多いです...
-変数名を考えるのって時にはめんどくさいですし、このtmpの...
** (12) strstr2
-すごくくだらない名前ですが、我ながらなかなかに有用だった...
-あるフレーズを見つけたら、その先にある別のフレーズまで読...
char *strstr2(const char *s, const char *t, const char *u)
{
char *p = strstr(s, t);
if (p != 0) {
p = strstr(p + strlen(t), u);
if (p != 0)
p += strlen(u);
}
return p;
}
-これはどうやって使うのかというと、例えばHTMLのテキストを...
p = HTMLの先頭;
for (;;) {
p = strstr2(p, "<a href=", ">");
if (p == 0) break;
q = strstr(p, "</a>");
if (q == 0) break;
printf("%.*s\n", q - p, p);
}
-とやるだけで、リンクしている文言を全部取り出せるわけです。
-まあ本当にくだらない関数なんですが、でもこれが結構便利だ...
** 次回に続く
-次回: [[idea0003]]
*こめんと欄
#comment
ページ名: