Escaping loop whilst adding to dynamic array - C - c

Currently my program allows the user to enter 5 integers which are used to create an average number. This is set to five as after the fifth number is entered the loop is broken.
I am trying to implement a method which will let the user continue to add as many numbers as they like to an array from which i can then use to create an average without a limit on the amount of numbers that can be entered.
I have come across a few problems, firstly i cannot create an array which is dyamic as i have no idea how many numbers the user may wish to enter which means i can't give it a definitive size.
Secondly the way my program currently creates the average is by looping through the elements in the array and adding the consecutively to an integer, from which the the average is made. I cannot specify the limit for the loop to continue running if i cannot determine the array.
Hopefully my example explains this better.
#include <stdio.h>
#include <string.h>
void main()
{
int i = 0;
int arrayNum[5];
int temp = 1;
int anotherTemp = 0;
int answer = 0;
printf("Enter as many numbers as you like, when finished enter a negative number\n");
for(i = 0; i < 5; i++)
{
scanf("%d", &temp);
arrayNum[i] = temp;
anotherTemp = anotherTemp + arrayNum[i];
}
answer = anotherTemp / 5;
printf("Average of %d,%d,%d,%d,%d = %d",arrayNum[0],arrayNum[1],arrayNum[2],arrayNum[3],arrayNum[4],answer);
}
Although this may not be the best way to implement it, it does work when the amount of numbers are specified beforehand.
What would be the best way to get around this and allow the user to enter as many number as necessary?
Edit: Although i needed to use an array I have decided that it is not necessary as the solution is much simpler without being restricted to it.

In terms of code simplicity, you might want to check out the realloc() function; you can allocate an initial array of some size, and if the user enters too many numbers call realloc() to get yourself a bigger array and continue from there.
You don't, however, actually need to keep the numbers as you go along at all, at least if you only care about the average:
int input;
int sum = 0;
int count = 0;
int average;
while (1) {
scanf("%d", &input);
if (input < 0) {
break;
}
sum += input;
count++;
}
average = sum / count;

If you're trying to compute an average, then you don't need to save the numbers. Save yourself the work of worrying about the array. Simply accumulate (add) each number to a single total, count each number, then divide when you're done. Two variables are all that you need.
With this method, you aren't in any risk of overflowing your array, so you can use a while loop... while (temp != -1)

Basically you start with a dynamically allocated array with a fixed size, and then allocate a new array that is bigger (say, twice as big as initial size) and copy the stuff from the old array to the new one whenever you run out of space.
For the second part of the problem, keep a counter of the number of items the user entered and use it when averaging.
Something like this.

Use a dynamic array data structure, like Vector in Java (java.util.Vector).
You can implement such a dynamic array yourself easily:
allocate array of size N
as soon as you need more elements than N, allocate a new bigger array (e.g. with size N+10), copy the content of the old array into the new array and set your working reference to the new array and your array size variable N to the new size (e.g. N+10). Free the old array.

Related

Cycling through interval in C efficiently

I have dynamically allocated array consisting of a lot of numbers (200 000+) and I have to find out, if (and how many) these numbers are contained in given interval. There can be duplicates and all the numbers are in random order.
Example of numbers I get at the beginning:
{1,2,3,1484984,48941651,489416,1816,168189161,6484,8169181,9681916,121,231,684979,795641,231484891,...}
Given interval:
<2;150000>
I created a simple algorithm with 2 for loops cycling through all numbers:
for( int j = 0; j <= numberOfRepeats; j++){
for( int i = 0; i < arraySize; i++){
if(currentNumber == array[i]){
counter++;
}
}
currentNumber++;
}
printf(" -> %d\n", counter);
}
This algorithm is too slow for my task. Is there more efficient way for me to implement my solution? Could sorting the arrays by value help in this case / wouldn't that be too slow?
Example of working program:
{ 1, 7, 22, 4, 7, 5, 11, 9, 1 }
<4;7>
-> 4
The problem was simple as the single comment in my question answered it - there was no reason for second loop. Single loop could do it alone.
My changed code:
for(int i = 0; i <= arraySize-1; i++){
if(array[i] <= endOfInterval && array[i] >= startOfInterval){
counter++;
}
This algorithm is too slow for my task. Is there more efficient way for me to implement my solution? Could sorting the arrays by value help in this case / wouldn't that be too slow?
Of course, it is slow. A single pass algorithm to count the number of elements that are in the set should suffice, just count them in a single pass if they pass the test (be n[i] >= lower bound && be n[i] < upper bound or similar approach) will do the work.
Only in case you need to consider duplicates (e.g. not counting them) you will need to consider if you have already touched them or no. In that case, the sorting solution will be faster (a qsort(3) call is O(nlog(n)) against the O(nn) your double loop is doing, so it will run in an almost linear, then you make a second pass over the data (converting your complexity to O(nlog(n) + n), still lower than O(nn) for the large amount of data you have.
Sorting has the advantage that puts all the repeated key values together, so you have to consider only if the last element you read was the same as the one you are processing now, if it is different, then count it only if it is in the specified range.
One final note: Reading a set of 200,000 integers into an array to filter them, based on some criteria is normally a bad, non-scalable way to solve a problem. Your problem (select the elements that belong to a given interval) allow you for a scalable and better solution by streaming the problem (you read a number, check if it is in the interval, then output it, or count it, or whatever you like to do on it), without using a large amount of memory to hold them all before starting. That is far better way to solve a problem, as it allows you to read a true unbounded set of numbers (coming e.g. from a file) and producing an output based on that:
#include <stdio.h>
#define A (2)
#define B (150000)
int main()
{
int the_number;
size_t count = 0;
int res;
while ((res = scanf("%d", &the_number)) > 0) {
if (the_number >= A && the_number <= B)
count++;
}
printf("%zd numbers fitted in the range\n", count);
}
on this example you can give the program 1.0E26 numbers (assuming that you have an input file system large enough to hold a file this size) and your program will be able to handle it (you cannot create an array with capacity to hold 10^26 values)

How to solve a runtime error happening when I use a big size of static array

my development environment : visual studio
Now, I have to create a input file and print random numbers from 1 to 500000 without duplicating in the file. First, I considered that if I use a big size of local array, problems related to heap may happen. So, I tried to declare as a static array. Then, in main function, I put random numbers without overlapping in the array and wrote the numbers in input file accessing array elements. However, runtime errors(the continuous blinking of the cursor in the console window) continue to occur.
The source code is as follows.
#define SIZE 500000
int sort[500000];
int main()
{
FILE* input = NULL;
input = fopen("input.txt", "w");
if (sort != NULL)
{
srand((unsigned)time(NULL));
for (int i = 0; i < SIZE; i++)
{
sort[i] = (rand() % SIZE) + 1;
for (int j = 0; j < i; j++)
{
if (sort[i] == sort[j])
{
i--;
break;
}
}
}
for (int i = 0; i < SIZE; i++)
{
fprintf(input, "%d ", sort[i]);
}
fclose(input);
}
return 0;
}
When I tried to reduce the array size from 1 to 5000, it has been implemented. So, Carefully, I think it's a memory out phenomenon. Finally, I'd appreciate it if you could comment on how to solve this problem.
“First, I considered that if I use a big size of local array, problems related to heap may happen.”
That does not make any sense. Automatic local objects generally come from the stack, not the heap. (Also, “heap” is the wrong word; a heap is a particular kind of data structure, but the malloc family of routines may use other data structures for managing memory. This can be referred to simply as dynamically allocated memory or allocated memory.)
However, runtime errors(the continuous blinking of the cursor in the console window)…
Continuous blinking of the cursor is normal operation, not a run-time error. Perhaps you are trying to say your program continues executing without ever stopping.
#define SIZE 500000<br>
...
sort[i] = (rand() % SIZE) + 1;
The C standard only requires rand to generate numbers from 0 to 32767. Some implementations may provide more. However, if your implementation does not generate numbers up to 499,999, then it will never generate the numbers required to fill the array using this method.
Also, using % to reduce the rand result skews the distribution. For example, if we were reducing modulo 30,000, and rand generated numbers from 0 to 44,999, then rand() % 30000 would generate the numbers from 0 to 14,999 each two times out of every 45,000 and the numbers from 15,000 to 29,999 each one time out of every 45,000.
for (int j = 0; j < i; j++)
So this algorithm attempts to find new numbers by rejecting those that duplicate previous numbers. When working on the last of n numbers, the average number of tries is n, if the selection of random numbers is uniform. When working on the second-to-last number, the average is n/2. When working on the third-to-last, the average is n/3. So the average number of tries for all the numbers is n + n/2 + n/3 + n/4 + n/5 + … 1.
For 5000 elements, this sum is around 45,472.5. For 500,000 elements, it is around 6,849,790. So your program will average around 150 times the number of tries with 500,000 elements than with 5,000. However, each try also takes longer: For the first try, you check against zero prior elements for duplicates. For the second, you check against one prior element. For try n, you check against n−1 elements. So, for the last of 500,000 elements, you check against 499,999 elements, and, on average, you have to repeat this 500,000 times. So the last try takes around 500,000•499,999 = 249,999,500,000 units of work.
Refining this estimate, for each selection i, a successful attempt that gets completely through the loop of checking requires checking against all i−1 prior numbers. An unsuccessful attempt will average going halfway through the prior numbers. So, for selection i, there is one successful check of i−1 numbers and, on average, n/(n+1−i) unsuccessful checks of an average of (i−1)/2 numbers.
For 5,000 numbers, the average number of checks will be around 107,455,347. For 500,000 numbers, the average will be around 1,649,951,055,183. Thus, your program with 500,000 numbers takes more than 15,000 times as long than with 5,000 numbers.
When I tried to reduce the array size from 1 to 5000, it has been implemented.
I think you mean that with an array size of 5,000, the program completes execution in a short amount of time?
So, Carefully, I think it's a memory out phenomenon.
No, there is no memory issue here. Modern general-purpose computer systems easily handle static arrays of 500,000 int.
Finally, I'd appreciate it if you could comment on how to solve this problem.
Use a Fischer-Yates shuffle: Fill the array A with integers from 1 to SIZE. Set a counter, say d to the number of selections completed so far, initially zero. Then pick a random number r from 1 to SIZE-d. Move the number in that position of the array to the front by swapping A[r] with A[d]. Then increment d. Repeat until d reaches SIZE-1.
This will swap a random element of the initial array into A[0], then a random element from those remaining into A[1], then a random element from those remaining into A[2], and so on. (We stop when d reaches SIZE-1 rather than when it reaches SIZE because, once d reaches SIZE-1, there is only one more selection to make, but there is also only one number left, and it is already in the last position in the array.)

2-D Array in C storing user inputs

total C newbie here. Thanks for any help beforehand.
I am required to write a code which has the following properties:
Asking user to input the number of rows and columns they would like in their 2-D array
creates a 2-D array with that many rows and columns for storing integers
fills the array with random numbers between 1 and 1000
outputs the largest number in the array
This is where I could go for now:
#include <stdio.h>
int main(){
int rows;
int columns;
scanf("%d", &rows);
scanf("%d", &columns);
}
What should I do?
Sorry for the very open question, I am stuck and don't know what to do. A guideline will be perfect. Thanks :)
EDIT:
Thanks for the guideline, here is how I solved it:
SOLUTION:
#include <stdio.h>
#include <time.h>
int main () {
//Declare variables
int a,b,k,l,big,z[100][100];
//Ask user input
printf("ENTER ROWS & COLUMNS\n");
scanf("%d\n%d", &a, &b);
//Randomize array values
srand(time(NULL));
big = 1;
for (k=0;k<a;k++){
for(l=0;l<b;l++){
z[k][l]=rand()%1000 + 1;
if(z[k][l]>big) big=z[k][l];
printf("%d\t", z[k][l]);
}
printf("\n");
}
//Print biggest number
printf("\nBIGGEST NUMBER IN THE ARRAY: %d", big);
return 0;
}
A guideline will be perfect.
okay... let's go...
Asking user to input the number of rows and columns they would like in their 2-D array
Use scanf or better fgets followed by sscanf
creates a 2-D array with that many rows and columns for storing integers
Use malloc (search the net for "how to correctly malloc a 2D array" or simply see Correctly allocating multi-dimensional arrays)
fills the array with random numbers between 1 and 1000
Use srand, rand and the % operator
outputs the largest number in the array
Iterate all elements of the array and compare against a running max.
C does not support natively 2D arrays, you need to allocate an array of arrays. You don't know the size in advance, so you need to allocate the arrays memory dynamically using malloc.
For generating random numbers, you could use rand, but you need to set a seed first for the sequence of the pseudo-random integers using srand to get (possibly) a different number on every execution, or you can use rand_r to do the both operation with one function. Note that rand generate a random number between 0 and RAND_MAX, you need to use a trick with the modulus operator % to generate a random number in a specific range [min, max].
min + (rand() % (max - min + 1))
You can iterate over the arrays with two loops, to get the maximum number.
To know how to use these function, you can read the man pages: malloc rand
As a side note, you don't really need the 2D array to get the maximum number, you can calculate it directly with allocating any additional memory.
Your solution will work, but it's limited to 100 columns and 100 rows. If for instance the user enters higher numbers, your code will mostly crash. One solution is to validate the input and refuse numbers above 100 if you don't want to handle dynamic memory allocation, but in real world that is very much rare and dynamic memory allocation is a necessary.
You shouldn't name your variables with one-character names, especially if they live long. A good descriptive name like columnsNumber is preferred.

dynamic memory allocation and dynamic array

I need to write a program, that will ask a user to enter a number of how many ints they would like to enter.. so the output would look like
Enter number of Ints (must be greater then 1)
and they would input a number between 2 - infinity (if they really wanted to go that far)
at that point i would scanf that number and set it to a variable
now with that number, i want to run a for loop to ask them to begin entering their Ints
for (count = 0; count < numofInts; count++)
{
printf(" Enter an integer: ");
scanf("%d", &Number);
}
the problem im having is that i need to make sure that it records every number that they enter, so i need to have those values stored to an array, but the number of elements of the array must be dynamic so that it can change depending on the numofInts, I'm supposed to use Malloc() to create a dynamic memory allocated space, and i understand that it creates a variable with a memory space of what ever i set the malloc to, but i don't know how to store a series a variables to that space, and then call them back as i need them.
The end result of the program is supposed to take a number like 123456789, and cycle through the number storing the intergers as the "largest" int, and then spit out which int is the largest, so like x = 1234567890, x % 10, x = 0, largest = x, x / 10, x % 10, x = 9, if x > largest, largest = x, and just loop that till it cycles through the whole number, and store that number at the very end. I have that part down, but because i have to take a series of numbers and run this loop for all of those numbers, i need to be able to store and recall those values and place them in the loop to be able to store the largest digits of those numbers
any help with this problem would be greatly appreciated, i just have not been able to figure out how to use malloc or to create a dynamic array and most of the tutorials ive read online or watched from youtube are about C++ and i need to do this with just C...
http://pastebin.com/PZyvEQ4J
what i have so far
After you read numInts, you allocate the array like so:
int* arr = malloc(numInts*sizeof(int));
Now you populate the array with your already existing function and assigning the values read to the array.
I'm not going to give you a full solution, since this is homework and wouldn't help you, but you access the i'th element of the array with the [] operator:
arr[i];
Learn more about pointers and calloc

How to find a certain number in an Array C Programming?

If I have an array and I need to display how many times the number '12' is created. I'm using a function to go about this. What resources should I look into to find how to exactly tease out this one number and display how many times it is in the array/list? Any help would be greatly appreciated.
You can do it by walking through the array, while keeping a tally.
The tally starts at 0, and every time you reach the number you want to track, add one to it. When you're done, the tally contains the number of times the number appeared.
Your function definition would probably look something like this:
int count_elements(int pElement, int pArray[], size_t pSize);
Simply create a counter variable, and examine each element in the array in a loop, incrementing the counter variable every time an element is equal to 12.
If you have a plain C-array, you have to iterate over all elements in a loop and count yourself with a variable.
int arr[20];
int twelves = 0;
int i;
/* fill here your array */
/* I assume your array is fully filled, otherwise change the sizeof to the real length */
for(i = 0; i < sizeof(arr)/sizeof(int);++i) {
if(arr[i] == 12) ++twelves;
}
After this, the variable twelves will contain the number of twelves in the array.

Resources