I am trying to implement a function int choose_N(void) that generates and returns a random list of integers N (up to four integers). I am not sure if I am using rand( ) in the correct way, but this is what I have so far:
int choose_N(void)
{
int x, integer[4];
srand ((int) time(NULL));
for (x=0; x<4; x++)
integer[x]=rand();
return integer;
}
Would looping it like this work? Is time initialized in the correct way?
Two problems: most importantly, the array integer is local, and will go away when you return. If you want to return an array of things in C, you have to make the caller pass it in (see below). Secondly, srand() should only be called once per program, so it doesn't belong inside a function like this--it should be in main or some similar initialization function, otherwise multiple calls to this function will be correlated (at worst, they might even be identical). So here's a better approach:
void choose_n(int *out, int count) {
for (int i = 0; i < count; i += 1) {
out[i] = rand();
}
}
int main(int argc, char *argv[]) {
int results[4];
srand(time(NULL));
choose_n(results, 4);
}
Your loop is correct but your return statement will not work. The array integer is local to the function and will not be available outside. In either case, your function is supposed to return int and not an array.
And if you want to limit the random number to a range, you are better off using the mod operator such as rand() % range.
You could define your choose_N() like this
void choose_N(int integer[4])
{
int x;
srand ((int) time(NULL));
for (x=0; x<4; x++)
integer[x]=rand();
}
and use it likes this
int integer[4];
choose_N(integer);
You can't return a pointer to a local variable from a function.
See this post for the reason why? Can a local variable's memory be accessed outside its scope?
You have to allocate the array on heap.
Change it to:
int choose_N(void)
{
int x;
int *integer = (int*)malloc(sizeof(int)*4);
srand ((int) time(NULL));
for (x=0; x<4; x++)
integer[x]=rand();
return integer;
}
Don't forget to free() the memory when you are done.
In case you are wondering about malloc & free, you can read here:http://www.codingunit.com/c-tutorial-the-functions-malloc-and-free
About the random part:
If you really want to feel the randomness of c rand() seeded by time(0), you should run rand() like 3 times before you use it for generating actual numbers. To justify that, try running this code few times one after another while printing the numbers. You will notice that first one will be almost the same. My out:
1023384829 832292180 1773676349 957893636
1023401636 1114767429 1248842775 1942837294
1023418443 1397242678 724009201 780297305
So your srand should look like this:
srand ((int) time(NULL));
rand(); rand(); rand();
Related
sorry if someone already asked this, didn't find it.
I'm wandering what's the minimum number of arguments i have to pass to a recursive function in order to explore all its values.
I'll make an example; suppose I want to write a function which returns me the sum of all the values contained in a MXM matrix, i can surely do it (and did it) like this:
int sum(int mat[][M], int i, int j){
if(j==M-1&&i==M-1){
return mat[i][j];
}
if(j==M){
i++;
j=0;
}
return mat[i][j] + sum(mat, i, j+1);
}
Calling
sum(mat,0,0);
I obtain the result.
My question is: can I obtain the same result writing a function with less arguments?
About the example: can I obtain the same result writing a funtion like:
int sum(int mat[][M], int i){...}
or just
int sum(int mat[][M]){...}
?
More abstractly speaking, what is the minimum number of arguments I need to pass to a recursive function in order to explore a matrix?
Thanks everyone.
You could do it with one argument by having it be the row-major index of the element to add. The function can calculate the row and column indexes from that.
int sum(int mat[M][M], int x){
int i = x / M;
int j = x % M;
if(j==M-1 && i==M-1){
return mat[i][j];
}
return mat[i][j] + sum(mat, x+1);
}
You can't do it by just passing the array, because you need some way of telling when you've reached the base case so the recursion should stop. A recursive call has to have some parameter that changes each time, getting closer to the base case. But the array value doesn't change.
For this program we have to create a user defined function to return 25 random variables from a value of 60-100, but when I run the program all 25 values are the same. I'm pretty new at programming and I think the error resided in where the user-function is defined, because I think instead of running the variable 25 times, its just running once and printing that first value 25 times. But I don't know how to actually go about fixing it :(
#include <stdlib.h>
#include <time.h>
int get_value (int Random);
int main ()
{
srand(time(NULL));//to randomize the number after each run
int Random = rand()%40+60;
printf("These are the temperatures for the day\n");
int temp[25], i;
for (i=0; i<25; i++)
{
temp[i] = Random;
printf("%d\n" ,temp[i]);
}
return 0;
}
int get_value (int Random)
{
Random = rand() % 40 + 60;
}
That's because get_value() has not returned anything. The Random argument is a copy of the Random which you (might have) passed. It's legitimate to overwrite a (non-const) function arguement, but it won't find it's way way to the caller. The second problem is that you never call this function anyway, you just repeat the first random number you generated.
I suggest you rewrite the function like this
int get_value (void)
{
return rand()%41+60; // range 60 to 100
}
and call it like this
temp[i] = get_value();
You assign to Random once; then you copy its value each time through the loop, giving you the same value each time as reported. You need to regenerate the random number with a new call to rand() on each iteration. You're correct to call srand() only once; that is important.
Your function only generates values in the range 60..99, not 60..100 as required in the question. The fix is trivial; use 41 instead of 40.
Of course, having the get_value() function is no help if you never call it. OTOH, it doesn't use its input argument, and it doesn't return a value, so maybe it is just as well that you never use it.
I have a simple C program which is supposed to fill an array with random values (this is the beginning of a school assignment). I'm using rand(), seeding it with srand(time()). Because this tended to generate somewhat predictable results when run repeatedly in a certain time period, I made another very simple function to give me a somewhat more random seed value:
time_t getRandomSeed(int numberOfIterations)
{
int i;
time_t result=time();
for (i = 0; i < numberOfIterations; i++)
{
result = randomizeSeed(result);
}
return result;
}
time_t randomizeSeed(time_t seed)
{
time_t result, fullTime, Modifier1, Modifier2;
srand((unsigned int)seed);
fullTime = time();
Modifier1 = time() >> (rand() % 10);
Modifier2 = (unsigned short)time();
Modifier2 <<= (rand() % 9 + 9);
result = fullTime ^ Modifier1 ^ Modifier2;
return result;
}
In main, I'm calling this inside srand() after declaring 2 int arrays. When I return to main, these arrays are garbage, and I can't figure out why.
int main(void)
{
int randomNumbers[ARRAY_LENGTH];
int sortedNumbers[ARRAY_LENGTH];
srand((unsigned int)getRandomSeed(2));
fillArray(randomNumbers, sizeof(randomNumbers) / sizeof(randomNumbers[0]));
return 0;
}
I set a breakpoint at line 4, and I have a perfectly normal unititialized array (at 0x00e1ea70 in the most recent run). Then I set another breakpoint at line 8, so I could see the array just before it was passed into fillArray. At this point, the address of the array is somehow 0xfffff04c, and all the elements show "unable to read memory", which I guess makes sense given the address is garbage.
Can anybody give me a clue what's happening to my array?
*Note, this is for a school assignment, so I don't really care if the RNG is secure, nor can I use any 3rd party libraries.
Update:
Per request, this is the body of fillArray(). However, from my question, the problem happens before we ever get to fillArray(), as I'm setting the breakpoint before it get's called.
void fillArray(int array[], size_t length)
{
size_t i;
for (i = 0; i < length; i++)
{
array[i] = rand()%1000 + 1;
}
return;
}
In your function randomizeSeed() you are calling time() three times in succession without an argument.
fullTime = time();
Modifier1 = time() >> (rand() % 10);
Modifier2 = (unsigned short)time();
The function prototype is
time_t time(time_t *timer);
So you should pay attention to your compiler warnings. From this point on, you have Undefined behaviour.
I am trying to write a program that will assign 5 random integers to an array but so far it is filling the array with zeroes. Also, the first number can't be a zero. What am I doing wrong?
#include <stdio.h>
#include <stdlib.h>
int number[5];
int main() {
int i;
int t=0;
for (int t=0;t<5;t++) {
if (i=0)
{number[i] = rand()%8+1;}
else
{number[i] = rand()%10;}
i++;
printf("%d", number[i]);
}
return (0);
}
if (i=0)
That's assignment, not equality comparison.
int i;
Also, i is uninitialized, so accessing its value is undefined behavior. Since you accidentally assigned to it instead of comparing to it, if (i=0) doesn't invoke undefined behavior, but it would if you fixed the first bug.
i++;
printf("%d", number[i]);
Incrementing i before the print means you always print the cell right after the one you were working on.
You don't actually need i; t does everything you want i to do. We'll remove i and rename t to i:
for (int i = 0; i < 5; i++) {
if (i == 0) {
number[i] = rand() % 8 + 1;
} else {
number[i] = rand() % 10;
}
printf("%d", number[i]);
}
Several things are wrong in your code ...
1)
You didn't initialize the variable i
2)
if(i=0)
should be
if( i == 0 )
3)
You can use variable t instead of i -- means variable i is unnecessary
4)
You should have a function call for randomize() function before rand() function call, so that you can get the real random numbers
5)
If you just want to show the random numbers, you don't even need to use array
You will get the same sequence of 'pseudo-random' values by calling rand() in your program. To change this sequence the Random Number generator has to be 'seeded'. This is done by calling srand() function once with a seed value at the beginning of your program.
Ideally the value used for seed should change with each run of the program. Things that you could use as the seed are the process id, time, date or any other system provided value that is guaranteed to be different for each run of the program.
void srand(unsigned int seed);
Apart from that there are logical flaws in your program as others have highlighted, of which the if conditional assignment error is the most serious.
Currently I have this code, and it works.
#include <stdio.h>
int isFactor(long number1, long number2)
{
int isitFactor = (number2 % number1 == 0)?1:0;
return isitFactor;
}
int isPerfect(int number)
{
int counter;
int sum;
for (counter = 1; counter < number; counter++)
if (isFactor(counter, number))
sum += counter;
return (sum == number);
}
int main()
{
int counter = 1;
for (counter = 1; counter <= 100; counter++)
{
printf("", isPerfect(counter));
if (isPerfect(counter))
printf("%d\n", counter);
}
}
However, if I take out the unnecessary line with the printf in main(), it fails to produce any numbers.... Possible causes?!
Variable sum in function isPerfect is not initialized.
You had two problems with that code, the first is that sum is not initialised and will generally be set to whatever rubbish happened to be on the stack at the time the function was called. Automatic variables are not guaranteed to be initialised to zero (or anything, for that matter) so, if you need them to start with a specific value, you have to initialise them yourself.
The second problem (now fixed with your edit) was that isFactor is missing. Although you probably want it as a function, the following code works, producing the two perfect numbers less than 100, 6 and 28:
#include "stdio.h"
#define isFactor(c,n) ((n % c) == 0)
int isPerfect (int number) {
int counter;
int sum = 0; // <-- note initialisation here.
for (counter = 1; counter < number; counter++)
if (isFactor(counter, number)) sum += counter;
return (sum == number);
}
int main (void) { // try to use one of the two canonical forms.
int counter = 1;
for (counter = 1; counter <= 100; counter++)
if (isPerfect(counter)) printf("%d\n", counter);
return 0;
}
And, looking into why it might be working with that extra printf, here's a viable explanation.
When calling a function, the local variables are allocated on the stack simply by reducing the stack pointer. Your isPerfect asembly code probably just has a prolog like:
sub %esp,8
and then you use the memory at %esp for counter and %esp + 4 for sum. Without initialising sum, it starts with whatever happened to be at that memory location, which is probably not zero.
Now think about what happens when you call printf first. It no doubt has its own local variables so it uses the part of the stack that you will later be relying on to be initialised to zero. When the printf returns, it doesn't set those memory locations back to their previous values, it just increments the stack pointer to skip over them.
Then, when you call isPerfect, there's a good chance that those memory locations will be different to what they were before you called printf, simply because printf has been using them for its own purposes.
If you're lucky (or unlucky, depending on your viewpoint), the memory location where sum will be may even be zero. But it's undefined behaviour nonetheless and you should not rely on it - initialise sum explicitly and your (immediate) problems will be over.
If this is homework, feel free to ignore this bit (in fact, actively ignore it since you may get caught out for plagiarism). This is how I would implement the isPerfect function as a first cut. It doesn't call functions to work out factors since, while they're generally quite fast, they're not without cost, and something that simple can be done in a single line of C anyway.
int isPerfect (int num) {
int i, left;
for (i = 1, left = num; i < num; i++)
if ((num % i) == 0)
left -= i;
return (left == 0);
}
There's no doubt it could be made faster but the return on investment drops away pretty quickly after a certain point.