-1

これが私のコードの一部です:perfectTestintを介して配列を渡す方法を理解するのに問題があります。nが-1の場合、それが不足している数であると出力し、nが0の場合、それが完全数であると出力し、nが1の場合、それが豊富であると出力するというオプションがあります。数ですが、その中に配列を組み込む必要があります。ヒントが必要です。

//prototype
int perfectTest(int n);


//function
int perfectTest(int n)

{   bool perfect;
    int answer;
    int perfectSum = 0;
    perfect = false;

    for(int i=1; i<=n/2; i++)
    {
        if(n % i==0)
            perfectSum = i;
    }

    if(perfectSum == n)
        perfect = true;
        answer = perfectSum;
}




//main function

int main()
{
    char option;
    int  n, m;
    bool InService = true;
    char perfectTestingOption;
    int  perfectNum;
    bool perfect = true;
    int factor;


    while (InService == true)
    {
    cout << "\t\t\nWelcome! Choose an option below\n" << endl;
    cout << "A = Perfect number testing" << endl;
    cout << "B = Greatest common divisors and least common multiples" << endl;
    cout << "C = Factorization of natural numbers" << endl;
    cout << "Q = Quit the program\n" << endl;
    cout << "Enter your choice:" << endl;
    cin >> option;

    if (option == 'A' || 'a')
    {
        cout << "\t\t\nWhich option would you like?\n" << endl;
        cout << "1" << endl;
        cout << "2" << endl;
        cout << "3" << endl;
        cout << "4" << endl;
        cin >> perfectTestingOption;

        if (perfectTestingOption == '1')
        {
            cout << "Enter a positive integer to check if it is a perfect number." << endl;
            cin >> perfectNum;


        perfectTest(0);

        for( );
        if (n == -1)
        {
            cout << "That number is a deficient number" << endl;
        }

        else if (n == 0)
        {
            cout << "That number is a perfect number" << endl;
        }

        else if (n == 1)
        {
            cout << "That number is a abundant number" << endl;
        }

        else
        {
            cout << "Number is invalid" << endl;
        }
    }
4

1 に答える 1

0

配列は、メモリ内のベースアドレスからのオフセットによってアドレス指定されたデータのブロックにすぎません。ベース アドレス、要素の数、および要素のデータ型があれば、データを配列として扱うのに十分な情報があります。

配列を直接宣言できます-

int array[SIZE];

ここSIZEで、配列内の要素の数を示す整数です。この構文は、メイン メモリのサイズに比べてサイズに厳しい制約があるスタックに配列を割り当てるため、この逐語的な宣言は の大きな値の場合は悪い考えであることに注意してください。SIZE

代わりに、ポインターを割り当ててから、ヒープ領域を指すように初期化することができます -

int * array = new int[SIZE];

これにより、int のブロックに動的にメモリが割り当てられ、最初の「スロット」のアドレスが得られます。次のビットのブラケット構文は「オフセット」演算子として機能するため、これで十分であることがわかります。

個々の要素にアクセスするには、配列変数が宣言されたら:

int foo = array[idx]

idxint はどこにありますか。たとえば、idx1 に等しい場合 (リテラル 1 で置き換えるか、整数 1 に評価される変数または式で置き換える)、最初の要素の「右側」にあるスロット 1 スロットで整数を取得します。C(++) の配列の最初の要素のインデックスは 0 であることを思い出してください。これは、プログラマーが頭がおかしくなり、0 でインデックスを付けるのが好きだからです (また、ブラケット演算子が最初の要素のアドレスからのオフセットを指定するため)。

配列を関数に渡すにはどうすればよいですか? 各配列要素のデータ型と配列の長さがわかっている場合は、メモリアドレスを渡すだけで十分です。配列の長さを渡して確認することは非常に重要です。そうしないと、配列の境界を超えてプログラム内の他の値を上書きし始めるという恐ろしい結果につながる可能性があります。(より高度なデータ構造やその他のプログラミング言語では、境界チェックを自動的に行うことができます。ベア配列を使用しているため、境界チェックは私たちの責任です。)

ここで、元の問題に戻りましょう。入ってきたものに対して何かクールなことをする関数int f(int i)があるとします。この関数を「配列化」して、配列を受け取り、配列も返すようにします。

この場合の出力配列は入力配列と同じサイズであるため、配列の長さが正確にわかっているという事実を利用します。そのため、配列化された関数からその数値を渡すことについても心配する必要はありませんが、それを行うための簡単なテクニックがあります。

次のようにします。

int * __f(int * __i, int ilen)
{
    int * output = new int[ilen];
    for(int offset = 0; offset < ilen; offset++)
    {
        output[offset] = f(__i[offset]);
    }
    return output;
}

ilenこの関数は、 intを含む整数配列を取り、fそれぞれに適用した結果を出力します。この関数は、後で必要になる新しいメモリを割り当てることに注意してくださいdelete[]。簡単な変更を行うだけで、この関数を変更して配列をその場で変更できます。

行ごとに分解してみましょう。

int * __f(int * __i, int ilen)

関数シグネチャ。これは、アドレスをilenint の配列に取り、アドレスを別のそのような配列に返していることを示しています。

    int * output = new int[ilen];

出力用に新しいメモリを割り当てます。メモリ ブロックの使用が終了した場合は、終了時に行うfoo必要delete[] fooがあります。そうしないと、メモリは割り当てられたままになり、プログラムが終了するまでスペースを占有します。詳細を知りたい場合は、動的メモリ割り当てを読んでください。

    for(int offset = 0; offset < ilen; offset++)
    {
        output[offset] = f(__i[offset]);
    }

配列の各要素 (offsetカウンターでインデックス付け) に対してf、入力配列の対応する要素を実行し、配列__iの正しい要素をoutput結果に設定します。

    return output;

最後に、構築した配列を返します。技術的には a を返しますがint *、これは単に「1 つ以上の int のメモリ アドレス」を表現するための凝った言い方です。

この記事全体を通して、ポインター構文 ( ) を使用してきました*。多くの人にとって、ポインターの深い理解にはある程度の時間がかかります (私も含めて、私は数年間ポインターを「取得」していませんでした!)。簡単に言えば、次のとおりです。

  • 形式の変数にはint * foo、メモリ アドレスが含まれます。このメモリ アドレスは、意味的には、 を指すように指定されていintます。ただし、実際には、アドレスは単なるアドレスです。(メモリ アドレスは、メモリ内の特定のセルに対応する番号です。メモリ セルは、連続したアドレスとして扱うことができます。つまり、セル 100 はセル 101 に「隣接」しています。メモリに番号を付ける場合、 1 バイトのセル サイズを使用します。4 バイトintints の配列など、より大きな構造のアドレスは、最初の要素のアドレスです。)
  • を宣言するとfoo、それfoo自体が格納されているアドレスを参照します。ポイントする値が必要な場合はfoo、 と言い*fooます。この*コンテキストでの は逆参照演算子です。メモリ アドレスを受け取り、そこにあるものを返します。
  • 変数のアドレスが必要な場合はbar、 と言い&barます。この&コンテキストでの はアドレス取得演算子です。変数を取り、それがどこにあるかを教えてくれます。
  • ポインタを加算および減算できます:foo + 3は完全に有効なメモリ アドレスです。ただし、注意してください!加算および減算する各 "1" は、1 つのメモリ セルではなく、配列によってカプセル化された型のサイズに等しいメモリ セルの数です。私たちの場合、intほとんどの最新のプラットフォームでは は 4 バイトであるため、3 ではなくfoo + 33*4 = 12 のメモリ セルが のアドレスに追加されますfoo
  • ポインターと配列は大まかに交換可能です。特に、foo[n]n の任意の値に対して、期待どおりに機能します。
于 2012-12-18T04:53:09.510 に答える