rand() returns nothing but zeroes - c

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.

Related

Why we can't compare a int variable with int return type function in c?

I tried to compare int variable with the function in two ways:
storing the int function return value in a variable then comparing with another
in value.
Directly comparing the int variable and the function call.
Here I got the answer for the first one but not for the second one.
Why does this happen?
My code:
#include < stdio.h >
int count = 0;
int countDigits(int);
int main() {
int i;
int result = countDigits(435);
for (i = 0; i < result; i++) {
printf("id %d\n", 3);
}
for (i = 0; i < countDigits(435); i++) {
printf("i =%d\n", i);
}
}
int countDigits(int n) {
if (n == 0) {
return count;
} else {
countDigits(n / 10);
count++;
}
}
We can.
It's just that your function has a logical error. Debug it, and you will be fine.
Enabling compiler warnings would have helped you. For example with GCC and Wall flag, you get:
prog.c: In function 'countDigits':
prog.c:32:1: warning: control reaches end of non-void
function [-Wreturn-type]
}
^
Tip: Think of what your function does if n us different than zero.
count is a global variable.
The function countDigits(n) adds the number of decimal digits in n to count and
If n is zero it returns 1.
If n is non-zero the return value is undefined.
Since countDigits(435) has an undefined value, anything can happen and no further analysis is necessary.
Let's assume that this obvious error is corrected by inserting return count; after count++;. In this case, the function returns the incremented count.
So we have this nice sequence:
Set result to countDigits(435).
countDigits(435) adds 3 to count and returns 3.
Set i to 0 and compare to countDigits(435).
countDigits(435) adds 3 to count and returns 6. 0 is less than 6, so the for loop continues.
Now i is 1, and we compare it to countDigits(435).
countDigits(435) adds 3 to count and returns 9. 1 is less than 9, so the for loop continues.
Now i is 2, and we compare it to countDigits(435).
countDigits(435) adds 3 to count and returns 12. 2 is less than 12, so the for loop continues.
... And so on.
Morality:
Beware of side effects. Never use and modify global variables unless you have a good reason to.
When you must use side effects, keep them prominent in your mind.
It is possible to compare a variable directly with the output of a function. However, your function countDigits has several problems.
Not all code paths return a value - you're missing a return statement in the else block. This alone makes the output of the function undefined.
It's not algorithmically correct. Have you tried debugging it? Just start with printing the output for different inputs and you'll see.
Modifying and returning a global variable count inside that function is a really bad practice - it should be local to the function. When it's global, every call to the function modifies a [possibly] already modified variable.
Others have already addressed the problem here with globals, so I will not go into details about that. Instead, here is a solution without globals:
int countDigits(int n) {
int count = 0;
while(n>0) {
n/=10;
count++;
}
return count;
}
I guess you could be philosophical about whether 0 has 0 or 1 digit, but your code implied that you wanted it to be 0. If you want it to be 1 instead, just change the first row to int count = 1.

I cant write this factorial codes

I have some problem with that. I am trying to learn C programming. Please help me
#include<stdio.h>
int main()
{
int a, factorial;
printf("Please enter a value :" );
scanf("%d", &a);
for (int i = 1; i<=a; i++)
{
a = (a - 1)*a;
}
printf("%d", factorial);
return 0;
}
Well in your code line a = (a - 1)*a; you actually changed your input for getting the factorial. It also will blow your loop. See your for loop will continue as long as your i is less than a, lets say you choose a=3 after first iteration the a itself will become 6, so the for loop will continue until it reach the integer limit and you will get overflow error.
What you should do?
First of all you should use a second variable to store the factorial result, you introduced it as factorial, the way that #danielku97 said is a good way to write a factorial since if you present 0 as input it will also give the correct result of 1. so a good code is:
factorial = 1;
for (int i = 1; i<=a; i++)
{
factorial *= i;
}
But lets say you insist of subtraction, the way you just tried to use, then you need to change the code like:
scanf("%d", &a);
if (a==1 || a==0){
printf("1");
return 0;
}
factorial = a;
for (int i = 1; i<a; i++)
{
factorial *= (a - i)*factorial;
}
You can see that the code just got unnecessarily longer. An if included to correct the results for 1 and 0. Also you need to make sure that i never become like i =a since in that case a-i will be equal to zero and will make the factorial result equal to zero.
I hope the explanations can help you on learning C and Algorithm faster.
Your for loop is using your variable 'a' instead of the factorial variable and i, try something like this
factorial = 1;
for (int i = 1; i<=a; i++)
{
factorial *= i;
}
You must initialize your factorial to 1, and then the for loop will keep multiplying it by 'i' until 'i' is greater than 'a'.
You are modifying the input a rather than factorial and also wrong (undefined behaviour) because you are using factorial uninitialized. You simply need to use the factorial variable you declared.
int factorial = 1;
...
for (int i = 1; i<=a; i++) {
factorial = i*factorial;
}
EDIT:
Also, be aware that C's int can only hold limited values. So, beyond a certain number (roughly after 13! if sizeof(int) is 4 bytes), you'll cause integer overflow.
You may want to look at GNU bugnum library for handling large factorial values.

user-defined function for random number generator in C output incorrect

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.

Using rand( ) to generate a random sequence of integers in C

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();

Perfect Numbers bug?

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.

Resources