No.1621![]() |
インプットの文字列の文字数を無制限のプログラムについて 投稿者---KAZ(2004/05/01 17:29:50) |
||
プログラムをかいていてふと思ったのですが、インプットの文字数を制限せずにC言語でプログラムをかくことができるのでしょうか?以下にサンプルのプログラムを示します。 #include <stdio.h> #include <string.h> void reverse(char *str); int main(void) { // define the number of input charactor as 100 char buff[100]; int i; for (i=0; i< 5; i++){ fgets(buff,100,stdin); reverse(buff); } } void reverse(char *str) { int len = strlen(str); char *new = (char *)malloc(len*(sizeof(char))); int left=0, right =len-2; while(left <= right){ new[left] = str[right]; new[right]= str[left]; left++; right--; } *(new+(len-1)) = '\n'; *(new+len) = '\0'; printf("new is %s",new); } このプログラムは入力したラインをリバースさせるものなんですがインプットを100文字以内と定義しています。ここで文字数を定義せずにプログラムをかくことができるのでしょうか? 入力した文字をバファーにいれる前に文字数が分ればmallocでとれると思うのですがそういったことはできるのでしょうか? |
No.1622![]() |
Re:インプットの文字列の文字数を無制限のプログラムについて 投稿者---かずま(2004/05/01 18:34:22) |
||
> このプログラムは入力したラインをリバースさせるものなんですがインプットを > 100文字以内と定義しています。ここで文字数を定義せずにプログラムをかく > ことができるのでしょうか? #include <stdio.h> #include <stdlib.h> void reverse(void) { int c = getchar(); if (c == EOF) exit(1); if (c == '\n') printf("new is "); else reverse(), putchar(c); } int main(void) { int i; for (i = 0; i < 5; i++) reverse(), putchar('\n'); return 0; } > 入力した文字をバファーにいれる前に文字数が分れば > mallocでとれると思うのですがそういったことはできるのでしょうか? できます。 |
No.1623![]() |
ファイルのバファーをしていせずにすることはできますか? 投稿者---KAZ(2004/05/01 19:21:35) |
||
御返事ありがとうございます。かずまさんのプログラム、勉強になります。mallocのことしか考えてませんでした。 でももしこのプログラムのインプットをファイルにしてそのファイルのライン のバファーを指定しないということもできますか?さっきのプログラムをかえてみました。この場合だとさきほどの方法ではできないと思うのですが、もし方法があれば、もう一度教えてください。よろしくおねがいします。<pre>プログラムをかいていてふと思ったのですが、インプットの文字数を制限せずにC言語でプログラムをかくことができるのでしょうか?以下にサンプルのプログラムを示します。 #include <stdio.h> #include <string.h> char * reverse(char *str); void rev(FILE *); int main(int argc, char *argv[]) { rev(stdin); return 0; } void rev(FILE *in) { char line[100]; if (fgets(line, 100, in) == NULL) return; rev(in); strcpy(line,reverse(line)); fputs(line, stdout); } char * reverse(char *str) { int len = strlen(str); char *new = (char *)malloc(len*(sizeof(char))); int left=0,right=len-2; while(left<=right){ new[left] = str[right]; new[right] = str[left]; left++; right--; } *(new+(len-1)) = '\n'; *(new+len) = '\0'; return new; } |
No.1626![]() |
Re:インプットの文字列の文字数を無制限のプログラムについて 投稿者---かずま(2004/05/02 02:24:10) |
||
> 入力した文字をバファーにいれる前に文字数が分れば > mallocでとれると思うのですがそういったことはできるのでしょうか? malloc でもできますが、この場合は realloc を使うほうがよいでしょう。 #include <stdio.h> #include <stdlib.h> #include <string.h> typedef struct { char *buf; int size, capa; } Line; void add(Line *p, int c) { if (p->size >= p->capa) { p->capa = p->capa ? p->capa * 2 : 256; p->buf = realloc(p->buf, p->capa); if (p->buf == NULL) puts("out of memory"), exit(1); } p->buf[p->size++] = c; } int getline(Line *p) { int c; while (c = getchar(), c != EOF && c != '\n') add(p, c); add(p, 0); return p->size; } void reverse(char *p) { int n = strlen(p); printf("new is "); while (--n >= 0) putchar(p[n]); putchar('\n'); } int main(void) { Line line = { 0 }; int i; for (i = 0; i < 5; i++) { line.size = 0; getline(&line); reverse(line.buf); } free(line.buf); return 0; } |
No.1627![]() |
Re:インプットの文字列の文字数を無制限のプログラムについて 投稿者---かずま(2004/05/02 10:31:51) |
||
> malloc でもできますが、この場合は realloc を使うほうがよいでしょう。 このプログラムですが、main の line.size = 0; は削除して、 getline の先頭に p->size = 0; を置いたほうがよいでしょう。 |
No.1628![]() |
ファイルのバファーをしていせずにすることはできますか? 投稿者---KAZ(2004/05/02 19:02:35) |
||
かずまさん、YUOさんありがとうございます。かずまさんのプログラム解読に 随分と時間がかかってしまいました。YUOさん のいうfgetsとreallocのくみあわせというのはどういうものでしょうか? 最初に配列を用意しといて、fgetsでとった文字列がその容量をこえた時点で reallocということでしょうか? 現在、次のようなプログラ厶でまったく制限をつけずにつくってみたいので すができるでしょうか? プログラム名 reverseall.c テキストファイル(test.txt)に these all sentences will be reversed. my program has to be desighned without any restriction, which means that can accept the any number of charactor in the given line. とテキストをうちこんで保存し ./reverseall < test.txt .enil nevig eht ni rotcarahc fo rebmun yna eht tpecca nac taht snaem hcihw ,noitcirtser yna tuohtiw denhgised eb ot sah margorp ym .desrever eb lliw secnetnes lla eseht でこのように上から下、左から右すべてを反転させたいんですが。。 fgets と realloc でできるんでしょうか? realloc をつかうときの条件が できません。(すみません、ばかな挑戦ばかりして、Cでいろいろなこと ができるようになりたいんです。) |
No.1629![]() |
Re:ファイルのバファーをしていせずにすることはできますか? 投稿者---かずま(2004/05/02 20:54:21) |
||
fgets は使いませんが。 #include <stdio.h> #include <stdlib.h> #include <string.h> typedef struct { char *buf; int size, capa; } Line; typedef struct { char **line; int size, capa; } Text; void check(const void *p) { if (!p) puts("out of memory"), exit(1); } void add_char(Line *p, int c) { if (p->size >= p->capa) { p->capa = p->capa ? p->capa * 2 : 256; p->buf = realloc(p->buf, p->capa); check(p->buf); } p->buf[p->size++] = c; } int getline(Line *p, FILE *fp) { int c; p->size = 0; while (c = getc(fp), c != EOF && c != '\n') add_char(p, c); add_char(p, 0); return c == EOF && p->size == 1 ? EOF : p->size; } void add_line(Text *p, const char *s) { if (p->size >= p->capa) { p->capa = p->capa ? p->capa * 2 : 256; p->line = realloc(p->line, p->capa); check(p->line); } p->line[p->size++] = strdup(s); check(p->line[p->size-1]); } void reverse(const char *s) { int n = strlen(s); while (--n >= 0) putchar(s[n]); putchar('\n'); } int main(void) { Line line = { 0 }; Text text = { 0 }; int i; while (getline(&line, stdin) > 0) add_line(&text, line.buf); for (i = text.size; --i >= 0; ) reverse(text.line[i]); return 0; } |
No.1630![]() |
ひとつわからないことが。 投稿者---KAZ(2004/05/03 20:51:37) |
||
かずまさんほんとうにありがとうございます。ソースのほう、すごくむずかしいですが、ためになります。ところで、昨日からこの部分がどうしてもわかりません。 この部分なんですが、 p->capa = p->capa ? p->capa * 2 : 256; これは if (p->capa != 0) p->capa = p->capa*2; else p->capa = 256; としているんですよね。このコードで p->capaが0じゃなかったらp->capa*2とするのはなぜでしょうか? そしてもし0の場合 256と容量をきめてますが、この256という数字には 何か理由があるのでしょうか? |
No.1631![]() |
Re:ひとつわからないことが。 投稿者---かずま(2004/05/03 21:46:20) |
||
> p->capaが0じゃなかったらp->capa*2とするのはなぜでしょうか? > そしてもし0の場合 256と容量をきめてますが、この256という数字には > 何か理由があるのでしょうか? 256 に特に意味はありません。100 でもいいし、32 でもいいし、極端な話、 1 でもかまいません。でも、1 にすると、何度も realloc が呼ばれ、 capa の値は、2, 4, 8, 16, 32, ... と増えることになります。 用意した領域を使い切ったら、それを拡張するわけですが、 capa * 2 というのは、倍々で増やそうと思っただけのことで、 capa + 256 でも、あるいは他の増やし方でもかまいません。 それから、ひとつバグがありました。add_line の p->line = realloc(p->line, p->capa); を、 p->line = realloc(p->line, p->capa * sizeof(char *)); に訂正します。 |
No.1634![]() |
ありがとうございました。 投稿者---KAZ(2004/05/05 01:08:33) |
||
かずまさん、みなさん、ほんとうにありがとうございます。どうにかすれば、なんでもできるもんなんですね。楽しめました。 |
No.1624![]() |
Re:インプットの文字列の文字数を無制限のプログラムについて 投稿者---YuO(2004/05/01 19:27:14) |
||
>プログラムをかいていてふと思ったのですが、インプットの文字数を制限せずにC言語でプログラムをかくことができるのでしょうか? 物理的な制限以内であれば可能です。 一番手っ取り早いのは,fgetsとreallocを組み合わせることです。 この場合,realloc可能な記憶域というのが限界値になります。 他にはリスト構造に保存したり,木構造に保存したりすることで, 入力文字数の制限を取り払ったかの様に見せかけることは可能です。 #どちらにしても,制限は存在する。 > 入力した文字をバファーにいれる前に文字数が分ればmallocでとれると思うのですがそういったことはできるのでしょうか? stdinの入力は読んでみないことにはわかりません。 改行を入力するタイミングは,ユーザーに任せられているからです。 他のストリームは大抵二度読みが可能なので, 先に読んでからバッファを確保,ということが可能です。 |
No.1625![]() |
関係ない話ですが… 投稿者---nop(2004/05/02 00:20:50) |
||
読みにくいので適度な位置で改行を入れましょう。 |