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.
Related
This question already has answers here:
Why do I always get the same sequence of random numbers with rand()?
(12 answers)
If I don't specify srand(), what seed does rand() use?
(5 answers)
Closed 5 years ago.
Program uses rand() function to generate random index. But it always produces same string no matter what! Why won't this work?
void rand_string()
{
int a[10];
int i;
char b[] = "qwertyuiopasdfghjklzxcvbnm1234567890QWERTYUIOPASDFGHJKLZXCVBNM";
printf("%d", sizeof(b) / sizeof(b[0]));
for(i = 0; i < 10; i++)
{
int gen_rand = rand() % 63;
a[i] = b[gen_rand];
}
for(i = 0; i < 10; i++)
printf("%c", a[i]);
}
Use srand function to seed the random generator
srand((unsigned)time(NULL));
Note that you only have to seed once in your program otherwise it will not work properly.
You could firstly define a random function specific to your needs, i.e. generating in specific range (the length of the current string), like so:
int random(int min, int max)
{
return min + (rand()) / (RAND_MAX / (max - min));
}
then in your string-random-generator function you could also add a random length to every string:
void rand_str()
{
static const char alphanum[] =
"0123456789"
"ABCDEFGHIJKLMNOPQRSTUVWXYZ"
"abcdefghijklmnopqrstuvwxyz"; // define only on first call
// call srand() using #include <time.h> ; could be outside of function, i.e. in main()
int length = random(0, 10); // get random length in [0, 10] on each call
// use length and random(0, sizeof(alphanum) / sizeof(alphanum[0])) in for loop
// everything else is the same...
}
use the keyword static to indicate single1 definition of the array alphanum (think of it that it is like making it global) and call function srand() once, before the use of random().
Note: you should consider modifying your function to a single purpose, i.e. only generating a random string and returning (a pointer to) a string; and printing it in a separate function.
1. Only on the first call of rand_str().
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();
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.
i'm writing a code for a number on a led segement to decrease by 1 every five seconds
my actual code at the moment is this
FiveSecDelay+=1;
if (FiveSecDelay ==100)
{
count2--; //decrement count2
for (uint32_t x = 0; x < 4; x++) //split count to to individual digits
{
new_value[x] = count2 % 10;
count2 = count2 / 10;
}
for (uint32_t i = 0; i < 4; i++)
{
Segment_Write(Digit[i],new_value[i]); assign value to segments
}
FiveSecDelay =0;
}
im using a schedular to call a function every milisecond, in theory this supposed to work as i used the same technique to assign a value to the segments,
what happens is that i have a starting value of 8, and it supposed to got 7,6,5,4 and so on till 0, but for some reason it goes from 8 to 42 and stays there
I had tried to fix it but have come up short.
Any help would be great
Thank you
Quick and dirty way:
while(true)
{
check();
sleep(5);
}
int values[1];
int check(void)
{
if (values[0] > 0)
values[0]--;
}
If you have access to the system time, you can store the initial time the call was made, and then every time you query its value, check against the system time to determine the correct adjusted value, and a little snippet to set the value, like such:
// initialize
int check = 142;
unsigned long long time = getMillis();
int get_value(void)
{
unsigned long long time_factor = ((getMillis() - time) / (unsigned long long) 5);
if (time_factor > (unsigned long long) check)
return 0;
else
return check - time_factor;
}
void set_value(int v)
{
check = v;
time = getMillis();
}
Note that I don't know off the top of my head how to get the system time in c (though I bet you'd need #include <time.h>) so I made up a function called getMillis() which returns the system time as an unsigned long long (should be a 64 bit unsigned integer). The implementation is up to the reader.
It's also worth mentioning that you will experience a wraparound error after about 600 million years.
void check() {
static int array[] = {142}; // why are you using an array here?
(*array)--;
}
int main() {
while(true)
{
check();
usleep(5000); // approximate
}
return 0;
}
Have check take a parameter which is the number. Then have a counter in the main loop of your program that starts at some value, and is decremented every time check is called.
I'm assuming that you are doing something more complex than what your current check function does because obviously it doesn't do anything in the provided form. If you provide more information, we would be able to give you a more thorough and applicable solution.
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.