ページ 11

関数の作り方

Posted: 2007年4月15日(日) 12:15
by
こんにちは★ぉひさしぶりです。
関数の作り方の質問です。
たぶん、みなさんにとっては、全然やさしい問題だと思うんですが、私はいまだにいまいち理解ができません。。。

今回、『入力された文字列を指定された方向(左右)にローテートするプログラム』をつくりました。
頑張って作ったのですが、提出する時は、『左ローテートする関数と右ローテートする関数を作成すること』と注意をうけました。

私が作ったプログラ厶は、以下のようです。
#include <stdio.h>

main(){
  
  char moji[100];         /*文字をいれる配列*/
  char a;
  int houkou;            /*ローテートの方向を選ぶ*/
  int i,n;                 /*配列内の位置*/
  
  printf("文字列を入力してください:");
  scanf("%s",&moji);
  
  printf("左右どちらにローテートしますか?(左:1,右:2): ");
  scanf("%d",&houkou);
  
  if(houkou==2){            /*右を選択したとき*/
    for(i=8;i>=0;i--){
      moji[i+1]=moji;
      
      if(moji=='\0')    n=i;

    }
    moji[0]=moji[n];
    moji[n]='\0';
  }

  else if(houkou==1){            /*左を選択したとき*/
    a=moji[0];
    for(i=0;moji!='\0';i++){
      moji=moji[i+1];
    }
    moji[i-1]=a;
  }
  else{                          /*それ以外のとき*/
    printf("エラー\n");
    return -1;
  }
  
  printf("ローテート結果:%s\n",moji);   /*ローテート結果を表示する*/
  return 0;
}

 
 

このプログラ厶をどのようにして関数を利用したものにつくり変えればいいんでしょうか?
ご指導お願いします。

Re:関数の作り方

Posted: 2007年4月15日(日) 13:13
by 管理人
上記プログラムは配布されたもので、それを関数化することが課題ですか?

Re:関数の作り方

Posted: 2007年4月15日(日) 13:17
by
いいえ。
もともと問題は関数を使って提出する問題なんですが、関数の作り方が分からないので、普通にプログラムを作りました。なので、このプログラムは私が自分で作ったものです。

なにか違うところがあったんでしょうか??
一応、プログラム的には、コンパイルもできるし、ちゃんと実行できるので、問題ないと思うのですが・・。

Re:関数の作り方

Posted: 2007年4月15日(日) 13:18
by 管理人
自作関数の作り方は過去にこのような回答をしていますので

http://www.play21.jp/board/formz.cgi?ac ... q&rln=5134

よければ参考にしてください。

Re:関数の作り方

Posted: 2007年4月15日(日) 13:19
by 管理人
***自作関数について***



***変数の有効範囲について***

をご覧下さい。

Re:関数の作り方

Posted: 2007年4月15日(日) 13:23
by 管理人
あらら~、そうですか、自作したものだと書いてありましたね、寝てないので集中力が・・><
すみませんzzz

Re:関数の作り方

Posted: 2007年4月15日(日) 13:24
by
こんな感じでしょうか??


#include <stdio.h>

int main(void){

char moji[100]; /*文字をいれる配列*/
int houkou; /*ローテートの方向を選ぶ*/
int i; /*配列内の位置*/

printf("文字列を入力してください:");
scanf("%s",&moji);

printf("左右どちらにローテートしますか?(左:1,右:2): ");
scanf("%d",&houkou);

if(houkou==2){
right_rotate(moji,i);
}

else if(houkou==1){
left_rotate(moji,i);
}

else{
printf("エラー\n");
return -1;}

printf("ローテート結果:%s\n",moji);
}

/*右ローテート関数*/
int right_rotate(char moji[/url],int i){
int n;
for(i=8;i>=0;i--){
moji[i+1]=moji;

if(moji=='\0') n=i;

}
moji[0]=moji[n];
moji[n]='\0';
return ;
}

/*左ローテート関数*/

int left_rotate(char moji[/url],int i){
char a;
a=moji[0];
for(i=0;moji!='\0';i++){
moji=moji[i+1];
}
moji[i-1]=a;
return ;
}

Re:関数の作り方

Posted: 2007年4月15日(日) 13:38
by 管理人
そういう感じなんですけど、これではコンパイルとおりませんよね?
何かエラーが出ているはずです。

というのも、関数を呼んでいる地点より下に自作関数があるので、コンパイラはどこに関数があるのかわからないのです。
メイン関数より下に自作関数を書く場合は「プロトタイプ宣言」が必要です。
プロトタイプ宣言なしに書くには単にメイン関数より上に書きます。

また、

int xxx(){

}

というint型関数であるにもかかわらず、returnの値がありません。
int型関数というのは、関数を呼んだ地点にint型で何か値を返すという意味です。
にもかかわらず
return ;
と、returnに値が返されていないのでエラーになります。
値を返す必要が無いのならvoid関数にしましょう。

void xxx(){

}

こんな形です。
そうすればとりあえず良いはずです。

しかし、メイン関数がmainから始まっています。

int main(){

ではじめたほうがいいでしょう。
また、このプログラムでは最大8文字までしか対応できませんがいいのでしょうか?

Re:関数の作り方

Posted: 2007年4月15日(日) 13:42
by
まず、引数にとしていれるべきものがわからないんですが・・・
例えば左ローテート関数では、char moji[/url],int iを仮引数にして、char aは仮引数にしてないのですが、いいのでしょうか??

Re:関数の作り方

Posted: 2007年4月15日(日) 13:49
by
直してみました★

#include <stdio.h>

void right_rotate(char moji[/url],int i);
void left_rotate(char moji[/url],int i);

int main(){

char moji[100]; /*文字をいれる配列*/

int houkou; /*ローテートの方向を選ぶ*/

int i; /*配列内の位置*/

printf("文字列を入力してください:");

scanf("%s",&moji);

printf("左右どちらにローテートしますか?(左:1,右:2): ");

scanf("%d",&houkou);

if(houkou==2){

right_rotate(moji,i);

}


else if(houkou==1){

left_rotate(moji,i);

}


else{

printf("エラー\n");

return -1;
}

printf("ローテート結果:%s\n",moji);

}

/*右ローテート関数*/

void right_rotate(char moji[/url],int i){

int n;

for(i=8;i>=0;i--){

moji[i+1]=moji;

if(moji=='\0') n=i;

}

moji[0]=moji[n];

moji[n]='\0';

return ;

}

/*左ローテート関数*/

void left_rotate(char moji[/url],int i){

char a;

a=moji[0];

for(i=0;moji!='\0';i++){

moji=moji[i+1];

}

moji[i-1]=a;

return ;

}

Re:関数の作り方

Posted: 2007年4月15日(日) 13:53
by
どうでしょうか??

Re:関数の作り方

Posted: 2007年4月15日(日) 14:07
by 管理人
>char moji[/url],int iを仮引数にして、char aは仮引数にしてないのですが、いいのでしょうか??

まず、aはメイン関数で使用する機会がないので、自作関数内だけで使用できればよいため、それでOKです。
一方iも自作関数内でしか使用していないので、渡す必要がありません。
それぞれの自作関数内で宣言させてください。引数は一つで大丈夫です。
要は両方の関数内で使用する変数だけ受け渡してやればいいのです。

入力した文字列の長さを調べて、どのような長さの文字列でも対応できるようにする必要はないのでしょうか?
右に動かす処理の方法と左に動かす処理の方法が若干違うので、統一した方がキレイに見えるようにも思います。


ちょっと出かける必要がありますので、ちょっと待ってください^^;
よければサンプル作りますね。

Re:関数の作り方

Posted: 2007年4月15日(日) 14:16
by
そうですか。
つまりmain関数で使わないものかつ、自作関数の変数的につかうものは、仮引数にする必要はないんですね!!
つまり・・・mainに値を返すものだけを、自作関数の仮引数にすればいいんですよね。

それでは、iも仮引数から外せばいいですね。

はい。文字列の長さを調べる必要は得にないんですが、確かに、今のままだと8文字までしかだめですよねー。8を100に変えちゃえばいいですかねー。

出かけるんですかー^^
気を付けてくださいねー★
はい、また返答お待ちしてます★
お願いします。

Re:関数の作り方

Posted: 2007年4月15日(日) 14:18
by
そうなんですよ。右と左のローテートのやり方が統一できなくて、このようなやりかたしか思い付かなかったですよ。統一できちゃうんですか???いろいろ方法があるんでしょーね。

Re:関数の作り方

Posted: 2007年4月15日(日) 21:25
by 管理人
ただ今帰りました。休みの日で天気のいい日は必ずツーリングに行くのでm(_ _)m
春なんで、ツーリングにいい時期ですねぇ、ブログにも書きましたが昨日も観光に行ってました☆

では、回答の続きです。
左にローテートする関数でこんな感じにしてみました。
lenには文字列の長さが入っています。
void rotate_left(char moji[/url],int len){
	int i;	char a;
	a=moji[0];
	for(i=0;i<len-1;i++)
		moji=moji[i+1];
	moji[len-1]=a;
	return ;
}
 
 
意味わかりますよね?右にローテートする関数はこんな風にしてみました。

void rotate_right(char moji[/url],int len){
	int i;	char a;
	a=moji[len-1];
	for(i=len-1;i>0;i--)
		moji=moji[i-1];
	moji[0]=a;
	return ;
}
 
 
先ほどと逆を行ってるだけですね。

文字列の入力をちょっと工夫して、3文字以上の文字列でなかったらもう一度入力をうがなすようにしてみました。
以下メイン関数の一部です。

while(1){
		printf("文字列を入力してください:"); 
		scanf("%99s",&moji);
		len=strlen(moji);
		if(len<3){
			printf("3文字以上の文字列を入力してください。\n");
			continue;
		}
		else
			break;
	}


scanf文の中の99は最大で99文字しか入らないようにするためです。
100しか配列要素を用意していないので、バッファオーバーしないように書きました。
strlenは\0までの長さを求める関数です。\0は含めませんので、実質的な文字の長さです。

continueはループの最初に戻る、breakはループを抜けます。

#include <stdio.h> 
#include <string.h> 


void rotate_left(char moji[/url],int len){
	int i;	char a;
	a=moji[0];
	for(i=0;i<len-1;i++)
		moji=moji[i+1];
	moji[len-1]=a;
	return ;
}
void rotate_right(char moji[/url],int len){
	int i;	char a;
	a=moji[len-1];
	for(i=len-1;i>0;i--)
		moji=moji[i-1];
	moji[0]=a;
	return ;
}

int main(){ 
	char moji[100]={};
	int houkou,len;
	while(1){
		printf("文字列を入力してください:"); 
		scanf("%99s",&moji);
		len=strlen(moji);
		if(len<3){
			printf("3文字以上の文字列を入力してください。\n");
			continue;
		}
		else
			break;
	}
	while(1){
		printf("左右どちらにローテートしますか?(左:1,右:2): "); 
		scanf("%d",&houkou);
		if(houkou==1)
			rotate_left(moji,len);
		else if(houkou==2)
			rotate_right(moji,len);
		else{
			printf("エラー\n"); 
			break; 
		}
		printf("ローテート結果:%s\n",moji); 
	}
	return 0;
}
 
 
このサンプルを一度実行してみてください。
何度でもローテートできるようにしてあります。

Re:関数の作り方

Posted: 2007年4月16日(月) 19:04
by
おそくなりました☆

なるほどぉーー!!
確かに、3文字以上ないとローテートできないので、そっちの方がいいかもしれません!!
とゆーか、そっちの方がいいですねぇ!!

どぉーも、詳しく書いていただいてありがとぉーございました。

実は、私・・・・ちょっと応用的に、1文字だけじゃなくて、ローテートする文字数を聞いてその文字数分だけ、ローテートする事も考えてしまいました!!!!
ちょっと、最近プログラミングがんばってるんですよ!!(笑)

Re:関数の作り方

Posted: 2007年4月16日(月) 19:36
by 管理人
失礼ですが、★さんは、以前の☆さんと同じ方ですか?
以前に☆さんがいらっしゃったので^^;http://www.play21.jp/board/ranking.cgi?id=dixq

>実は、私・・・・ちょっと応用的に、1文字だけじゃなくて、ローテートする文字数を聞いてその文字数分だけ、ローテートする事も考えてしまいました!!!!

お~いいですね~。
プログラムはそうやって課題だけじゃなく、課題から「こう工夫するとこう応用できるのでは?」と考えながら色々試してみるのはホントいいことです^^

最初はどんなに汚くてもいいからただ動けばいい!って感じで作って行っていいですけど、
余裕が出てきたらどうやったらスマートに、無駄な処理なくかけるだろか?
って事にも気を配ってみてください☆

関数化をうまく汎用化できるようになれば処理を書くのがとても楽になりますよ^^

Re:関数の作り方

Posted: 2007年4月19日(木) 23:13
by
はい。同じ方です(笑)
以前使ってた名前忘れてしまって・・・★にしようと思ったら、☆だったってゆー。。(笑)

スマートですねぇ!!わかりました☆
これからは、学校の課題をひとまず片付けて、そのプログラムをいろいろいじくる事にも時間をかかれればなぁー♪と思います。

また、ぃろぃろ教えてくださいねぇー!!!!!

Re:関数の作り方

Posted: 2007年4月22日(日) 15:25
by 管理人
遅くなりました・・(_ _|||)

同じ方でしたか^^
おかしいな~前は塗りつぶし無かったようなとw
どちらに統一されます?よければ2つにわかれているポイントひとまとめにしますが^^
(どうでもいい話かなw

これからも頑張ってくださいね~☆

Re:関数の作り方

Posted: 2007年4月23日(月) 23:10
by
本当ですかぁ??
それじゃ、『☆』に統一してもらえますかぁ???(笑)
よろしくぉねがいします。。。(笑)

はぁーぃ!!!!!頑張りますーー。

Re:関数の作り方

Posted: 2007年4月24日(火) 00:00
by 管理人
う~、忙しくて掲示板に書き込みも出来ないしむつさんに作ってもらったスクリプトもアップできない(T_T
☆さんに統一しておきましたよ^^

修正しようと名前一覧を表示させてびっくりしましたけど、今までこんなにも沢山の人が利用しているんですね^^;
一覧スクロールするのにちょい時間かかりましたw

いつの間にか私のポイントが30万・・。
まぁ掲示板ランク上がったからって何か商品があるわけでもないんですけどね^^;

もしかしたら神になると記念品が・・・(ナイナイ

Re:関数の作り方

Posted: 2007年4月30日(月) 16:29
by
管理人さん大人気なんですよ♪♪
頑張ってこれからも私のような未熟者を助けてくださいねぇ。。お願いします☆