Use less pointers - c

I'm trying to write a program that calculates the cumulative sum of a dynamically allocated vector filled with random values ​​using only pointers(without any other type of variable).I think I managed to do that but now I want an improvement:
-I want a maximum of two variables used and without malloc(the size of the vector should be fixed
and not be read by the user,for example the number of items collected should be 10). Some suggestions?
my code:
#include <stdio.h>
#include <malloc.h>
#include <time.h>
int main() {
int *n=malloc(sizeof(int)); // memory allocation for required variables
int *sum=malloc(sizeof(int));
int *a;
srow(time(NULL));
printf("Define the size of array A \n");
scanf("%d", n);
if (*n < 1) { // the size must be > 0
puts("Invalid size");
return 1;
}
printf("Generates random values... \n");
a=malloc(sizeof(int) * *n); //allocates array of int's
*sum=0; //reset the sum
while ((*n)--) {
a[*n]= row() % 1000 + 1; // add random numbers in the array from 1 to 1000
*sum += a[*n]; //add values
}
printf("The sum of all the elements in the array=%d\n", *sum);
return 0;
}

Recursion is an academic curiosity. In real world computing, you want to avoid it like the plague. I mention this because there's an answer here that would depend on recursion to ensure that we're only creating 'two variables'. We're not really, since all variables are just stack objects, and we're abusing the stack to avoid creating variables. Anyway, with newer versions of C you can define stack arrays using the array notation like such:
int array[count];
And you can avoid pointers completely this way. Out two 'variables' are thus array and count, as shown below.
int main() {
// Initialize all variables to known values
int count = 0;
// Seed the random number generator
srand(time(NULL));
printf("Define the size of array A \n");
scanf("%d", &count);
// the size must be > 0
if (count < 1) {
printf("Invalid size\n");
} else {
int array[count];
printf("Generating %d random values...\n", count);
fill_array( array, count );
// Sum the array of values
sum_array( array, count );
printf("The sum of all the elements in the array=%d\n", sum);
}
}
To have the function fill_array not use any variables, we'll use a do-while loop.
void fill_array(int *array, int size) {
do array[--size] = rand() % 1000;
while (size != -1);
}
Finally, we'll use recursion to get our sum, also without any new variables.
int sum_array(int* array, int size) {
if(!size) return 0;
else return sum_array(array, size - 1) + array[size - 1];
}

Related

Unexpected output of a growing dynamic array

I am attempting to create a dynamic array that will grow in size if needed, as I don't know how large the array will actually be. My code seems to work until the 8th element of the array where I start to see very large incorrect values that I did not enter. Not sure why this is happening.
#include <stdio.h>
#include <stdlib.h>
int main (int argc, char** argv)
{
int val;
int userInput;
int* arr;
int size = 1;
int arrIndex = 0;
arr = (int*) malloc(sizeof(int) * size);
/* prompt the user for input */
printf ("Enter in a list of numbers to be stored in a dynamic array.\n");
printf ("End the list with the terminal value of -999\n");
/* loop until the user enters -999 */
scanf ("%d", &val);
while (val != -999)
{
if (arrIndex >= size)
{
size++;
}
arr[arrIndex] = val;
arrIndex++;
/* get next value */
scanf("%d", &val);
}
int j = 0;
for(j = 0; j < size ; j++)
{
printf("%d \t", arr[j]);
}
}
The size of the array remains 1 and doesn't increase while incrementing size variable.
Your code worked until 8th element because adjacent memory after the array upto 7th element must be free.
In C array index out of bound is not checked and it is programmers responibility.
if you want to increase or decrease size of array you can use realloc inside while loop:
arr=(int*)realloc(arr,sizeof(int)*size);
Also Correct this if condition in your code initially arrayindex is 0 and size is 1 which results in false.
if (arrIndex >= size)
{
size++;
}

saving data from an array in C

I should mention that I am in my 1st 2 weeks of an intro to programming class before people get too crazy with answers.
Using this array as an example,
int scores[30] = {90,85,100,50,50,85,60,70,55,55,80,95,70,60,95,
80,100,75,70,95,90,90,70,95,50,65,85,95,100,65}
I am trying to parse through it to create 2 new parallel arrays to use later. The idea is to make one array that holds the "scores" and one that holds the "occurrences" of each score. I end up compiling with no errors however during run time it crashes.
void frequency(int scores[], int max){
int i, x=0, temp=0, count=0, sum=0, mode=0;
int score[sum]; //unknown length of array, sum gets added after the while loop
int freq[sum];
printf("score\tfrequency\n");
printf("-----\t---------\n");
fprintf(fp, "score\tfrequency\n");
fprintf(fp, "-----\t---------\n");
for (i = 0; i < max; ++i){
while (scores[i]==scores[x]){
x++;
count++;
sum++;
temp = x-1;
if(scores[i] != scores[x]){
//printf(" %d\t %d\n",scores[i], count);
freq[i] = count;
score[i] = scores[i];
count=0;
i=temp;
x=temp+1;
sum++;
printf("%d\t%d", score[i], freq[i]);
fprintf(fp, "%d\t%d", score[i], freq[i]);
}
}
}
}
This part:
int i, x=0, temp=0, count=0, sum=0, mode=0;
int score[sum];
int freq[sum];
looks wrong.
You set sumto zero and then use it for the array dimension. Did you mean to do:
sum = max;
I end up compiling with no errors however during run time it crashes.
Reason:
The reason why your program crashes is because you have not allocated sufficient memory to the arrays that you use int the frequency() function
void frequency(int scores[], int max){
int i, x=0, temp=0, count=0, sum=0, mode=0;
int score[sum];
int freq[sum];
Solution:
So, is there a way to provide memory during run time according to requirements or change memory size of blocks during compile time?
Yes, that's the very reason why Dynamic memory allocation is used.... though you send a fixed array to the frequency() function in your code, the function I've provided works for any integer array you send..
Here I've provided code in which
one array stores all the unique scores
and other array stores number of occurrences of each score
I've done this using dynamic memory allocation.. I think it's easy to understand if you have basic understanding of dynamic memory allocation functions.. if you have any doubts, ask me through the comments :) and by the way I've assumed your main function to be :
int main()
{
int scores[30] = {90,85,100,50,50,85,60,70,55,55,80,95,70,60,95,
80,100,75,70,95,90,90,70,95,50,65,85,95,100,65};
frequency(scores,30);
return 0;
}
Code:
#include <stdio.h>
#include <stdlib.h>
void frequency(int scores[], int max);
int main()
{
int scores[30] = {90,85,100,50,50,85,60,70,55,55,80,95,70,60,95,
80,100,75,70,95,90,90,70,95,50,65,85,95,100,65};
frequency(scores,30);
return 0;
}
void frequency(int scores[], int max)
{
int i,j,count=0,flag=0,occur=0;
int *score=malloc(sizeof(int));
if(malloc==NULL)
{
printf("memory allocation failed");
exit(1);
//it's good to check if memory allocated was successful or not
//I've avoided it for further allocations,to decrease the size of post :)
}
int *freq=malloc(sizeof(int));
printf("score\tfrequency\n");
printf("-----\t---------\n");
//building array which has only scores
for(i=0;i<max;i++)
{
if(count==0) //first time
{
score=realloc(score,(count+1)*sizeof(int));
//increasing size of array by 1*sizeof(int)
score[count]=scores[i];
count++;
}//first one requires no checking whether it's repeated or not
else
{
flag=0; //resetting flag value
for(j=0;j<count;j++)
{
if(scores[i]==score[j])
{
flag=1; //
break;
}
}
if(flag==0) // if not repeated need to add new element
{
score=realloc(score,(count+1)*sizeof(int));
score[count]=scores[i];
count++;
}
}
}
//allocating memory for frequency array
freq=realloc(freq,count*sizeof(int));
//building array which has frequency of each score
for(i=0;i<count;i++)
{
occur=0;
for(j=0;j<max;j++)
{
if(score[i]==scores[j])
occur++;
}
freq[i]=occur;
}
for(i=0;i<count;i++) //printing output
printf("\n %d\t %d\n",score[i],freq[i]);
free(score); //freeing the blocks
free(freq);
}
My approach is quite simple to understand
first I create array score which creates extra memory whenever it encounters unique elements and stores in it
and then I check occurrences for each of the element of score array in the scores array and store them in freq array.
Output:
score frequency
----- ---------
90 3
85 3
100 3
50 3
60 2
70 4
55 2
80 2
95 5
75 1
65 2
I hope this is what you were trying to achieve :)

Correctly passing an array from a function

I have some code to generate an array of size [user_input] in a function called array_generator, using size of array from scanf in main(), and then filling it with the numbers 0 to user_input (0, 1, 2, 3, if user input is 4). The array fills correctly as printf prints
`The array contains the value 1`
`The array contains the value 2`
`The array contains the value 3`, etc.
However when I pass the array to main and printf the array values I get equal statements filled with garbage numbers. I'm also 90% sure I have been passing the arrays and pointers incorrectly (new to them).
The code is below:
#include <stdio.h>
int *array_generator(int number_songs);
int main(void)
{
int input;
int *p;
int i;
int x;
printf("Enter number of songs wanted in random playlist: ");
scanf("%d", &input);
p = array_generator(input);
x = *p;
for (i = 0; i < input; i++)
{
printf("The array contains the values %d\n", x);
}
return 0;
}
int *array_generator(int n)
{
int a[n];
int *p;
int i;
for (i = 0; i < n; i++)
{
a[i] = i;
printf("The array contains the values %d\n", i);
}
return p = &a[n];
}
One simple solution is to define an array which is bigger than the largest list of songs reasonably possible. For example, since you print every entry, more than a few hundred are not reasonable. On a modern computer space is abundant. You would have a define for the max size on top of the prog, or later in some header:
#define MAX_SONGLIST_LEN 1000
The array can be global, or it can be static inside the function. Let's make it static because you want the function to return the address.
The change is minimal. Just say
static int a[MAX_SONGLIST_LEN];
You may want to change the loop and check for the max length as well:
for (i = 0; i < input && i < MAX_SONGLIST_LEN; i++)
inside array_generator() and main(). You also may want to inform your users about the maximum, and catch numbers which are too large. (You don't do any error handling of user input anyway -- what happens if the user enters a letter instead of a number? Look into the return value of scanf().)
The static array's life time is the lifetime of the program. It will be initialized to all zeroes by the way. If you want to randomly initialize it look at the rand() function.
You are correct in that you are using pointers wrong. The code below preforms the function that you want...
#include <stdio.h>
void array_generator(int n, int arr[]) {
for (int i = 0; i < n; i++) {
arr[i] = i;//array values
//printf("The array contains the values %d\n", i);
}
}
int main() {
int input;
printf("Enter number of songs wanted in random playlist: ");
scanf("%d", &input);
int array[input];//declare array with length of input
array_generator(input, array);
for(int i=0; i<sizeof(array)/sizeof(array[0]); i++) {//input could also be used at the limit to the for loop
printf("%d", array[i]);
}
printf("\n");
return 0;
}
What you are doing is you are over complicating your code. The first thing you do is you create a function and try to make it return an array. This is not necessary. All you need to do is pass a pointer to the array and all edits to the array will be made on the same scope as the array was declared on.
You also mentioned that you want to find the size of an array. This can be done with array *a of any type and sizeof(a)/sizeof(a[0]). This works by returning the number of bytes used by the array divided by the number of bytes used by the first element in the array.
One more thing that you have that you don't need is x = *p;. when you do this, you are essentially doing this x=*p=array_gen(input);
More information on pointers in C can be found here.

Learning c programming - passing array into function

May i know why is int count, biggest = -12000;? Why must it be -12000 and I do not understand this statement biggest = -12000
If I put biggest = 10000, it can still compile. Appreciate your advise as I am currently learning c programming. Can you please understand as clearly as possible? Thanks in advance!
#include <stdio.h>
#define MAX 10
int array[MAX], count;
int largest(int x[], int y);
int main()
{
/* Input MAX values from the keyboard. */
for (count = 0; count < MAX; count++)
{
printf("\nEnter an integer value:\n ");
scanf_s("&d", &array[count]);
}
/* Call the function and display the return value. */
printf("\n\nLargest value = %d\n", largest(array, MAX));
return 0;
}
/* Function largest() returns the largest value in an integer array */
int largest(int x[], int y)
{
int count, biggest = -12000;
for (count = 0; count < y; count++)
{
if (x[count] > biggest)
biggest = x[count];
}
getchar();
return biggest;
}
If you want to find the largest number in an array you compare all elements against the currently 'biggest' value. Whenever you find a value that's larger you put it in biggest.
To make sure that you find the proper value you must initialize biggest to a sensible value.
Your code initializes biggest to -12000, and therefore it will fail if all elements in the array have values lower than -12000 (unless you know something about the values in the array, but then that should be mentioned in a comment, to explain the unusual initialization value).
Sure it will compile, but that does not mean it will work correctly.
You could initialize biggest to the lowest integer value possible (INT_MIN),
int largest(int x[], int y)
{
int count, biggest = INT_MIN; // lowest integer value possible
for (count = 0; count < y; count++)
{
but a smart trick is to initialize it to the first value in your array.
int largest(int x[], int y)
{
int count, biggest = x[0]; // first value in your array
for (count = 1; count < y; count++) // starting with 2nd element
{
You can work this all out on a piece of paper with e.g. 3 array values, or step through your debugger and see what values the respective variables get.
Instead of assigning the value in starting to biggest, you can compare two elements of the array and after comparing it store maximum value in biggest and after it swap the numbers if greater it would be good approach.
if you use like:
if(x[count]>x[count+1])
biggest=x[count];
x[count]=x[count+1];
x[count+1]=biggest;
code above line in loop.
What you tried assigned a very high value to biggest. It's not a worthy idea.

exceeding 500000 with the method of Erastosthenes

i got a problem which i can't solve
I want to know all prime numbers below a given limit x. Allowing me to enter x and calculate the prime numbers using the method of Erastosthenes. Displaying the result on the screen and saving it to a text file.
Calculating the primenumbers below the x, printing them and saving them to a text file worked, the only problem i have is that x can't exceed 500000
could you guys help me?
#include <stdio.h>
#include <math.h>
void sieve(long x, int primes[]);
main()
{
long i;
long x=500000;
int v[x];
printf("give a x\n");
scanf("%d",&x);
FILE *fp;
fp = fopen("primes.txt", "w");
sieve(x, v);
for (i=0;i<x;i++)
{
if (v[i] == 1)
{
printf("\n%d",i);
fprintf(fp, "%d\n",i);
}
}
fclose(fp);
}
void sieve(long x, int primes[])
{
int i;
int j;
for (i=0;i<x;i++)
{
primes[i]=1; // we initialize the sieve list to all 1's (True)
primes[0]=0,primes[1]=0; // Set the first two numbers (0 and 1) to 0 (False)
}
for (i=2;i<sqrt(x);i++) // loop through all the numbers up to the sqrt(n)
{
for (j=i*i;j<x;j+=i) // mark off each factor of i by setting it to 0 (False)
{
primes[j] = 0;
}
}
}
You will be able to handle four times as many values by declaring char v [500000] instead of int v [100000].
You can handle eight times more values by declaring unsigned char v [500000] and using only a single bit for each prime number. This makes the code a bit more complicated.
You can handle twice as many values by having a sieve for odd numbers only. Since 2 is the only even prime number, there is no point keeping them in the sieve.
Since memory for local variables in a function is often quite limited, you can handle many more values by using a static array.
Allocating v as an array of int is wasteful, and making it a local array is risky, stack space being limited. If the array becomes large enough to exceed available stack space, the program will invoke undefined behaviour and likely crash.
While there are ways to improve the efficiency of the sieve by changing the sieve array to an array of bits containing only odd numbers or fewer numbers (6n-1 and 6n+1 is a good trick), you can still improve the efficiency of your simplistic approach by a factor of 10 with easy changes:
fix primes[0] and primes[1] outside the loop,
clear even offsets of prime except the first and only scan odd numbers,
use integer arithmetic for the outer loop limit,
ignore numbers that are already known to be composite,
only check off odd multiples of i.
Here is an improved version:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
void sieve(long x, unsigned char primes[]) {
long i, j;
for (i = 0; i < x; i++) {
primes[i] = i & 1;
}
primes[1] = 0;
primes[2] = 1;
/* loop through all odd numbers up to the sqrt(x) */
for (i = 3; (j = i * i) < x; i += 2) {
/* skip composite numbers */
if (primes[i] == 0)
continue;
/* mark each odd multiple of i as composite */
for (; j < x; j += i + i) {
primes[j] = 0;
}
}
}
int main(int argc, char *argv[]) {
long i, x, count;
int do_count = 0;
unsigned char *v;
if (argc > 1) {
x = strtol(argv[1], NULL, 0);
} else {
printf("enter x: ");
if (scanf("%ld", &x) != 1)
return 1;
}
if (x < 0) {
x = -x;
do_count = 1;
}
v = malloc(x);
if (v == NULL) {
printf("Not enough memory\n");
return 1;
}
sieve(x, v);
if (do_count) {
for (count = i = 0; i < x; i++) {
count += v[i];
}
printf("%ld\n", count);
} else {
for (i = 0; i < x; i++) {
if (v[i] == 1) {
printf("%ld\n", i);
}
}
}
free(v);
return 0;
}
I believe the problem you are having is allocating an array of int if more than 500000 elements on the stack. This is not an efficient way, to use an array where the element is the number and the value indicates whether it is prime or not. If you want to do this, at least use bool, not int as this should only be 1 byte, not 4.
Also notice this
for (i=0;i<x;i++)
{
primes[i]=1; // we initialize the sieve list to all 1's (True)
primes[0]=0,primes[1]=0; // Set the first two numbers (0 and 1) to 0 (False)
}
You are reassigning the first two elements in each loop. Take it out of the loop.
You are initializing x to be 500000, then creating an array with x elements, thus it will have 500000 elements. You are then reading in x. The array will not change size when the value of x changes - it is fixed at 500000 elements, the value of x when you created the array. You want something like this:
long x=500000;
printf("give a x\n");
scanf("%d",&x);
int *v = new int[x];
This fixes your fixed size array issue, and also gets it off the stack and into the heap which will allow you to allocate more space. It should work up to the limit of the memory you have available.

Resources