文字列を先頭から1文字ずつ表示する関数の作成

このQ&Aのポイント
  • C言語を使用して、文字列を先頭から1文字ずつ表示する関数を作成します。
  • gput関数は、引数として表示する文字列と表示速度(ミリ秒単位)を受け取ります。
  • gput関数は、forループを使用して文字列の各文字を順番に表示し、一定の時間待機します。
回答を見る
  • ベストアンサー

問題文に対してこのプログラムは正しいか

文字列を先頭から1文字ずつ表示する関数を作成せよ。 void gput(const char *s, int speed); ここで、sは表示する文字列、speedはミリ秒単位の表示速度である。たとえば、 gput("ABC", 100); と呼びだすと、まず'A'を表示し、その100ミリ秒後に'B'を表示し、さらにその100ミリ秒後に'C'を表示する。このようにして"ABC"の全文字を表示すると呼び出し元に戻ること。 /* 課題2-1 */ #include <time.h> #include <stdio.h> #include <stdlib.h> /* gput関数の宣言 */ void gput(const char *s, int speed); /* sleep関数の宣言 */ int sleep(unsigned long x); int main (void) { gput("ABC", 1000); return (0); } /* gput関数の定義 */ void gput(const char *s, int speed) { int i; int c = strlen(s); for(i=0; i<c; i++){ putchar(s[i]); fflush(stdout); sleep(speed); } } /* sleep関数の定義 */ int sleep(unsigned long x) { clock_t c, s = clock(); do{ if((c = clock()) == (clock_t)-1) return (0); }while(1000UL * (c - s) / CLOCKS_PER_SEC < x); return (1); } 演習問題に解答が無いので質問します。 呼び出し元に戻ることとは、gput関数を呼び出した後にmain関数に戻ることを言っているのでしょうか。 またsleep関数では、return 0とreturn1を使い分けていますがそれぞれどういった意味があるのですか。 関数の返り値は理解できるのですが、本にmain関数のreturn0についてなど何も触れられていないので混乱しています。

質問者が選んだベストアンサー

  • ベストアンサー
  • bluehat43
  • ベストアンサー率52% (9/17)
回答No.2

まずおっしゃってる通りで、「呼び出しに戻る」とはmain関数に戻る事です。これは普通に関数を作成すると勝手に呼び出し元に戻りますし、仮に戻らない関数を作っても実用性はありませんから、あまり気にしなくていいかと思います。 sleep関数ですが、clock()関数はプログラムが開始されてからの経過時間を返す関数で、何らかの事情(システム側の事情)で経過時間が返せない状況の場合、-1を返す事になっています。 つまりsleep関数は、指定されたミリ秒の間スリープさせるのですが、システム側の問題で時間が取得できなかった場合は0を返して、正常に指定時間分のスリープができた場合は1を返すような作りになってるわけです。 ただし呼び出し元では、戻り値が0か1で条件分岐させていませんから、もし100ミリ秒という時間が計測できないような状況(これはシステムが壊れでもしない限り通常は起きない)の場合、エラーも何も表示しないプログラムという事になります。 このプログラムを見る限り、sleep関数で戻り値を使い分けているのは意味がないと思うかもしれませんが、関数というのは単体で汎用性を追及して作った方が利便性が増します。 この課題では意味がなくても、システムの時間が取得できた場合とできない場合とで処理を分けたいようなプログラムでは役に立ちます。 なので、sleep関数については「汎用性を考慮して作られているが今回はあまり意味がない」という理解でいいかと思います。

tanosiiC
質問者

お礼

わかりやすい解答ありがとうございます。 sleep関数では返り値を分けているけれども意味は今のところ無いんですね。

その他の回答 (5)

  • kmee
  • ベストアンサー率55% (1857/3366)
回答No.6

> mainの戻り値 おそらく、GUIでダブルクリックで起動、動作は自分自身で完結している、ってものしか作らなければ、あまり意識することもないでしょう。 バッチファイルや各種スクリプトから使おうとすると、この戻り値を有効に使うことが求められます。 例えば「ファイルをコピーして、成功したら元ファイルは消す」というバックアップを実行する場合、コピーがなんかの理由で正常終了しなかった場合、削除を実行する意味がない(実行してはいけない)、となります。 この時に正常終了かどうかを判定するのに使うのが「main関数の戻り値」です。 0なら正常、それ以外なら異常。その値はバッチファイルならERRORLEVEL変数で調べられるので、返す値を細かく分けて、ERRORLEVELによって後処理を分岐する、ということもできます

tanosiiC
質問者

お礼

まだ自分の知識では曖昧ですが全ての文に意味があることがわかりました。 ありがとうございます。

  • mesoneer
  • ベストアンサー率20% (2/10)
回答No.5

私が昔C言語を習った時に、「C言語は関数のみで構成される言語」という話を聞いた記憶があります。 そんなわけで、上記プログラムの本体はmain関数となるので、main関数の戻り値は、 プログラムの戻り値とも言えます。 あまり使わないとは思いますが、あるプログラムから別のプログラムを呼び出すような時、 プログラムが正常終了したのか異常終了したのかを判断するのにmain関数の戻り値を使うこともあります。 普通はそんなことせず、DLL化したりマルチスレッド・マルチプロセスとしますが・・・。 なんにせよ、main関数は return 0; としておけば問題ありません。 また、sleep関数のように戻り値を成功/失敗としておくと、 呼び出す時に以下のように書けて便利です。 if (sleep(speed)) { /* 成功 */ } else { /* 失敗 */ }

tanosiiC
質問者

お礼

ありがとうございます。 失敗した時のことも考えてプログラムをかけますね。

  • bajutsu
  • ベストアンサー率20% (139/693)
回答No.4

解答が無いんだよね? ということは自分で作ったんでしょ? sleepのreturnを、return(0) と return(1) に分けるのは 設計者(=質問者)がそういう設計にしたからでしょう。 それとも、他人の答えをコピペしたの? 「解答」はあるけど「解説」が無いの間違い?

tanosiiC
質問者

補足

sleep関数は例題などで使われておりコピペみたいなものです。 演習問題では解答も解説も無いです。

  • Tacosan
  • ベストアンサー率23% (3656/15482)
回答No.3

ちなみに main の返り値については 本来の処理が正常に終わったら 0 とするのが「お約束」です.

tanosiiC
質問者

補足

どの返り値を返しても動くけれどもお約束として0を返すってことですか?

回答No.1

実際に作ってみれば

tanosiiC
質問者

補足

実際に作って動かしています。 わかりにくくてすいません。

関連するQ&A

  • このプログラムのどこを直せばいいんでしょうか?

    いま、文字列strの中に文字cが含まれている個数を表示するプログラムを作っているんですが、下のように作っても、上手く行きません。 どこをどう直せばいいのか教えてください! #include <stdio.h> int str_chnum (const char str[],int d) { int i=0; int sum=0; while(str[i]!=0){ if(str[i]==d ){ sum++; } i++; } return(sum); } int main(void) { int c; char str[128]; puts("put sentence..."); scanf("%s",str); puts("search character..."); scanf("%d",&c); printf("there are %d %ds in this sentence.",str_chnum(str,c),c); return(0); }

  • abcdとキーボードで打ったらdcbaと表示されるプログラム

    C言語に関しては初心者です。 メイン関数は変更せずに行います。 /* reverse.c: reverse a given string */ #include <stdio.h> #include <string.h> void reverse(char *); /* プロトタイプ宣言 */ int main(void) { char str[100]; scanf("%s", str); reverse(str); printf("%s\n", str); return (0); } void reverse(char *s) { char n; int i; char str; n = strlen(str) - 1; for(i=0,i++,i<=100) { s[i] = *s[n-i]; printf("%s\"s[i]); } }

  • プログラム

    文字列を逆順にする関数を作ってるのですがうまくできません。 void reverse(char *str, int count=0) { int i; char *s="momonga"; s+=strlen(s); count=strlen(s); for(i=count; i<0; i--, str++, s--){ *str++=*s++; } } int main() { char s1[20]; int c; reverse(s1,c); printf("%momongaを逆順にすると%sで文字数が%dです",s1,c); return 0; } このプログラムの間違ってる所をおしえてください。

  • 多桁 計算プログラム

    下のプログラムを (1)上位桁の不要な0を表示しない (2)3つの数を計算できるようにする (3)0が入力されるまでは入力を受け付けて加算を繰り返す プログラムに改造する方法を教えてください。 #include <stdio.h> #define MAXDIGIT 70 void reset(char*,int); void input(char*,int); void add(char*,char*,char*,int); void add_digit(char ,char ,char ,char* ,char* ); void display(char* ,char* ,char* ,int ); void lineprint(char ,char* ,int ); void linedraw(char ,int ); int main(void) { char a[MAXDIGIT],b[MAXDIGIT],c[MAXDIGIT]; reset(a,MAXDIGIT); reset(b,MAXDIGIT); reset(c,MAXDIGIT); input(a,MAXDIGIT); input(b,MAXDIGIT); add(a,b,c,MAXDIGIT); display(a,b,c,MAXDIGIT); return 0;} void reset(char* buf,int maxdigit) { int i; for(i=0;i<maxdigit;i++) buf[i]=0; return;} void input(char* buf,int maxdigit) { char str[MAXDIGIT]; int i,j; printf("input data:"); scanf("%s",str); i=0; while(str[i]!='\0') i++; j=0; while(i>0){ buf[j]=str[i-1]-'0'; j++; i--; } return;} void add(char* a,char* b,char* c,int maxdigit) { int i; char carry_in,carry_out; i=0; carry_in=0; while(i<maxdigit) { add_digit(a[i],b[i],carry_in,&c[i],&carry_out); carry_in=carry_out; i++;} return;} void add_digit(char a,char b,char carry_in,char* c,char* carry_out) { *c=(a+b+carry_in)%10; *carry_out=(a+b+carry_in)/10; return;} void display(char* a,char* b,char* c,int maxdigit) { lineprint(' ',a,maxdigit); lineprint('+',b,maxdigit); linedraw('-',maxdigit+1); lineprint(' ',c,maxdigit); return;} void lineprint(char c,char* line,int maxdigit) { int i,maxdigitlimit; maxdigitlimit=maxdigit-1; printf("%c",c); for(i=maxdigitlimit;i>=0;i--){ printf("%1d",line[i]); } printf("\n"); return;} void linedraw(char c,int length) { int i; for(i=0;i<length;i++) printf("%c",c); printf("\n"); return;}

  • 4桁の英字の3桁目を当てるプログラム

    乱数でとってくる4ケタの英字の3桁目を入力して当てるプログラムを 組もうとしているのですが、コンパイラしてもいまいちうまくいきません。 特に下に書いたプログラムのこの部分が違っていると思い どのように修正したらよいのか指摘していただきたいです。 human=getchar(); if(comp[2]!=human) { ero=1; } よろしくお願いします。 #include<stdio.h> #include<stdlib.h> #include<time.h> #include<string.h> int sleep(unsigned long x) { clock_t c1=clock(),c2; do{ if((c2=clock())==(clock_t)-1) { return 0; } }while(1000.0*(c2-c1)/CLOCKS_PER_SEC<x); return 1; } int main(void) { int num,val,i,j; char comp[21]; char human; int ero=0; int try_count=0; int seikai=0; clock_t start,end; int num1; char eiji[]="ABCDEFGHIJKLMNOPQRSTUVWXYZ"; srand(time(NULL)); puts("英字記憶トレーニング"); do{ printf("挑戦するレベル(3~20):"); scanf("%d",&num1); }while(num1<3 || num1>20); printf("%d個の英字を記録しましょう。\n",num1); start=clock(); do{ for(i=0;i<num1;i++) { comp[i]=eiji[rand()%strlen(eiji)]; } comp[num1]='\0'; printf("%s",comp); fflush(stdout); sleep(125*num1); printf("\r%*s\r3番目の英字を入力してください:",num1,""); human=getchar(); if(comp[2]!=human) { ero=1; } if(ero==0) { printf("正解です。\n"); seikai++; } else { printf("\a間違いです。\n"); } try_count++; }while(try_count<2); end=clock(); printf("%d回中%d回成功しました。\n",try_count,seikai); printf("%.1f秒でした。\n",(double)(end-start)/CLOCKS_PER_SEC); return 0; }

  • 2つのプログラムの違い

    どうしても分からなかったので投稿しました。よろしくお願いします。 #include<stdio.h> int main(void) { int c; while((c=getchar())!=EOF){ putchar(c); } return 0; } のプログラムをコマンドプロンプトで入力すると、 abc abc なんですが、 #include<stdio.h> int main(void) { int c,i; i=0; while ((c=getchar())!=EOF) { putchar(c); i++; printf("%d\n",i); } return 0; } の場合、 abc a1 a2 a3 4 になります。 自分は abc a1 a2 a3 になると思ったのですが、a3と4の隙間と4は何故出て来たのでしょうか?

  • C言語 説明文

    C言語(文字列のコピーについて) /* 文字列のコピーを行う関数の実現例 動作原理のコメントを書き入れる */ #include <stdio.h> /*-----文字列のコピー(1)-----*/ char *scpy1 (char *d, const char *s) { int i = 0; while ((d[i] = s[i]) != '\0') { i++; } return(d); } /*-----文字列のコピー(2)-----*/ char *scpy2 (char *d, const char *s) { char *p = d; while ((*d = *s) != '\0') { d++; s++; } return(p); } /*-----文字列のコピー(3)-----*/ char *scpy3 (char *d, const char *s) { char *p = d; while ((*d++ = *s++) != '\0') { ; } return(p); } /*-----文字列のコピー(4)-----*/ char *scpy4 (char *d, const char *s) { char *p = d; while (*d++ = *s++) { ; } return(p); } int main(void) { char astr[] = "ABC"; char bstr[8], cstr[8], dstr[8],estr[8]; scpy1 (bstr, astr); scpy2 (cstr, astr); scpy3 (dstr, astr); scpy4 (estr, astr); printf("astr = %s\n" , astr); printf("bstr = %s\n" , bstr); printf("cstr = %s\n" , cstr); printf("dstr = %s\n" , dstr); printf("estr = %s\n" , estr); return (0); } ----------------------- このプログラムに、この行で何をやっているのかわかるように 一言くらいの説明文を入れる問題です。 ところどころはわかるのですが、わからないところの方が多いです。 プログラムが長くて大変かとは思いますが、どうかよろしくお願いいたします。 このプログラム自体はちゃんとコンパイルでき、実行もできたので おそらく間違いないと思います。

  • C++の問題で困っています。

    C++の問題で困っています。 今,C++の入門書を読んでその中の演習問題に取り組んでいるのですが、この本には答えがついていないみたいなので、問題で悩んでいます。 お力を貸してください。 問題 「文字列 s に含まれる最も先頭に位置する文字 c へのポインタを返す関数 strchr_ptr を作成せよ。型は char * strchr_ptr(const char *s, char c); とする。例えば、文字列 s が "ABSZXYX" で文字 c が 'X' であれば、返却するのは &s[4]である。 なお、文字 c が文字列 s に含まれない場合は NULL を返却すること。 」 です。 僕はこの問題に対して、以下のように答えました。 ヘッダのインクルードなどは省きます。 char *strchr_ptr(const char *s, char c) {         for(int i = 0; s[i]; i++)         if(s[i] == c)             return const_cast<char *>(&s[i]);     return NULL; } int main() {     char s[36] = "ABSZXYX";     cout << strchr_ptr(s, 'X') << "\n";     cout << &s + 4 << "\n"; } と書きました。 cout << &s + 4 << "\n"; はこの上の文で導き出したアドレスがあっているか確かめるものです。 ですが、これをコンパイルして実行すると、 ----------------- XYX 0012FFE0 ----------------- となり、関数側のほうはアドレス的な表記をしてくれません・・。 どうにかして、アドレス表記にしようとあれこれ考えたのですが、どうしても出来ませんでした。 どのようにしたらいいのか教えてください。 初歩的な質問ですが、よろしくお願いします。

  • C言語のint型の配列が分かりません

    #include<stdio.h> int main(void) { int str[ ]={0,1,2} printf("%s\n", str); return 0; } というプログラムをC言語でつくってみましたが動きません.(012と表示されて欲しかったのですが) int str[ ]={1,2,3}の部分をchar str[ ]={'0','1','2'}とすれば動きます. そこで質問なのですが, printf("~%s~", (配列名));  はchar型の配列にしか適応できないのですか? ※追記 puts関数の定義は int puts (const char *str); であるそうなので char型の仮引数にはchar型のアドレスを渡さなければいけません. ではprintf関数の定義は一体どんなものなのですか?

  • 副プログラム内(void mystery(char s1[],char s2[]))の動作確認文 

    お忙しい中失礼します。 下記のプログラム内の動作について質問があります。宜しければご回答願います。 void mystery(char s1[],char s2[]) { int i=0; while(s2[i]!='\0'){ //s2[i]内に文字が入力され、エンターキーが入力されるまで{s1[i] = s2[i]; ++i;}内の動作を行う。 s1[i] = s2[i];    //s1[i] を基準にs2[i]の文字数を++iを使い、カウントする。 ++i;         //++iはただs1[i] とs2[i]の文字が合致してるか確認を行う。s1[]=”Good”なら s2[]=”Good”の各文字が合致してるかどうか。 } s1[i] = '\0';    //s1[i]にエンターキーが入力されて、void mystery(char s1[],char s2[])内のループを抜ける。 return;       //s1[i] = '\0'で'\0'が定義されているのでreturn 0;でない? } ↑上記動作質問://より右側の文章は文章的に正しいでしょうか? void mystery(char s1[],char s2[])内でどんな動作をしてるのかが、イマイチよく分からないのです。 ↓下記のプログラム #include <stdio.h> #include <stdlib.h> void mystery(char [], char[]); int main() { char m1[81],m2[81]; int i; printf("Message?"); gets(m1); mystery(m2,m1); puts(m2); system("PAUSE"); return 0; } void mystery(char s1[],char s2[]) { int i=0; while(s2[i]!='\0'){ s1[i] = s2[i]; ++i; } s1[i] = '\0'; return; }

専門家に質問してみよう