
講義でこのような問題が出ました
/*
関数hanten()を作り、プログラムを完成させよ。
ただし、関数hanten()の中で、配列を宣言してはならない。
(当然引数である配列は除く。)
main関数内部を変更してはならない。
例えば、入力が1, 8, 2, 6, 7だとすると、
出力は、
7 6 2 8 1
となる。
*/
自分なりに色々やってみたのですが、できませんでした
正直な話答えをそのまま聞きたいのですが
それだけでは習得したといえないので
どういう考えでやればいいのかご指摘いただくとうれしいです。
入れ替えということは変数を別に用意してあげてそこに読み込んでから
順番に入れ替えるということだと思うのですが・・・
参考書(やさしいC,第3版)などを色々見たのですが
なんかポインタを使うような・・・気はするのですが
配列はポインタでもあるのはわかっているのですが・・・
ネットで色々探したのですが、わかったのが*((data)...etcみたいなことができるということです。
ちなみに自分で色々やった結果はこれです。
コンパイルしたら入れ替えはされてない
#include <stdio.h>
#define MAX 5
void hanten(int [MAX],int);
int
main(void)
{
intdata[MAX], i;
for (i = 0; i < MAX; ++i) {
scanf("%d", &data[i]);
}
hanten(data, MAX);
for (i = 0; i < MAX; ++i) {
printf("%d ", data[i]);
}
printf("\n");
return 0;
}
void
hanten(int data[MAX],int max)
{
int i,tmp,*data2;
for(i=0;i<max;i++){
tmp = *((data)+(i));
*((data)+(i)) = *((data2)+(i));
*((data2)+(i)) = tmp;
}
}
No.4ベストアンサー
- 回答日時:
>入力が1, 8, 2, 6, 7
ということであれば、
1)先頭と最後とを入れ替える(結果:7,8,2,6,1)
2)先頭から2番目と最後から2番目とを入れ替える(結果:7,6,2,8,1)
要素数が5個の場合は、ここまで行なうと要求を満たすプログラムができあがります。
一般に、
・いちばん最初といちばん最後とを入れ替える
・先頭から2番目と最後から2番目とを入れ替える
・先頭から3番目と最後から3番目とを入れ替える
・先頭から4番目と最後から4番目とを入れ替える
...
・先頭からn番目と最後からn番目とを入れ替える
この操作を繰り返すと逆順にできますが、nをいくつにすればよいかは
もともとの要素数によって異なります。考えてみてください。
No.3
- 回答日時:
#1さんの回答で必要十分で、足すところがないのですが、人のコードを見るのもいい勉強になると思いますので、参考までにいろいろと余計なことをしつつ書いてみます。
ここでは酔狂のために無駄にポインタを使っていますが、最小限題意を満たすように作るなら、やってきた配列以外の新たな配列を作らなくてもいいですし、ポインタ変数を新たに作る必要もありません。ポインタ変数を使わない場合、hanten関数の中でswap関数に相当する処理をやります。C99が通らないコンパイラだとコンパイルできませんが、こんな感じで。
(gccを使っている場合、-std=c99と書くとコンパイルできるかもしれません)
#include <string.h>
#include <stdio.h>
#define MAX 5
#define STRING_MAX 1024
#define STRING_MAX_STR "1024"
void static inline
swap(void *x0, void *x1, int size) {
unsigned char tmp[size];
memmove(tmp, x0, size);
memmove(x0, x1, size);
memmove(x1, tmp, size);
}
void
hanten(void *data, int size, int nmemb) {
for (int i = 0; i < nmemb / 2; i++) {
swap(data + i * size, data + (nmemb - i - 1) * size, size);
}
}
int
main(void)
{
int data[MAX], i;
char buf[STRING_MAX];
printf("Please input %d numbers:\n", MAX);
for (i = 0; i < MAX; ++i) {
scanf("%d", &data[i]);
}
hanten(data, sizeof(int), MAX);
for (i = 0; i < MAX; ++i) {
printf("%d ", data[i]);
}
printf("\n");
printf("Please type string:\n");
scanf("%" STRING_MAX_STR "s", buf);
hanten(buf, sizeof(char), strlen(buf));
printf("%s\n", buf);
return 0;
}
とまぁ、hanten関数とswap関数を型によらないように作ってみました。int型だけを受けうる場合、memmoveやらsizeでデータのサイズを渡しているところやらをやらないでいいことがあるので、そこのところをそんな風に書くと最低限題意を満たすものになるかと。
No.2
- 回答日時:
講義で何を期待してこの問題を出したか、によります。
○ 一番単純な方法は次のものになりますよね?
・新規配列data_newを用意
・data_newに反転したdataを入れる
data_new[0] = data[max-1] ;
data_new[1] = data[max-2] ;
..
data_new[i] = data[max - 1 -i] ;
...
data_new[max-1] = data[0] ; // 0 == (max-1)-(max-1)
・dataにdata_newをコピー
data[i] = data_new[i] ;
この方法を使うには、「配列」data_newが必要です。
配列を宣言するには、大きさを指定する必要があります。
正しく動作させるには、引数max以上である必要があります。
そのため、「配列で宣言」するにはint data_new[500];等と適当に大きな値を使う必要があります。
# 正確には「ありました」。新しい規格に準拠したC言語では int data_new[max];と変数を使うこともできます。
# ただし、新規格に準拠していないコンパイラもまだまだ残っています。
問題の意図が「maxの値に応じた領域を確保する方法を学ぶ」ものであるなら、上記のような「適当に大きな配列を宣言」しないで
・malloc/callocで領域を確保、ポインタに記憶させる
・return前にfreeで解放
とします。
○(malloc等で領域を確保するものも含め)同じ大きさの配列を用意することはしない、というのが「配列を宣言しない」の意味なら、「別のやりかたを考えろ」というのが、問題の意図となります。
上のやりかたを良く見ると、
data_new[0] = data[max-1] ;
data_new[max-1] = data[0]
等と、2つ1組で入れ替わっていることがわかります。
つまり、data_newを用意しなくても、「data中の2つを入れかえる」を繰り返すだけで同等のことができる、というのがわかります。
「同じ組を2回入れかえたら、元にもどってしまう」ということに注意しましょう。
○なお、質問にあるhantenですが
・ポインタで宣言しても[]が使えます。次のように書いても、まったく一緒です。
tmp = data[i];
data[i] = data2[i];
data2[i] = tmp; // =元のdata[i]
単に data[i]とdata2[i]を入れ替えただけで、順番は何も変わっていないことがわかります。
・ポインタは宣言しただけでは、どこを指しているかわかりません。
そのまま *data2 などとすると、その「どこかわからないアドレス」にある「なんだかわからない値」が使われます。
別の変数の値を参照しているかもしれないし、OSの領域を参照しているかもしれません。
その結果、なにごともなく動作しているように見えることもあれば、領域違反でエラー終了することもあります。
ややこしいところですが、ポインタと配列はきちんと整理してしっかり勉強しましょう。
お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!
関連するカテゴリからQ&Aを探す
おすすめ情報
デイリーランキングこのカテゴリの人気デイリーQ&Aランキング
-
関数から配列を返すには?
-
配列の要素数に変数を入れたい...
-
C言語において、 配列要素をひ...
-
C言語 ファイルの指定された行...
-
C言語についてです 5人のテスト...
-
fclose()でセグメンテーション違反
-
c言語
-
define で 配列
-
ポインタを使って構造体の配列...
-
char gyou[1024];でcharの表現...
-
配列のアドレス部
-
コンボボックスでデフォルト値...
-
構造体を引数とする関数について
-
ファイルのデータを構造体に代...
-
MFCのCArrayを使った二次元配列
-
bmpやImageの配列を関数の引数...
-
C言語を使って、ファイルの読み...
-
C#で配列が空かを判定するには?
-
C#で構造体の配列を持った構造...
-
C言語の配列のコピーについて
マンスリーランキングこのカテゴリの人気マンスリーQ&Aランキング
-
関数から配列を返すには?
-
配列の要素数に変数を入れたい...
-
C言語において、 配列要素をひ...
-
c言語
-
C言語 ファイルの指定された行...
-
define で 配列
-
C#で構造体の配列を持った構造...
-
C言語の課題が出たのですが自力...
-
char型配列をint型に代入するには
-
C#で配列が空かを判定するには?
-
MFCのCArrayを使った二次元配列
-
コンボボックスでデフォルト値...
-
MFC - ダイアログボックスのPic...
-
c言語 構造体
-
2番目の最大値を求める
-
C言語から質問です。
-
Cのエラー
-
プログラミングに関する問題が...
-
C言語の2次元配列 容量が大き...
-
Visual C++を 用いたテキストフ...
おすすめ情報