Can someone give me some tips on using arrays to print out abundant, perfect, and deficient numbers in C++? [closed]

StackOverflow https://stackoverflow.com/questions/13925691

  •  10-12-2021
  •  | 
  •  

Question

Here is some of my code: I am having trouble figuring out how to pass an array through the perfectTest int. I have the options that if n is -1 than it prints out that it is a deficient number, if n is 0 than it prints out that it is a perfect number, and if n is 1 than it prints out that it is a abundant number but I need to incorporate arrays within that. I need some tips.

//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;
        }
    }
Was it helpful?

Solution

An array is nothing more than a block of data addressed by offset from some base address in memory. If you have the base address, the number of elements, and the data type of the elements, you have sufficient information to treat the data as an array.

You can declare arrays directly -

int array[SIZE];

where SIZE is some integer denoting the number of elements in the array. Observe that declaring this verbatim is a bad idea for large values of SIZE, as this syntax allocates the array on the stack, which has severe constraints on size relative to the size of main memory.

Instead, you can allocate pointers and then initialize them to point to some heap space -

int * array = new int[SIZE];

This allocates some memory for a block of ints dynamically and gives you the address of the first 'slot'. It turns out that that is enough, as the bracket syntax in the next bit functions as an 'offset' operator.

To access individual elements, once the array variable is declared:

int foo = array[idx]

where idx is some int. For instance, if idx were equal to 1 (either replacing it with a literal 1, or with a variable or expression evaluating to integer 1), we'd get the integer in the slot 1 slot to the "right" of the first element. Recall that the first element in an array in C(++) has index 0, because programmers are crazy and like to index things by 0 (and because the bracket operator designates an offset from the address of the first element).

How do we pass arrays to functions? It suffices to pass their memory addresses, if we know the data type of each array element, as well as the array length. It is very important that you pass and check the array length! Not doing so can lead to terrifying consequences as you overrun the boundaries of your array and start overwriting other values in your program. (More advanced data structures, and other programming languages, can do bounds checking automatically. Since we're using bare arrays, bounds checking is our responsibility.)

Let's turn back to the original problem now. Suppose we have a function int f(int i) that does something cool to whatever comes in. We want to 'arrayify' this function so that it takes arrays and returns arrays as well.

We're going to take advantage of the fact that we know exactly how long our array is, since the output array in our case is the same size as the input array. So we don't need to worry about passing that number out of the arrayified function as well, though there are simple techniques to do that.

We do something like this:

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;
}

This function takes an integer array containing ilen ints, and outputs the result of applying f to each one. Notice that this function allocates new memory, which you'll have to delete[] later. With some simple modification, you can alter this function to modify the array in-place.

Let's break it down line-by-line:

int * __f(int * __i, int ilen)

The function signature. This tells me I'm taking the address to an array of ilen ints, and returning an address to another such array.

    int * output = new int[ilen];

Allocating new memory for our output. If you're finished with a block of memory foo, you should delete[] foo when you're done; otherwise the memory stays allocated and takes up space until your program terminates. Read up on dynamic memory allocation if you want to learn more.

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

For each element in our array (indexed by the offset counter), we perform f on the corresponding element of the input array __i, and set the correct element of the output array to the result.

    return output;

Finally, we return the array we constructed. Technically, we return a int *, but that's just a fancy way of saying "memory address of one or more ints".

I've been using pointer syntax (*) throughout this writeup. Deep understanding of pointers takes some time to develop for a lot of people (myself included; I didn't 'get' pointers for several years!). In brief, though:

  • A variable of the form int * foo contains a memory address. This memory address, semantically, is designated to point to an int. In reality, though, an address is just an address. (A memory address is a number that corresponds to a particular cell in memory. You can treat memory cells as contiguous address-wise; that is, cell 100 is "adjacent" to cell 101, from our perspective. When we number memory, we use a cell size of 1 byte. The address of a larger construct, like a 4-byte int or an array of ints, is the address of the first element.)
  • Once we've declared foo, then foo by itself refers to the address stored within. If we want the value to which foo points, we say *foo. The *, in this context, is the dereference operator: it takes a memory address and returns what lives there.
  • If we want the address of a variable bar, we say &bar. The & in this context is the address-of operator: it takes a variable and tells you where it lives.
  • You can add to and subtract from pointers: foo + 3 is a perfectly valid memory address. BE CAREFUL, THOUGH! Each "1" you add and subtract by is not one memory cell, but a number of memory cells equal to the size of the type encapsulated by the array. In our case, since int is 4 bytes on most modern platforms, foo + 3 adds 3*4 = 12 memory cells to the address of foo, not 3.
  • Pointers and arrays are loosely interchangeable. In particular, foo[n] works, for any value of n, just as you'd expect it would.
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top