How can I reduce the runtime? - c

Here is a link to the problem I'm trying to solve: http://acm.timus.ru/problem.aspx?space=1&num=1086
Here is my approach:
#include <stdio.h>
#include <math.h>
int main()
{
int n, i, m, p;
scanf("%d", &n);
for(i = 0; i < n; i++)
{
scanf("%d", &m);
p = find_prime(m);
printf("%d\n", p);
}
return 0;
}
int find_prime(int a)
{
int i, p = 1, t, prime[15000], j;
prime[0] = 2;
for(i = 0; i < a; )
{
if(p == 2)
{
p++;
}else
{
p = p + 1;
}
t = 0;
for(j = 0; prime[j] <= sqrt(p); j++)
{
if(p%prime[j] == 0 && p != 2)
{
t = 1;
break;
}
}
if(t != 1)
{
i++;
prime[i] = p;
}
}
return p;
}
I know the algorithm is fine and it produces the correct answer. But I always get "Time Limit Exceeded". I can't get the runtime download to 2 seconds. It's always equal to 2.031 seconds. I have tried few other approaches, for example, I iterated through all the numbers until I found the mth prime number, I tried skipping the even integers greater than 2 but I still get 2.031 seconds.
What should I do?

Your buffer for prime numbers doesn't need to be a local variable that's recalculated every time.
You can try to memoize by storing the buffer in the global scope and using a global counter to keep track of how many primes you have already calculated until now and which number was the maximum number requested.
If the next number that's requested from you is smaller than the previous maximum, you should fall back to the corresponding pre-calculated number. If the next number is larger than the previous maximum, make it the new maximum - and also try to start calculating from where you last left off.

Remove
if(p == 2)
{
p++;
}else
{
p = p + 1;
}
and replace it with
p++

as I understand it,
the problem is to find the next prime greater that the sum of all the prior input numbers.
That means there are certain expectations.
1) the sum of the prior input numbers is available in find_prime().
2) for simplification, the last found prime number is available in find_prime().
Neither of these expectations are implemented.
Then there is that 60 thousand byte array on the stack in find_prime().
Suggest moving that to a file global position and including a 'static' modifier.
move the prior sum of inputs to a file global location, so it is always available.
for overall speed,
calculate all the primes in the array as a first thing, thereby filling the array with prime values. then
1) add new input to sum,
2) index into array using sum.
3) return value found in array.

Related

the largest palindrome made from the product of two 3-digit numbers. using c .whats wrong in my code?

Program not working, not giving output, I don't know what to do, where the problem is.
I'm trying to find out the largest palindrome made from the product of two 3-digit numbers.
#include <stdio.h>
main() {
int i, k, j, x;
long int a[1000000], palindrome[1000000], great, sum = 0;
// for multiples of two 3 digit numbers
for (k = 0, i = 100; i < 1000; i++) {
for (j = 100; j < 1000; j++) {
a[k] = i * j; // multiples output
k++;
}
}
for (i = 0, x = 0; i < 1000000; i++) {
// for reverse considered as sum
for (; a[i] != 0;) {
sum = sum * 10 + a[i] % 10;
}
// for numbers which are palindromes
if (sum == a[i]) {
palindrome[x] = a[i];
x++;
break;
}
}
// comparison of palindrome number for which one is greatest
great = palindrome[0];
for (k = 0; k < 1000000; k++) {
if (great < palindrome[k]) {
great = palindrome[k];
}
}
printf("\ngreatest palindrome of 3 digit multiple is : ", great);
}
What do you mean with "not working"?
There are two things, from my point of view:
1) long int a[1000000], palindrome[1000000]
Depending on you compile configuration you could have problems compiling your code.
Probably the array is too big to fit in your program's stack address space.
In C or C++ local objects are usually allocated on the stack. Don't allocate it local on stack, use some other place instead. This can be achieved by either making the object global or allocating it on the global heap.
#include <stdio.h>
long int a[1000000], palindrome[1000000], great, sum = 0;
main() {
int i, k, j, x;
2) printf("\ngreatest palindrome of 3 digit multiple is : ", great);
I will change it by :
printf("\ngreatest palindrome of 3 digit multiple is %li: ", great);
Regards.
Compiling and running your code on an on-line compiler I got this:
prog.c:3:1: warning: type specifier missing, defaults to 'int' [-Wimplicit-int]
main() {
^
prog.c:34:61: warning: data argument not used by format string [-Wformat-extra-args]
printf("\ngreatest palindrome of 3 digit multiple is : ", great);
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ^
2 warnings generated.
Killed
Both the warnings should be taken into account, but I'd like to point out the last line. The program was taking too much time to run, so the process was killed.
It's a strong suggestion to change the algorithm, or at least to fix the part that checks if a number is a palindrome:
for (; a[i] != 0;) { // <-- If a[i] is not 0, this will never end
sum = sum * 10 + a[i] % 10;
}
I'd use a function like this one
bool is_palindrome(long x)
{
long rev = 0;
for (long i = x; i; i /= 10)
{
rev *= 10;
rev += i % 10;
}
return x == rev;
}
Also, we don't need any array, we could just calculate all the possible products between two 3-digits number using two nested for loops and check if those are palindromes.
Starting from the highest numbers, we can store the product, but only if it's a palindrome and is bigger than any previously one found, and stop the iteration of the inner loop as soon as the candidate become less then the stored maximum. This would save us a lot of iterations.
Implementing this algorithm, I found out a maximum value of 906609.

I want to optimize this program

I have recently started to learn c and as a programming exercise, I've written a program that computes and lists out prime numbers from 0 up to a maximum entered by the user. It's a rather short program so I'll post the source code here.
// playground.c
#include <stdio.h>
#include <stdbool.h>
#include <math.h>
int main ()
{
int max;
printf("Please enter the maximum number up to which you would like to see all primes listed: "
); scanf("%i", &max);
printf("All prime numbers in the range 0 to %i:\nPrime number: 2\n", max);
bool isComposite;
int primesSoFar[(max >> 1) + 1];
primesSoFar[0] = 2;
int nextIdx = 1;
for (int i = 2; i <= max; i++)
{
isComposite = false;
for (int k = 2; k <= (int)sqrt(i) + 1; k++)
{
if (k - 2 < nextIdx)
{
if (i % primesSoFar[k - 2] == 0)
{
isComposite = true;
k = primesSoFar[k - 2];
}
}else
{
if (i % k == 0) isComposite = true;
}
}
if (!isComposite)
{
printf("Prime number: %i\n", i);
primesSoFar[nextIdx] = i;
nextIdx++;
}
}
double primeRatio = (double)(nextIdx + 1) / (double)(max);
printf("The ratio of prime numbers to composites in range 0 to %d is %lf", max, primeRatio);
return 0;
}
I have become strangely fascinated with optimizing this program but I've hit a wall. The array primesSoFar is allocated based on a computed maximum size which ideally would be no larger than the number of prime numbers from 0 to max. Even if it were just slightly larger, that would be fine; as long as it's not smaller. Is there a way to compute the size the array needs to be that doesn't depend on first computing the primes up to max?
I've updated the code both applying suggested optimizations and adding internal documentation wherever it seemed helpful.
// can compute all the primes up to 0x3FE977 (4_188_535). Largest prime 4_188_533
#include <stdio.h>
#include <stdbool.h>
#include <math.h>
int main ()
{
int max;
printf("Please enter the maximum number up to which you would like to see all primes listed: "
); scanf("%i", &max);
// The algorithm proper doesn't print 2.
printf("All prime numbers in the range 0 to %i:\nPrime number: 2\n", max);
bool isComposite;
// primesSoFar is a memory hog. It'd be nice to reduce its size in proportion to max. The frequency
// of primes diminishes at higher numerical ranges. A formula for calculating the number of primes for
// a given numerical range would be nice. Sadly, it's not linear.
int PRIMES_MAX_SIZE = (max >> 1) + 1;
int primesSoFar[PRIMES_MAX_SIZE];
primesSoFar[0] = 2;
int nextIdx = 1;
int startConsecCount = 0;
for (int i = 2; i <= max; i++)
{
isComposite = false; // Assume the current number isn't composite.
for (int k = 2; k <= (int)sqrt(i) + 1; k++)
{
if (k - 2 < nextIdx) // Check it against all primes found so far.
{
if (i % primesSoFar[k - 2] == 0)
{
// If i is divisible by a previous prime number, break.
isComposite = true;
break;
}else
{
// Prepare to start counting consecutive integers at the largest prime + 1. if i
// isn't divisible by any of the primes found so far.
startConsecCount = primesSoFar[k - 2] + 1;
}
}else
{
if (startConsecCount != 0) // Begin counting consecutively at the largest prime + 1.
{
k = startConsecCount;
startConsecCount = 0;
}
if (i % k == 0)
{
// If i is divisible by some value of k, break.
isComposite = true;
break;
}
}
}
if (!isComposite)
{
printf("Prime number: %i\n", i);
if (nextIdx < PRIMES_MAX_SIZE)
{
// If the memory allocated for the array is sufficient to store an additional prime, do so.
primesSoFar[nextIdx] = i;
nextIdx++;
}
}
}
// I'm using this to get data with which I can find a way to compute a smaller size for primesSoFar.
double primeRatio = (double)(nextIdx + 1) / (double)(max);
printf("The ratio of prime numbers to composites in range 0 to %d is %lf\n", max, primeRatio);
return 0;
}
edit: primesSoFar should be half the size of the range 0 to max. No doubt that's caused some confusion.
I can give you two main ideas as I have worked on a project discussing this problem.
A prime number bigger than 3 is either 6k-1 or 6k+1, so for example 183 can't be prime because 183=6x30+3, so you don't even have to check it. (Be careful, this condition is necessary but not sufficient, 25 for exemple is 6x4+1 but is not prime)
A number is prime if it can't be divided by any prime number smaller or equal to its root, so it's preferable to take a benefit out of the smaller primes you already found.
Thus, you can start with a primesList containing 2 and 3, and iterate k to test all the 6k-1 and 6k+1 numbers (5, 7, 11, 13, 17, 19, 23, 25...) using the second rule I gave you, by using division on elements in the primesList which are smaller than or equal to the root of the number you are checking, if you found only one element dividing it, you just stop and pass to another element, 'cause this one is not prime, otherwise (if no one can divide it): update the primesList by adding this new prime number.
There is some debugging to be done first.
When I saw that the test was <= my brain said BUG as Arrays are subscripted from 0 .. max - 1.
for (int i = 2; i <= max; i++)
So I went to look at the array.
int primesSoFar[(max >> 1) + 1];
Oh he is adding one to the size so it should be ok.
Wait. Why is that shift in there? (max >> 1) is a divide by two.
I compiled the code and ran it, and MSVC reported a memory error.
I removed the shift, and the memory error report went away. The program worked as expected.
With that out of the way, PiNaKa30 and II Saggio Vecchino have very good advice. The choice of algorithm is going to effect the performance dramatically.
Mat gives very good advice. Read the Wikipedia entry. It is filled with wonderful information.
Picking the correct algorithm is key.
How you represent the data you are checking is a factor. int has a maximum value it can hold.
A performance profiler can tell you lots of useful information about where the Hot Spots are in your program.
Congratulations on your efforts in learning C. You picked a very good learning path.
The source code that follows is basically a rewrite. It's running now as I write this. I entered 0x7FFF_FFFF, the 32-bit signed integer positive maximum. In mere minutes on my Acer aspire laptop running on an AMD ryzen 3 with Linux Mint it's already in the hundreds of millions! The memory usage of the old version was half of max, rendering anything larger than 0x3EF977 impossible on my 4gb of RAM. Now it only uses 370728 bytes of memory for its array data when computing primes from 0 to 2_147_483_647.
/*
A super optimized prime number generator using my own implementation of the sieve of Eratosthenes.
*/
#include <stdio.h>
#include <stdbool.h>
#include <math.h>
int main ()
{
int max;
printf("Please enter the maximum to which you would like to see all primes listed: "
); scanf("%i", &max);
/*
Primes and their multiples will be stored until the next multiple of the prime is larger than max.
That prime and its corresponding multiple will then be replaced with a new prime and its corresponding
multiple.
*/
int PRIMES_MAX_SIZE = (int)sqrt(max) + 1;
int primes[PRIMES_MAX_SIZE];
int multiples[PRIMES_MAX_SIZE];
primes[0] = 2;
multiples[0] = 2;
int nextIdx = 1;
int const NO_DISPOSE_SENTINAL_VALUE = -1;
int nextDispose = NO_DISPOSE_SENTINAL_VALUE;
int startConsecCount = 0;
int updateFactor;
bool isComposite;
printf("All prime numbers in the range 0 to %i:\n\n", max);
// Iterate from i = 2 to i = max and test each i for primality.
for (int i = 2; i <= max; i++)
{
isComposite = false;
/*
Check whether the current i is prime by comparing it with the current multiples of
prime numbers, updating them when they are less than the current i and then proceeding
to check whether any consecutive integers up to sqrt(i) divide the current i evenly.
*/
for (int k = 2; k < (int)sqrt(i) + 1; k++)
{
if (k < nextIdx)
{
// Update the multiple of a prime if it's smaller than the current i.
if (multiples[k] < i)
{
updateFactor = (int)(i / primes[k]);
multiples[k] = updateFactor * primes[k] + primes[k];
// Mark the value for disposal if it's greater than sqrt(max).
if (multiples[k] > (int)sqrt(max)) nextDispose = k;
}
if (i == multiples[k])
{
isComposite = true;
break;
}else
{
startConsecCount = multiples[k] + 1;
}
} else
{
if (startConsecCount != 0)
{
k = startConsecCount;
startConsecCount = 0;
}
if (i % k == 0)
{
isComposite = true;
break;
}
}
}
/*
Print the prime numbers and either insert them at indices occupied by disposed primes or at
the next array index if available.
*/
if (!isComposite)
{
printf("Prime number: %i\n", i);
if (nextDispose != NO_DISPOSE_SENTINAL_VALUE)
{
primes[nextDispose] = i;
// This will trigger the update code before the comparison in the inner loop.
multiples[nextDispose] = 0;
nextDispose = NO_DISPOSE_SENTINAL_VALUE;
}else
{
if (nextIdx < PRIMES_MAX_SIZE)
{
primes[nextIdx] = i;
multiples[nextIdx] = 0;
}
}
}
}
return 0;
}
This thing will do the old 0 to 0x3EF977 in the blink of an eye. The old version couldn't do the 32-bit maximum on my system. It's on 201 million + already. I am super chuffed with the results. Thank you for your advice. I wouldn't have made it this far without help.

checking if a array has numbers in it from 0 to length -1 in C

I have got an assignment and i'll be glad if you can help me with one question
in this assignment, i have a question that goes like this:
write a function that receives an array and it's length.
the purpose of the function is to check if the array has all numbers from 0 to length-1, if it does the function will return 1 or 0 otherwise.The function can go through the array only one.
you cant sort the array or use a counting array in the function
i wrote the function that calculate the sum and the product of the array's values and indexes
int All_Num_Check(int *arr, int n)
{
int i, index_sum = 0, arr_sum = 0, index_multi = 1, arr_multi = 1;
for (i = 0; i < n; i++)
{
if (i != 0)
index_multi *= i;
if (arr[i] != 0)
arr_multi *= arr[i];
index_sum += i;
arr_sum += arr[i];
}
if ((index_sum == arr_sum) && (index_multi == arr_multi))
return 1;
return 0;
}
i.e: length = 5, arr={0,3,4,2,1} - that's a proper array
length = 5 , arr={0,3,3,4,2} - that's not proper array
unfortunately, this function doesnt work properly in all different cases of number variations.
i.e: length = 5 , {1,2,2,2,3}
thank you your help.
Checking the sum and product is not enough, as your counter-example demonstrates.
A simple solution would be to just sort the array and then check that at every position i, a[i] == i.
Edit: The original question was edited such that sorting is also prohibited. Assuming all the numbers are positive, the following solution "marks" numbers in the required range by negating the corresponding index.
If any array cell already contains a marked number, it means we have a duplicate.
int All_Num_Check(int *arr, int n) {
int i, j;
for (i = 0; i < n; i++) {
j = abs(arr[i]);
if ((j >= n) || (arr[j] < 0)) return 0;
arr[j] = -arr[j];
}
return 1;
}
I thought for a while, and then i realized that it is a highly contrained problem.
Things that are not allowed:
Use of counting array.
Use of sorting.
Use of more than one pass to the original array.
Hence, i came up with this approach of using XOR operation to determine the results.
a ^ a = 0
a^b^c = a^c^b.
Try this:
int main(int argc, char const *argv[])
{
int arr[5], i, n , temp = 0;
for(i=0;i<n; i++){
if( i == 0){
temp = arr[i]^i;
}
else{
temp = temp^(i^arr[i]);
}
}
if(temp == 0){
return 1;
}
else{
return 0;
}
}
To satisfy the condition mentioned in the problem, every number has to occour excatly once.
Now, as the number lies in the range [0,.. n-1], the looping variable will also have the same possible range.
Variable temp , is originally set to 0.
Now, if all the numbers appear in this way, then each number will appear excatly twice.
And XORing the same number twice results in 0.
So, if in the end, when the whole array is traversed and a zero is obtained, this means that the array contains all the numbers excatly once.
Otherwise, multiple copies of a number is present, hence, this won't evaluate to 0.

Counting number of primes within a given range of long int using C

Well, there are lots of such questions available in SO as well as other forums. However, none of these helped.
I wrote a program in "C" to find number of primes within a range. The range i in long int. I am using Sieve of Eratosthenes" algorithm. I am using an array of long ints to store all the numbers from 1 till the limit. I could not think of a better approach to achieve without using an array. The code works fine, till 10000000. But after that, it runs out of memory and exits. Below is my code.
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
typedef unsigned long uint_32;
int main() {
uint_32 i, N, *list, cross=0, j=4, k, primes_cnt = 0;
clock_t start, end;
double exec_time;
system("cls");
printf("Enter N\n");
scanf("%lu", &N);
list = (uint_32 *) malloc( (N+1) * sizeof(uint_32));
start = clock();
for(i=0; i<=N+1; i++) {
list[i] = i;
}
for(i=0; cross<=N/2; i++) {
if(i == 0)
cross = 2;
else if(i == 1)
cross = 3;
else {
for(j=cross+1; j<=N; j++) {
if(list[j] != 0){
cross = list[j];
break;
}
}
}
for(k=cross*2; k<=N; k+=cross) {
if(k <= N)
list[k] = 0;
}
}
for(i=2; i<=N; i++) {
if(list[i] == 0)
continue;
else
primes_cnt++;
}
printf("%lu", primes_cnt);
end = clock();
exec_time = (double) (end-start);
printf("\n%f", exec_time);
return 0;
}
I am stuck and can't think of a better way to achieve this. Any help will be hugely appreciated. Thanks.
Edit:
My aim is to generate and print all prime numbers below the range. As printing consumed a lot of time, I thought of getting the first step right.
There are other algorithm that does not require you to generate prime number up to N to count number of prime below N. The easiest algorithm to implement is Legendre Prime Counting. The algorithm requires you to generate only sqrt(N) prime to determine the number of prime below N.
The idea behind the algorithm is that
pi(n) = phi(n, sqrt(n)) + pi(sqrt(n)) - 1
where
pi(n) = number of prime below N
phi(n, m) = number of number below N that is not divisible by any prime below m.
That's mean phi(n, sqrt(n)) = number of prime between sqrt(n) to n. For how to calculate the phi, you can go to the following link (Feasible implementation of a Prime Counting Function)
The reason why it is more efficient is because it is easiest to compute phi(n, m) than to compute pi(n). Let say that I want to compute phi(100, 3) means that how many number below or equal to 100 that does not divisible by 2 and 3. You can do as following. phi(100, 3) = 100 - 100/2 - 100/3 + 100/6.
Your code uses about 32 times as much memory as it needs. Note that since you initialized list[i] = i the assignment cross = list[j] can be replaced with cross = j, making it possible to replace list with a bit vector.
However, this is not enough to bring the range to 264, because your implementation would require 261 bytes (2 exbibytes) of memory, so you need to optimize some more.
The next thing to notice is that you do not need to go up to N/2 when "crossing" the numbers: √N is sufficient (you should be able to prove this by thinking about the result of dividing a composite number by its divisors above √N). This brings memory requirements within your reach, because your "crossing" primes would fit in about 4 GB of memory.
Once you have an array of crossing primes, you can build a partial sieve for any range without keeping in memory all ranges that precede it. This is called the Segmented sieve. You can find details on it, along with a simple implementation, on the page of primesieve generator. Another advantage of this approach is that you can parallelize it, bringing the time down even further.
You can tweak the algorithm a bit to calculate the prime numbers in chunks.
Load a part of the array (as much as fits the memory), and in addition hold a list of all known prime numbers.
Whenever you load a chunk, first go through the already known prime numbers, and similar to the regular sieve, set all non primes as such.
Then, go over the array again, mark whatever you can, and add to the list the new prime numbers found.
When done, you'll have a list containing all your prime numbers.
I could see that the approach you are using is the basic implementation of Eratosthenes, that first stick out all the 2's multiple and then 3's multiple and so on.
But I have a better solution to the question. Actually, there is question on spoj PRINT. Please go through it and do check the constraints it follows. Below is my code snippet for this problem:
#include<stdio.h>
#include<math.h>
#include<cstdlib>
int num[46500] = {0},prime[5000],prime_index = -1;
int main() {
/* First, calculate the prime up-to the sqrt(N) (preferably greater than, but near to
sqrt(N) */
prime[++prime_index] = 2; int i,j,k;
for(i=3; i<216; i += 2) {
if(num[i] == 0) {
prime[++prime_index] = i;
for(j = i*i, k = 2*i; j<=46500; j += k) {
num[j] = 1;
}
}
}
for(; i<=46500; i+= 2) {
if(num[i] == 0) {
prime[++prime_index] = i;
}
}
int t; // Stands for number of test cases
scanf("%i",&t);
while(t--) {
bool arr[1000005] = {0}; int m,n,j,k;
scanf("%i%i",&m,&n);
if(m == 1)
m++;
if(m == 2 && m <= n) {
printf("2\n");
}
int sqt = sqrt(n) + 1;
for(i=0; i<=prime_index; i++) {
if(prime[i] > sqt) {
sqt = i;
break;
}
}
for(; m<=n && m <= prime[prime_index]; m++) {
if(m&1 && num[m] == 0) {
printf("%i\n",m);
}
}
if(m%2 == 0) {
m++;
}
for(i=1; i<=sqt; i++) {
j = (m%prime[i]) ? (m + prime[i] - m%prime[i]) : (m);
for(k=j; k<=n; k += prime[i]) {
arr[k-m] = 1;
}
}
for(i=0; i<=n-m; i += 2) {
if(!arr[i]) {
printf("%i\n",m+i);
}
}
printf("\n");
}
return 0;
}
I hope you got the point:
And, as you mentioned that your program is working fine up-to 10^7 but above it fails, it must be because you must be running out of the memory.
NOTE: I'm sharing my code only for knowledge purpose. Please, don't copy and paste it, until you get the point.

C: Program crashes before completing for loop

Hello Stackoverflow crew. I'm a very amateur C programmer and I'm working on a program that reads some input about wedding gifts, and then outputs information that includes the maximum gift value, the minimum gift value, the total average of the gift values, and the average of the gifts that were valued at x > 0. I've finished writing everything, but the program always seems to crash after the first loop. I've been looking at it for the past few hours, so I'm having issues finding what the error might be. Here is the code I have:
#include <stdio.h>
#include <stdlib.h>
int main() {
//Opens the file and creats a pointer for it.
FILE *ifp;
ifp = fopen("gifts.txt", "r");
//Declares the variables
int i, j, k, l, m, n, o, p, q, x, y;
int gift_sets, num_gifts, prices, max_value, max, avg_val, no_zero;
//Scans the file and assigns the first line to variable "gift_sets"
fscanf(ifp, "%d", &gift_sets);
//Begins a for loop that repeats based on the value of gift_sets
for (i = 0; i < gift_sets; i++) {
printf("Wedding Gifts #%d\n", i + 1);
printf("Gift Value\t Number of Gifts\n");
printf("----------\t ---------------\n");
//Scans the price values into the array prices[num_gifts]
fscanf(ifp, "%d", &num_gifts);
int prices[num_gifts];
//Creates a loop through the prices array
for (j = 0; j < num_gifts; j++){
fscanf(ifp, "%d", &prices[j]);
}
//Declares a frequency array
int freq[max + 1];
for (k = 0; k <= max; k++) {
freq[k] = 0;
}
for (l = 0; l < num_gifts; l++) {
freq[prices[l]]++;
}
for (m = 0; m < max + 1; m++) {
if (freq[m] > 0){
printf("%d\t%d",m, freq[m]);
}
}
printf("\n");
//Zeroes the variable "max_val."
int max_val = prices[0];
//Loops through the array to find the maximum gift value.
for (n = 0; n < num_gifts; n++){
if (prices[n] > max_value)
max_value = prices[n];
}
// Zeroes "min_val."
int min_val = prices[0];
//Finds the lowest value within the array.
for(o = 0; o < num_gifts; o++){
if(prices[o] !=0){
if(prices[o] < min_val){
min_val = prices[o];
}
}
}
//Calculates the total number of gifts.
double sum_gifts = 0;
for(p = 0; p < num_gifts; p++){
sum_gifts = sum_gifts + prices[p];
}
//Calculates the average value of all the gifts.
avg_val = (sum_gifts / num_gifts);
//find non zero average
double x = 0;
int y = 0;
for(q = 0; q < num_gifts; q++){
if (prices[q] != 0){
x += prices[q];
y++;
}
}
//Calculates the average value of the gifts, excluding the gifts valued zero.
int no_zero = x / y;
//Prints the maximum gift value.
printf("The maximum gift value is: $%d", max_value);
printf("\n");
//Prints the minimum gift value.
printf("The minimum gift value is: $%d\n", min_val);
//Prints the average of all the gifts.
printf("The average of all gifts was $%.2lf\n",avg_val);
//Prints the no zero average value of the gifts.
printf("The average of all non-zero gifts was $%.2lf",no_zero);
printf("\n\n\n");
}
return 0;
}
Thanks in advance for the help guys. As always, it's much appreciated.
EDIT: To further elaborate, the "crash" is a windows error "gifts.exe has stopped working" when executing the program. It does say at the bottom of the window that "Process returned -1073741819 <0xC0000005>"
When you declare the array with the num_gifts variable, it generates assembly instructions which allocate enough space on the stack to hold num_gifts integers. It does this at compile-time. Normally this wouldn't compile, but depending on the behavior of the ms c compiler, it could compile and assume whatever value is put in num_gifts by default (maybe 0, maybe something else) is the length. When you access it, it's possible that you're trying to access an array with zero elements, which could cause an access violation.
I'll tell you one thing you should do, straight away.
Check the return values from fscanf and its brethren. If, for some reason the scan fails, this will return less than you expect (it returns the number of items successfully scanned).
In that case, your data file is not what your code expects.
You should also be checking whether ifp is NULL - that could be the cause here since you blindly use it regardless.
One thing you'll find in IDEs is that you may not be in the directory you think you're in (specifically the one where gifts.txt is).
And, on top of that, max ill be set to an arbitrary value, so that int freq[max+1]; will give you an array of indeterminate size. If that size is less than the largest price, you'll be modifying memory beyond the end of the array with:
freq[prices[l]]++;
That's a definite no-no, "undefined behaviour" territory.
At least at first glance, it looks like you haven't initialized max before you (try to) use it to define the freq array.

Resources