• ベストアンサー

プログラムの中身の意味

C言語で縦書き表示のプログラムを習ったんですが、プログラム中でわからない個所がありました。まずは、プログラムです #include<stdio.h> void put_haiku(char *nyuuryoku); int main() { char haiku[100]; puts("俳句を入力せよ"); fgets(haiku,sizeof(haiku),stdin); if(haiku[strlen(haiku)-1] == '\n'){ haiku[strlen(haiku)-1] = '\0'; } put_haiku(haiku); return 0; } void put_haiku(char *nyuuryoku) { char *ptr = nyuuryoku; while(*ptr !='\0'){ printf("%c%c\n",ptr[0],ptr[1]); ptr += 2; } return ; } メイン関数内の put_haiku(haiku); はどのような役割をしているのでしょうか? もうひとつ ユーザー定義関数の char *ptr = nyuuryoku; はポインタを宣言し、さらに初期値にnyuuryokuを代入しているということであっていますか? 簡単な質問ですいません

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

  • ベストアンサー
回答No.1

>メイン関数内の put_haiku(haiku); >はどのような役割をしているのでしょうか? 引数「nyuuryoku」で渡されたアドレスから格納されている文字列を(半角)2文字ずつ出力しています。 「縦書き」ということなので「全角(2Byte)文字」を意識しているのでしょう。 >ユーザー定義関数の char *ptr = nyuuryoku; >はポインタを宣言し、さらに初期値にnyuuryokuを代入しているということであっていますか? ほぼあっています。 char型のポインタ変数ptrを宣言し、ptrに対して引数「nyuuryoku」で渡されたアドレス(mainで宣言されているhaikuの先頭アドレス)を代入しています。

su-sen
質問者

お礼

なるほど。ものすごくわかりやすいです。ありがとうございます。

その他の回答 (2)

回答No.3

sinagawa68です。 先ほどの回答は全角文字を考慮していませんでた。 申しわけない・・・。

回答No.2

su-senさん はじめまして。 sinagawa68と申します。 put_haiku(haiku)は引数haiku文字列を縦書き2行でコンソール出力機能を持たせたい のですかね?それとも俳句だから5・7・5かな? 上記プログラムでは、隣り合う文字同士をを並べて出力しているだけなので、文が変に なるのではないですか? char *ptr = nyuuryoku;は構文的に誤りはありません。 ただ上記のput_haiku関数の機能を満たす上では特に必要な宣言ではありません。 引数のnyuuryokuを流用することもできます。プログラムの可読性を向上させたいので あれば話は別ですが・・・、あるところではptrを配列の添え字で参照し、またあるとこ ろではポインタを直接進めるといった書き方は正直可読性が悪いように思えますので、 できればどちらかに統一すると良いでしょう。 余談ですが縦書き5・7・5などで出力したいのであれば、横3文字ずつの出力にし、ル ープ処理とポインタの移動位置を5・7・5に合うように調整するとよいと思います。 また、5・7・5の5の部分はスペース文字などを挿入して7の部分がずれないように工 夫すると良いでしょう。 では。

関連するQ&A

  • strlen

    c言語初心者です。 10文字以上入力すると警告してくれるプログラムを考えています。 一応文字数を制限するにあたりstrlenを使おうとしてるのですが 思ったように機能してくれません。 以下が私の書いたプログラムです。 void main() { char name[10]={0}; memset( name, '\0', sizeof(name) ); loop: puts("*****登録*****"); printf(" 名前 :"); fgets(name,10,stdin); //バッファクリア**// if(strchr(name,'\n') == NULL) { while(getchar() != '\n'); } if(strlen(name)>10) { puts("<<文字入力数が多すぎです>>"); fgets(name,10,stdin); //バッファクリア**// if(strchr(name,'\n') == NULL) { while(getchar() != '\n'); } system("cls"); goto loop; } else { puts("OK"); } } よろしくお願いします。

  • このプログラムは「こんにちは」と打つと「こんにちは、元気ですか」と返答

    このプログラムは「こんにちは」と打つと「こんにちは、元気ですか」と返答するプログラムです このプログラムを改良して「こんにちは」と打つと「こんにちは、元気ですか」と言うようなキーワードを打つ決められた回答をするようなものを増やしていきたいのですが、どのように改良すればよいでしょうか? 例えば 「寒いですね」といれると「冬だからね」となるように #include <stdio.h> #include <string.h> int reply(const char *s) { const char *reply_s[] = {"こんにちは 元気ですか?", "バイバイ", "ふ~ん?"}; if(strstr(s, "こんにちは")) puts(reply_s[0]); else if(strstr(s, "さようなら")){ puts(reply_s[1]); return 0; } else puts(reply_s[2]); return 1; } int main(void) { char s[128]; do{ char *p; fgets(s, sizeof s, stdin); if(p = strchr(s, '\n')) *p = '\0'; }while(reply(s)); return 0; }

  • 入力されたとき,何も入力しない,もしくは20字以上だと再入力のプログラム??

    こんにちわ, 今Cの勉強をしているんですが,入力をして,何も入力しないもしくは20字以上だと再入力させるのプログラムを作りたいんですけどどうしたらよろしいでしょうか。 char sk[21]; start1: while(stdin = " puts("入力"); if ((*fgets(sk,sizeof(sk),stdin) < 0x21) || strlen(sk) >= 21 ) {   puts("error");   goto start1; } だと,20字以上のときにstdinのバッファに残ってしまってエラー表示が2度出ます。 ちなみにfflush(stdin)は使用できないANSI C規格です。 よろしくお願いします。

  • ファイルの内容の表示

    実行時のコマンドライン引数で指定したファイルの内容を、行番号付きで画面に表示するプログラムを作る という問題です。ヒントも与えられています。 行番号付きの表示、コマンドライン引数の利用。両者を組み合わせればできるはずだ >  main関数の引数にargcとargvを指定して、コマンドライン引数をファイル名として利用する。キーボード入力を促す文(プロンプト)や改行チェックは不要なので書かないこと >  コマンドライン引数が指定されない場合は、メッセージを表示してプログラムを終了 >  ファイルの内容を画面表示する処理は、ユーザー定義関数put_file_contentsに記述する。仮引数には文字型のポインタ変数をひとつ指定し、ファイル名を受け渡せるようにする。put_file_contents自体の型は整数型(int)で、正常終了なら返り値0を返すこと。 行番号付きのプログラム#include<stdio.h> > int put_file(char *filename); > > int main() > { > char line[50]; > char *ptr; > > printf("ファイル名を入力:"); > fgets(line,sizeof(line),stdin); > ptr = line + strlen(line) - 1; > if(*ptr == '\n') { > *ptr = '\0'; > } > > put_file(line); > > return 0; > } > > int put_file(char *filename) > { > FILE *fp; > char buf[100]; > int line_no; > > fp = fopen(filename,"r"); > if (fp == NULL){ > printf("%sを開けません\n",filename); > return 1; > } > line_no = 1; > while (fgets(buf,sizeof(buf),fp) != NULL){ > printf("%3d: ",line_no); > printf("%s",buf); > line_no++; > } > fclose(fp); > > return 0; > } で、コマンドライン引数のプログラムは#include<stdio.h> void write_key_inputs(char *filiname); int main(int argc, char *argv[1]) { write_key_inputs(argv[1]); return 0; } void write_key_inputs(char *filename) { FILE *fp; char buf[100] ; fp = fopen(filename,"w"); while(fgets(buf, sizeof(buf),stdin) != NULL) { fputs(buf, fp); } fclose(fp); return ; } です。これらを組み合わせて少しいじると出来るみたいなのですが、できていません。ちなみに私が考えたプログラムは #include<stdio.h> int put_file_contents(char *filename); int main(int argc,char *argv[]) { int i; if(argc == 1){ printf("コマンドライン引数がありません\n"); return 1; } for(i = 0;i<argc;i++) printf("argv[%d]は「%s」です\n",i,argv[i]); put_file(i); return 0; } int put_file(char *filename) { FILE *fp; char buf[100]; int line_no; fp = fopen(filename,"r"); line_no = 1; while (fgets(buf,sizeof(buf),fp) != NULL){ printf("%3d: ",line_no); printf("%s",buf); line_no++; } fclose(fp); return 0; } です。コマンドライン引数は表示されるのですが、行番号が表示されません。どうしたらいいでしょうか??

  • C++のoperator関数でのキャストする場合の書き方がまだよく理解

    C++のoperator関数でのキャストする場合の書き方がまだよく理解できていません。 下記のコードで、 //ここから #include "stdafx.h" #include <string> #include <iostream> class AutoPtr { char *ptr; public: AutoPtr():ptr(0) { } ~AutoPtr() { delete [] ptr; } // char *operator=(char *ptr) { delete [] this->ptr; this->ptr = ptr; return this->ptr; } operator char *(){ return ptr; } char &operator[](int index) { return ptr[index]; } }; void reverse(char *str) { int i, n; AutoPtr work; n = strlen(str); work = new char[n+1]; strcpy(work, str); for(i=0; i<n; i++) { str[i] = work[n-i-1]; } printf("%s\n", str); } int _tmain(int argc, _TCHAR* argv[]) { char str[] = "ABCDEFG"; reverse(str); return 0; } //ここまで 2番目のoperator関数の定義ですが、 operator char *(){ return ptr; } これは多分、reverse()関数中の、 strcpy(work, str); のworkの展開に用いられると思うのですが、 機能としては、「operator char *」はAutoPtrをchar *にキャストするために使われているらしいのですが、何故この書き方でAutoPtrをchar *型にキャストできるのかがいまいち分かりません。また、2番目のoperator関数の記述「operator char *()」はどこまでが型で、どこからが関数の定義と見なせばよいのでしょうか? 何か勘違いしているかもしれません。理解されている方、御教示いただければと思っています。 よろしくお願い致します。

  • 数字を入力して配列に格納するプログラムを書きたいです。

    各行任意個の数字をスペースで区切って入力し、格納する数字は10個までとします。また、/の入力以降は数字を格納せず、プログラムを終了するようにしたいです。 PrintNumは配列に格納された数字を順番に印字する関数として、次のプログラムを書くと、数字を入力するとき、2行目を入力しようとするとエラーになってしまいます。 char line[50]; char *ptr; int count=0; int numbers[50]; while(*ptr!='/'){ fgets(line,50,stdin); ptr = strtok(line," "); if(ptr!=NULL && *ptr!='/') numbers[count++]=atoi(ptr); if(count>=10){ PrintNum(numbers,count); return 0; } while(ptr!=NULL && *ptr!='/'){ ptr=strtok(NULL," "); if(ptr!=NULL && *ptr!='/') numbers[count++]=atoi(ptr); if(count>=10){ PrintNum(numbers,count); return 0; } } } PrintNum(numbers,count); return 0; 最初のwhile文でたとえば while(1) とすると2行目以降も入力できることがわかったのですが、上のプログラムは何がまずいのかわかりません。教えていただけると幸いです。

  • C言語のプログラム問題に対応するBNFの書き方がわかりません

    C言語のプログラムからBNFにする方法を習っているのですが、どうしてもそのやり方がわかりません。 下にあるプログラムに対応するBNFを自分で作成してみたのですが、 <A>::=A|Bぐらいしかできませんでした。このBNFを作っても、なぜこうなるのかもわかりません。 #include<stdlib.h> #include<stdio.h> #include<string.h> enum symboltype{SMILE,HELLO,BYE,END}; void A(); void B(); void scan(); void error(char *msg); enum symboltype next; int main(int argc, char* argv[]){ scan(); A(); if(next != END) error("#PARSE ERROR#"); else puts("#PARSE OK#"); return 0; } void A(){ if(next != SMILE) error("#PARSE ERROR#"); else puts("#PARSE OK#"); return 0; } void B(){ if(next != SMILE){ scan(); return; }else if(next != HELLO){ scan(); A(); if(next != BYE) error("#PARSE ERROR#"); scan(); }else error("#PARSE ERROR#"); } void error(char *msg){ puts(msg); exit(1); } void scan(){ char buff[10]; if(fgets(buff,10,stdin)==NULL){ next=END; return; } if(strcmp(buff,"hello\n")==0) next=HELLO; else if(strcmp(buff,"bye\n")==0) next=BYE; else if(strcmp(buff,"(*_*)\n")==0) next=SMILE; else error("#UNKNOWN TOKEN#"); } このプログラムに対応するBNFを教えてほしいんです。 お願いしますm(_ _)m また、BNFはどのように書くのかも教えていただけませんか。

  • 入力制御

    c言語初心者です。 以下のプログラムをみてください。 #include<stdio.h> int main() { char ch[3]; fgets( ch, 3,stdin );   if(ch[0]=='3') { printf("Hello!\n"); } else if(ch[0]=='2') { puts("回る"); } else{ puts("間違いf"); } return 0; } このプログラムでは2を入力すると"回る"と表示されますが 2wでも同じように表示されてしまいます。 制限して2wで入力したら"間違い"と表示させたいのですがなかなかうまくいきません。 どなたか教えてください。

  • C++のコンストラクタを使った自動ポインタでoperator関数の使い

    C++のコンストラクタを使った自動ポインタでoperator関数の使い方で分からないところがあります。 環境下はVisual C++でC/C++のWin32コンソールアプリケーションを使って行っています。 下記のコードで実行させています。やっていることは文字列を反転させて表示させるだけのことです。 #include "stdafx.h" #include <string> #include <iostream> class AutoPtr { char *ptr; public: AutoPtr():ptr(0) { } ~AutoPtr() { delete [] ptr; } // char *operator=(char *ptr) { delete [] this->ptr; this->ptr = ptr; return this->ptr; } operator char *(){ return ptr; } char &operator[](int index) { return ptr[index]; } }; void reverse(char *str) { int i, n; AutoPtr work; n = strlen(str); work = new char[n+1]; strcpy(work, str); for(i=0; i<n; i++) { str[i] = work[n-i-1]; } printf("%s\n", str); } int _tmain(int argc, _TCHAR* argv[]) { reverse("ABCDEFG"); return 0; } これを実行させると、reverse関数のfor()文の、str[i] = work[n-i-1];を実行させた所で実行エラーになってしまいます。その前の、strcpy(work, str);でworkにstrの内容が正常にコピーされているところまでは確認できています。operator関数の、 char &operator[](int index) { return ptr[index]; } で、operator[]はAutoPtrを配列のように扱っているはずなのですが、何故かstr[i] = work[n-i-1]; の所で実行エラーになってしまいます。 operaror関数の書き方が悪いのか、何が原因なのか分かりかねています。御経験のあるかたは、御教示いただけたらと思っています。 よろしくお願い致します。

  • プログラム

    文字列を逆順にする関数を作ってるのですがうまくできません。 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; } このプログラムの間違ってる所をおしえてください。

専門家に質問してみよう