-1

I'm having some difficulty in generating a random int* and store it into a list<int*>.

I have tried the following:

std::list<int*> generateInt(){
   std::list<int*> randomInt;

   int i = 0;

   // initialize random seed
   srand (time(NULL));

   while (i < 5){
      int* random = (int*)std::rand();
      std::cout << "Random int generated: " << random << std::endl;

      randomInt.push_back(random);
      i++;
   }

   return randomInt;
}

But I get compiler issue as following

error: cast to pointer from integer of different size [-Werror=int-to-pointer-cast]
       int* random = (int*)std::rand();
                                     ^

I'm not sure if i'm missing something important here? Any help or advice would be very appreciated. Thanks!

ferics
  • 77
  • 7

3 Answers3

2

The easiest way I can think of is:

std::vector<int> generateInt(){
   std::vector<int> randomInt;

   int i = 0;

   // initialize random seed
   // srand (time(NULL)); Let that be the first line in main()

   while (i < 5){
      int random = std::rand();
      std::cout << "Random int generated: " << random << std::endl;

      randomInt.push_back(random);
      i++;
   }

   return randomInt;
}

There's no need to introduce pointers or std::list at all.

πάντα ῥεῖ
  • 1
  • 13
  • 116
  • 190
0

Don't use pointers in your task, list use a self allocator:) if you need poiner use unique ore shared ptr if you need int prt with random value use

int* p = new int{rand()};

Use mt to generate a random value (http://www.cplusplus.com/reference/random/mt19937/) ande see coments in code block

#include <iostream>
#include <list>
#include <random>
#include <functional>


namespace test {
    std::list<int*> __attribute__((noinline))
    foo() noexcept{
        // Mersenne Twister generator with random device seed
        // good way and not use time spec
        std::mt19937_64 generator(std::random_device{}());
        // for int gen
        // this a seporator for generated value
        std::uniform_int_distribution<> uid(0, 256);
        // make functional object to use
        auto rand_gen{std::bind(uid, generator)};

        std::list<int*> lst;
        int i{0};
        for (auto i{0}; i < 5; ++i) {
            // emplase is right way now
            try {
                lst.emplace_back(new int{rand_gen()});
            } catch (std::bad_alloc& ba) {
                std::cerr << "bad_alloc caught: " << ba.what() << std::endl;
            }
        }
        return std::move(lst);
    }
}

int main() {
    std::list<int*> lst{test::foo()};
    for(const auto& val : lst) {
        std::cout << *val << std::endl;
        delete val;
    }
    return 0;
}

ore use /dev/urandom if you linux like user :)

0

A note: You would not do this in real life. You would use a container of int, possibly std::list but more likely std::vector, not pointers to int. This is probably an assignment to make the learner struggle for a while with pointers.

So let's deal in pointers and do this the hard way.

int* random = (int*)std::rand();

means Get me a random number and store the random number as a memory address. What does this address point to? Anybody's guess. It's random. That makes it a bad idea.

A pointer must point to a valid object of the same type (or has an is-a relationship with the pointer's type) or it should be pointed at a "safe" parking location like nullptr until it can be pointed at a valid object. There are exceptions to this, but you'll learn those later.

Given

I'm implementing an assignment question that requires to store a list of pointers to random integers.

std::list<int*> randomInt;  

Is probably correct. But... You still need an int to point at, so

  1. Get a valid integer,
  2. store the random number as an integer in that integer, and
  3. store a pointer to that integer in the list.

So how do you get a valid integer? Obviously you need more than one so,

int number; // easy, but not enough numbers. 

is out. All of randomInt would point at the same place and only the last value generated would be stored.

If you don't know how many numbers you're getting you need dynamic storage and should use new

int * random = new int; // get an int from dynamic memory
*random = std::rand(); // generate random number and assign to int pointed at by random

(or a smart pointer if they are available to you). Remember everything you new you will have to delete

for (int * p:randomInt) // for all pointers in randomInt
{
    delete p; // free the memory (and other stuff you'll cover later)
}

after you are finished using it to avoid memory leaks. This is disturbingly error-prone, it is sickeningly easy to have a path that misses the delete or deletes while the allocation is still needed, so avoid this in real life. Use Automatic allocation, containers and smart pointers. If you can't, embrace the power of RAII.

Where possible avoid having to mess around with managing dynamic memory, smart pointer managed or otherwise, because dynamic memory always has a cost.

In this case it looks like a maximum of five, so you can make an array

int numbers[5];

(but NOT a local variable

std::list<int*> generateInt(){
    int numbers[5]; // do not use!!! FATAL!!!

as it would go out of scope and vanish at the end of the function, leaving the program with a list full of pointers to invalid objects) and point at the elements of the array. For a simple program, you could get away with a static local variable

std::list<int*> generateInt(){
    static int numbers[5];

or a global variable

int numbers[5];
std::list<int*> generateInt(){

but what if the function is called more than once? The second call would destroy the results of the first call. This may be tolerable, but the responsibility for making this call and guaranteeing the program works as expected falls on the programmer.

My suspicion is the Asker is intended to use new. Check with whomever assigned the problem to see what other options they will accept.

user4581301
  • 33,082
  • 7
  • 33
  • 54
  • thank you so much for the thorough explanation. I will check with the assignment specs and marker asap. as for now, I have some other issues such as 0xfffffffff and things like that when I try to allocate the pointers to those ints I generated. Any advice? if I allocate by say some big amount less, then it'd back down less than fffffff but if I then allocate more big int, it'd go back to that – ferics Aug 31 '19 at 16:40
  • Typically (but not always. [See the first table here](https://en.cppreference.com/w/cpp/language/types)) `int` can only hold a 32 bit signed number for a maximum of about 2 billion (or 0x7fffffff). If you need a larger number, you need too use a different type. an `unsigned int` will (probably) store 0xffffffff, but no more. `long` or `long long` may store 64 bits. In addition, the range of numbers provided by `std::rand` may be as small as 0 to 32767. For larger numbers use [`std::uniform_int_distribution`](https://en.cppreference.com/w/cpp/numeric/random/uniform_int_distribution) – user4581301 Aug 31 '19 at 16:48
  • Side note: [Some interesting viewing](https://channel9.msdn.com/Events/GoingNative/2013/rand-Considered-Harmful) on `rand` and its modern replacements. Quite funny, too. – user4581301 Aug 31 '19 at 16:56