大学の課題が分かりません。

フォーラム(掲示板)ルール
フォーラム(掲示板)ルールはこちら  ※コードを貼り付ける場合は [code][/code] で囲って下さい。詳しくはこちら

トピックに返信する


答えを正確にご入力ください。答えられるかどうかでスパムボットか否かを判定します。

BBCode: ON
[img]: ON
[flash]: OFF
[url]: ON
スマイリー: OFF

トピックのレビュー
   

展開ビュー トピックのレビュー: 大学の課題が分かりません。

Re: 大学の課題が分かりません。

#6

by かずま » 6年前

提出期限が過ぎてからの指摘で申し訳ありません。

そのプログラムだと、101個のデータが入力できてしまうか、
あるいは 101個目のデータで異常終了する可能性があります。

試しに、int a[4]; としてみてください。データが 5個入力できませんか?
a[0], a[1], a[2], a[3] の 4つの場所しかないのに、
参照してはいけない a[4] が使われているからです。

readArray の中の if(n>size) break; を if (n >= size) break; とするか、
あるいは、readArrayを次のように書くとよいでしょう。

コード:

int readArray(int *a, int size)
{
	int n;
	for (n = 0; n < size; n++) {
		printf("data = ");
		if (scanf("%d", &a[n]) != 1) break;
	}
	return n;
}
printf は一つで済みます。
scanf の返却値を EOF ではなく、1 と比較しているのは、
EOF だと、まちがって数字以外を入れた時とんでもないことになるからです。
試してみてください。

次に、mysort ですが、変数 b はなんのためにあるのでしょうか?
値が 0 のまま変化しません。次のように書いてもいいでしょう。

コード:

void mysort(int *d, int n)  // n はデータの個数
{
	n--;  // n は最後の要素の番号
	while (n > 0) {
		int last = 0;
		for (int i = 0; i < n; i++)
			if (d[i] > d[i + 1]) {
				swap(d[i], d[i + 1])
				last = i;
			}
		n = last;
	}
}

Re: 大学の課題が分かりません。

#5

by frontriver » 6年前

返信ありがとうございます。

コード:

/*mysort.c*/
#include<stdio.h>
int readArray(int*,int);
void printArray(int*,int);
void mysort(int *,int);
#define swap(x,y) {int t; t=(x); (x)=(y); (y)=t;}
int main()
{
  int a[100],n;
  n = readArray(a, 100);
  printArray(a, n);
  mysort(a, n);
  printArray(a, n);
  return 0;
}
int readArray(int *a,int size)
{
  int n;
  /*配列aにデータを読む*/
  n = 0; 
  printf("data = ");
  while(scanf("%d",&a[n]) != EOF){ 
    n++;
    if(n>size) break;
    printf("data = ");
  }
  return n;
}

void mysort(int d[], int n)
{
  int i,last,b,t;
  b=0;
  t=n-1;
  while(t>b){
    last=b;
    for(i=b;i<t;i++)
      if(d[i]>d[i+1]){
	swap(d[i],d[i+1]);
	last = i;
      }
    t = last;
  }
}

コード:

コンパイル結果
[peodbm02-( ~/C )-519]gcc mysort.c -o mysort
[peodbm02-( ~/C )-520]./mysort
data = 23
data = 2
data = 3
data = 4
data = 
a = 23
a = 2
a = 3
a = 4

a = 2
a = 3
a = 4
a = 23
かずまさんのアドバイスをヒントに色々試行錯誤してみたらできました。
ありがとうございました。
加えて、フォーラム掲示板ルールにしたがっておらず、申し訳ありませんでした。
以後、質問をする際は気をつけます。

Re: 大学の課題が分かりません。

#4

by かずま » 6年前

frontriver さんが書きました:
6年前
readArrayをreturn 0で返したのが間違いだと思うのですが、0で返すことで、正しくプログラムを終了させたという意味合いで使っていました。0で返すと0で入力されるのは当たり前ですよね。

readArrayはint型なので、returnを使わなければいけないと思い、何で返せばいいか分からず、0を使いました。
readArray関数から return しても、プログラムは終了しません。
main関数から return したら、プログラムは終了します。
そして、main関数は、0 を返すことが正常終了と規定されています。

一般の関数は、引数の意味や、返却値の意味を自由に決めていいのです。
そして、それを決めないと関数は書けません。

それから、変数を宣言するときは、その変数がどんな意味を持つのかも
プログラマが決めないといけません。

printArray の引数 size は、配列に入っているデータの個数です。
size には、main の変数 n が渡されます。
その n には readArray の返却値が代入されています。
ということは、main の n は、入力データの個数でなければなりません。

readArray が、読み込んだデータの個数を返すのは当然のことです。

readArray がデータの個数以外にエラーかどうかを返したければ、
書き方に工夫が必要です。

コード:

返却値でエラーを返し、引数 p で個数を返すなら、
int readArray(int *a, int size, int *p)
{
    ....
    *p = n;    // データの個数
	return 0;  // エラーなし
}

返却値で個数を返し、引数 e で エラーを返すなら、
int readArray(int *a, int size, int *e)
{
	....
    *e = 0;    // エラーなし
	return n;  // データの個数
}

返却値で個数を返すが、エラーの場合は負の値を返すなら
int readArray(int *a, int size)
{
	....
    if (エラー) return -1;  // エラー
	return n;  // データの個数
}
もちろん mainからは readArray の仕様にあった呼び出しが必要です。
frontriver さんが書きました:
6年前
かずさんに日本語で説明されて分かったのですが、returnで返すものはnと言うことでしょうか?
そのように変更してどういう結果になるか試していないのですか?

最初の質問のプログラムはコードタグを使っていないのでおかしな表示に
なっています。フォーラム(掲示板)ルールに従ってください。
件名も「大学の課題が分かりません。」は不適切です。
「関数とポインタを使うプログラム」や「配列への読み込みと表示」など
内容を他の質問と区別できるものにしましょう。

Re: 大学の課題が分かりません。

#3

by frontriver » 6年前

返信ありがとうございます。
readArrayをreturn 0で返したのが間違いだと思うのですが、0で返すことで、正しくプログラムを終了させたという意味合いで使っていました。0で返すと0で入力されるのは当たり前ですよね。

readArrayはint型なので、returnを使わなければいけないと思い、何で返せばいいか分からず、0を使いました。

かずさんに日本語で説明されて分かったのですが、returnで返すものはnと言うことでしょうか?

Re: 大学の課題が分かりません。

#2

by かずま » 6年前

5日も考えなくても、変数の変化をトレースすれば
5分でどこが誤っているかわかるのではありませんか?

コード:

main:
  a : [ ][ ][ ]...[ ]
  n : [ ]
readArray:
  a : main の a[0] への矢印
  size : 100
  n : 0
  "data = "を表示
  scanf で main の a[0] に 11 を書き込む
  n : 1
  n > size ではないので break しない
  "data = "を表示
  scanf で main の a[1] に 2 を書き込む
  n : 2
  n > size ではないので break しない
  "data = "を表示
  scanf で main の a[2] に 3 を書き込む
  n : 3
  n > size ではないので break しない
  "data = "を表示
  Ctrl-D を入力したので、
  scanf は EOF を返す
  whie ループを抜ける
  return 0; なので readArray は 0 を返して main に戻る
main:
  readArray が返した 0 を n に代入する。 
  n : 0
printArray:
  a : main の a[0] への矢印
  n : 0
  i : 0
  i < n ではないので、for ループを抜ける
  main に戻る
main:
mysort:
どこで勘違いしたのかを教えてください。

大学の課題が分かりません。

#1

by frontriver » 6年前

大学の課題で、関数とポインタを使い次の問題をプログラミングする問題が出ました。

キーボードから入力した整数を指定した配列に読み込む関数 int readArray(int *a, int size) と指定した整数配列の先頭からn個の要素を画面に表示する関数 void printArray(int *a, int n) を作りなさい。ここでsizeは配列aの大きさを示しており、readArray(a, size) はsizeの値を超えて整数を読み込まないようにしなさい。

そして自分が作った答えがこちらです。

/*mysort.c*/
#include<stdio.h>
int readArray(int*,int);
void printArray(int*,int);
void mysort(int *,int);
#define swap(x,y) {int t; t=(x); (x)=(y); (y)=t;}
int main()
{
int a[100],n;
n = readArray(a, 100);
printArray(a, n);
mysort(a, n);
printArray(a, n);
return 0;
}
int readArray(int *a,int size)
{
int n;
/*配列aにデータを読む*/
n = 0;
printf("data = ");
while(scanf("%d",&a[n]) != EOF){
n++;
if(n>size) break;
printf("data = ");
}
return 0;
}

void mysort(int d[], int n)
{
int i,last,b,t;
b=0;
t=n-1;
while(t>b){
last=b;
for(i=b;i<t;i++)
if(d>d[i+1]){
swap(d,d[i+1]);
last = i;
}
t = last;
}
}


void printArray(int *a,int n)
{
/*配列a要素を表示する*/
int i;
for(i=0;i<n;i++) printf("a = %d\n",a);
}

コンパイル結果がこちらです。

[@peodbm02-( ~/C )-510]gcc mysort.c -o mysort
[@peodbm02-( ~/C )-511]./mysort
data = 11
data = 2
data = 3
data = [@peodbm02-( ~/C )-512]

答えすら出ずにどこが誤っているのかもわからない状態です。
かれこれ5日は考えていますが、期限が今週の木曜日23:59までなのでどうにかならないかと、この掲示板に投稿させていただきました。
ご教授の程、よろしくお願いします。

ページトップ