ポインターと配列について長いこと考えてるんですが、なかなか解決されません。できたら誰か助けてもらえますか?どうかお願いします。
* 私の作成したプログラムで実行させたいことは次の通りです。*
1.最初に数字を9回入力します。
2.その入力した数字を出力して表示します。
*問題点*
1.エラーは実行エラーです。
2.ポインター渡しができてないと思われます。
3.入力後の出力に問題があります。
#include <iostream.h>
#include <stdlib.h>
void Display( void );
int Input( void );
void Arrange( int *passed );
const int buffer = 256;
// main function
int main ()
{
static int pass[1]={0};
int *address = &pass[0];
Display();
pass[1] = Input();
cout << "\t *The address in the main function " << &pass[1] << endl;
Arrange( address );
return 0;
}
////////////////////////////////////////////////////////////////
void Display( void )
{
cout << "\t ******************************" << endl;
cout << "\t Please enter numbers 9 times." << endl;
cout << "\t ******************************" << endl;
return;
}
///////////////////////////////////////////////////////
int Input( void )
{
static int num[9]={0,0,0,0,0,0,0,0,0};
int *point;
point = num; // Insert the head address of num
for ( int i = 0 ; i < 9 ; ){
cout << "\t";
if ( cin >> num[i] ){
i++;
system("cls");
cout << "\t Please enter again." << endl;
}else{
cin.clear();
cin.ignore( buffer, '\n');
system("cls");
cout << "\t You did not entered number." << endl;
cout << "\t Please enter number." << endl;
}
}
return ( *point );
}
////////////////////////////////////////////////////////
void Arrange( int *passed )
{
cout << "\t Arrange start." << endl;
int results[10]={0,0,0,0,0,0,0,0,0,0};
cout << "\t *The Head address is " << &passed << endl;
for( int i = 0 ; i < 9 ; i++ ){
for ( int j = 10 ; i < 9 ; j-- ){
results[j] = passed[i];
}
}
cout << "\t Before values" << "\t\t" << "After values" << endl;
for ( int m = 0 ; m < 9 ; m++ ){
cout << "\t ________________________________" << endl;
cout << m+1 << "\t" << &passed[m] << "\t\t\t" << results[m] << endl;
}
}
???
一体、どんな値を入力時、どんな演算を行ない、どんな出力にしたいのかが
分かりませんでした。
アクセス違反と無限ループだけは分かりましたが。
1.数字を9回入力して、数字以外を入力した場合、cin.clearとcin.ignoreで数字を入力されていませんと表示されます。
2.その入力後全ての入力された数字を今度は反対からresultに入れて、その後resultとpassに入っている数字を出力させます。
追加
この言語はC++です。
コンパイラーはVisual C++です。
main()
{
...(省略)
pass[1] = Input();
}
main()
{
...(省略)
pass[1] = Input();
}
すいません。間違って送信しちゃいました。
あんまりソースおっかけてないので気づいた部分です。
main()
{
上記の部分がたぶん
pass[0] = Input();
// それか要素数を変更するか
static int pass[2]; // 1→2に変更
}
あと、memsetを使用すると初期化とか楽になりますよ。
要素数が100とかだったら入力疲れちゃうでしょうし
memset使ってどうやって初期化するか教えてもらえますか?^^;
それからたぶん渡しの作ったプログラムは、アドレスをきちんと、pass[0]に渡せてないと思うんですが?
実行エラーがまだ出てるんでたぶん。
すいませんm(_ _)m
おそらくInput()の中のstatic int num[9]の先頭アドレスを
Arrange(int *passed)に渡したいのだと思いますが
このコードではそれが正常に行われません
やるとしたら
int* Input( void )
{
static int num[9]={0,0,0,0,0,0,0,0,0};
/*略*/
return num;
}
みたいにしないと
まぁ個人的には内部の配列のポインタを持ち出すのはあんまり好きじゃないんで
void Input(int* pHoge)
っていう関数にして、main()で宣言した配列を放り込む方法を取りそうですが
とにかくどのポインタがどこを指し示しているかをきちんと把握してください
他にも修正が必要そうな部分がありそうな気はしますが、
取り合えずその辺を直して最後まで動くようにしてみましょう
memset(num, 0x00, sizeof(num))で手入力で0と入力している部分と
一緒の働きをします。
ちょっと簡単な方法っぽいのを
int Input();
main()
{
int num[10];
int* address = &num[0];
// 初期化
memset(num, 0x00, sizeof(num));
Display();
for(i = 0; i < 10; i++) {
// Input内で数字かチェックして数字だったら値を返す
// 文字列などの場合はInput内で再入力を促す
num[i] = Input();
}
// この時点で*address にはnum[0]の値が入っています。
Arrange( address );
}
void Arrange(int* address)
{
// 仮処理です
// num[10]にInputで入力された数字が格納されます
int num[10];
for(int i = 0; i < 10; i++) {
num[i] = add;
add++;
// ↓ここで値を逆にする処理をいれるといいと思います。
}
}
頭で考えたソースなのですが少しなら参考になると思います。
アクセス違反についてはhuruyaさんのおっしゃるとおり。
(ご自分で気付いて欲しかった…)
無限ループについては下記の部分。
> for( int i = 0 ; i < 9 ; i++ ){
> for ( int j = 10 ; i < 9 ; j-- ){
> results[j] = passed[i];
> }
> }
まず、i == 0 で、 i < 9 なので無限ループ。
初期化については、
> int num[10];
> int* address = &num[0];
> // 初期化
> memset(num, 0x00, sizeof(num));
これは、
int num[10] = {0};
int* address = &num[0];
と書いても同等です。
int num[10] = {0}; は、
int num[10] = {0,0,0,0,0,0,0,0,0,0}; と同等です。
# 2番目以降の初期化子を省略した場合、以降の要素は0で埋められる。
>> static int pass[1]={0};
>> pass[1] = Input();
配列の添え字は0から始まり、
int a[10];
と宣言したら
a[0],a[1],....,a[9] (全部で10個)
までしか使えないということを
理解しているかしら?
そもそも pass[1] って1個だけなら配列にする意味はどのへんにあるの?
int a;
int * pa = &a;
でいいじゃない。
でもって、
Arrange( pa );
にしか int * を使っていない。
Arrange( &a );
でいいじゃない。
!クイズ!
//////////////////////////////////////
char a[32] = "abcdefg";
char * p = a;
printf( "%s\n", p );
//////////////
char b[3][32] = { "ABC","DEF","GHI" };
char ** pp = b;
int c;
for( c = 0;c < 3; c ++ )
{
printf("%s\n", pp[c] );
}
正しいかい?
答えはあなたの VC++ にて。
色々と教えていただ大変きありがとうございます。
コンパイルも見事に通り、実行エラーも出なくなりました。
それから、ここで二つ質問があるんですが.....
すいませんm(_ _)m.
1.memsetを使って、初期化するのと、普通に初期化するのとではどちらの方 が有効ですか?
2.Input関数とmain関数と、Arrange関数のアドレスが違っているのに、何故
Arrange関数出力させた時で入力した数字と同じ数が出力されるんですか?
大変すいませんでした^^;。
私の言っているアドレスとはInput関数の戻り値のアドレスの事です。
>1.
どちらも有効です。厳密に言えば、memset()は関数呼び出しなので
「初期化」とは呼ばない人もいます。
初期化は、文字通り、宣言時に行います。
memsetは主にループ内で使用されることが多いです。
>Input関数の戻り値のアドレス
???
Input関数の戻り値の型はint型になっていますが…。
1. まず、あなたの知っている初期化の種類を列挙してください。
(memset もごく普通の初期化ですが)
それぞれの方法にそれぞれの有効な場面があります。
2. Input()関数は return( *point );です。
値を戻しています。
アドレスなど戻していません。
かぶってしまった。(^^;;
>> memsetは主にループ内で使用されることが多い
あと、0xFF/0xCC 初期化。
ZeroMemory(),FillMemory() なんてのもあります。
なるほど。
memsetの詳しい説明大変ありがとうございます。
ではアドレス渡しをしたい時はどのようにしたらよいですか?
C++ なら
void Input( int & a )
{
...
a = 10; // たとえば。
}
main(...)
{
int v;
Input( v ); // 呼び出しはこう書ける。そしてvに値が戻ってくる。
}
C 限定なら
void Input( int * a )
{
...
if( a ) // ポインタにNULL指定されていないことを確認する。作法。
{ // ( a != NULL ) の意味。!= NULL は冗長なので書かないが、
// 初心者は書いた方がよいかも。
*a = 10;
}
}
色々と説明ありがとうございましたw
まだまだ私は修行がたりませんね^^;
ツイート | ![]() |