How compiler works with arrays? - c

I am writing a code to find the factor of the user given number. And then I want to store all the factors in an array. I created two functions, factors and insert_element. factors will find the factor and insert_element will store the factor in array as loop continues. When i call insert_element function form factors it shows me an error like warning: passing argument 1 of ‘insert_element’ from incompatible pointer type [-Wincompatible-pointer-types]. I have no idea what this means and how it occurred as I am new at C language. I would like to know how a bit about how compiler works with array along with how this error occurred
I am extremely SORRY if the question title and the question body seems to be misleading..
Here's my code below:
// PROGRAME TO FIND FACTORS OF GIVEN NUMBER"
#include <stdio.h>
void insert_element(int *factor_array[], int *base_divisor, int *index_of_array_elements)
//I heve used * because i want to ruturn more then one thing
{
*factor_array[*index_of_array_elements] = *base_divisor;
*index_of_array_elements++;
}
void factors(int number)
// I dont know if I want to return something or not so i kept it of type void
{
int base_divisor = 2, factor_array[50], index_of_array_elements = 0;
// base_divisor starts dividing given number from 2
while (number != 1)
{
if (number % base_divisor==0) //If remainder is zero then only devide number by base_divisor
{
number = number / base_divisor;
}
else //If remainder is not zero then base_divisor will be increase by 1.
{
base_divisor++;
}
// calling the function to insert element in array
insert_element(&factor_array[50], &base_divisor, &index_of_array_elements);
}
//i dont know why i did this but error is not caused by this.
printf("%ls", factor_array);
}
int main()
{
int number;
printf("\nPROGRAME TO FIND FACTORS OF GIVEN NUMBER\n\n");
printf("Enter the number to find factor: ");
scanf("%d", &number);
factors(number);
}

As written, the code in your post is outputting values that are not always factors. Only during the final iteration of the loop is the value for factor_array (if stored correctly) a quotient and a factor, which of course should also mean it is prime.
The following example, for simplification removes one function, and modifies the prototype of the remaining function to take a struct array argument. The struct itself contains values for quotient, factor, base. The code is also commented to explain some of the modification. In particular I hope this will help you to understand how to pass an array as a function argument, and how to use a loop to output the values in an array.
typedef struct {
long long factor;
long long quotient;
long long base;
}elements_s;
elements_s factor_array[50] = {{0}};
//REMOVED as all the work done here is moved to it's calling function
// void insert_element(size_t arr_size int *factor_array[], int *base_divisor, int *index_of_array_elements)
////I heve used * because i want to ruturn more then one thing
//{
//
// *factor_array[*index_of_array_elements] = *base_divisor;
// *index_of_array_elements++;
//
//
//}
void factors(long long number, size_t size, elements_s arr[size])//changed to pass container for results.
// I dont know if I want to return something or not so i kept it of type void
{
long long base_divisor = 2, /**factor_array[50],*/ index_of_array_elements = 0;//factor_array replaced by struct array
arr[index_of_array_elements].factor = 1;//fill array here, no need to send via function
arr[index_of_array_elements].quotient = number;
arr[index_of_array_elements].base = base_divisor;
int i=0;
// base_divisor starts dividing given number from 2
while (number != 1 && base_divisor < LLONG_MAX )
{
if (number % base_divisor==0) //If remainder is zero then only devide number by base_divisor
{
index_of_array_elements++;//index array index
number = number / base_divisor;
arr[index_of_array_elements].factor = base_divisor;//fill array here, no need to send via function
arr[index_of_array_elements].quotient = number;//fill array here, no need to send via function
arr[index_of_array_elements].base = base_divisor;//fill array here, no need to send via function
}
else //If remainder is not zero then base_divisor will be increase by 1.
{
base_divisor++;
}
//REMOVED for simplification of example (Not needed)
// calling the function to insert element in array
//insert_element(&factor_array[50], &base_divisor, &index_of_array_elements);
//insert_element(&factor_array, &base_divisor, &index_of_array_elements);
}
//i dont know why i did this but error is not caused by this.
for(i = 0;i < index_of_array_elements-1; i++)//putting into loop so all populated element of array are output
{
printf("quotient:%lld\nfactor:%lld\n", factor_array[i].quotient,factor_array[i].factor);//using %d for int
}
printf("base divisor:%lld\nfactor and quotient:%lld\nfactor:%lld\n", factor_array[i].base, factor_array[i].quotient,factor_array[i].factor);//using %d for int
}
int main(void)//this is a minumum signature for main. Anything less is not portable.
{
long long number = 0; //allows larger values up to 9223372036854775807 (LLONG_MAX)
//int factor_array[50] = {0};
size_t size = sizeof factor_array/sizeof *factor_array;
printf("\nPROGRAME TO FIND [prime] FACTORS OF GIVEN NUMBER\n\n");
printf("Enter the number to find factor...\n");
scanf("%lld", &number);//format specifier changed to accomodate larger type
factors(number, size, factor_array);//factor_array contains all the results here,
// so prinf could be used here if index were
// also passed as argument
return 0;//int main(void) requires this statement
}
Example run for value: 1234567890: (multiply all factors to test for input)

Related

Totally unexpected output when trying to compute the average using arrays

I am trying to compute the average after reading in the data from a text file of int type.The program compiles fine. clang -std=gnu11 -Weverything -g3 -pedantic -g3 -O3 -lm average_weight_of_elephant_seals.c -o average_weight_of_elephant_seals
Suppose I want to compute the average weight of 2000 seals,the expected output is 6838.848152 but I get 1710.566467.I have no idea how to make sense of GDB yet.
Could someone please point out where have I have gone wrong?
/* The following program demonstrates the usage of fscan to read in a set of integer data into a file and then computes the sum followed by the average.
* The computation shall be encapsulated in a function and then be called in the main routine
*/
#include <stdio.h>
#define MAXSIZE 5000 /* Macro definition to pre-define the size of the array */
double average_weight(int count, int weights_array[]);
int main(void)
{
int number_of_seals;
int weights_array[MAXSIZE];
printf("Enter the number of seals: \n");
scanf("%i", &number_of_seals);
printf("Their average weight is %lf\n", average_weight(number_of_seals, &weights_array[number_of_seals]));
return 0;
}
double average_weight(int count, int weights_array[])
{
/* Variable declaration and initialization
* Note the use of the FILE data type */
int weight;
int sum = 0;
FILE *elephant_seal_data = fopen("elephant_seal_data.txt", "r");
if (elephant_seal_data == NULL)
{
return -1;
}
/* FEOF function to determine if EOF has been reached or not */
while (!feof(elephant_seal_data))
{
fscanf(elephant_seal_data, "%i", &weight);
weights_array[count++] = weight;
sum += weight;
count++;
}
double average_weight = (double)sum / (double)count;
fclose(elephant_seal_data);
return average_weight;
}
printf("Their average weight is %lf\n", average_weight(number_of_seals, &weights_array[number_of_seals]));
The code passes a pointer to a position into the array for no apparent reason, and does not check if number_of_seals * 2 is less than MAXSIZE so may overflow the array. But the array isn't needed for this calculation anyway.
weights_array[count++] = weight;
sum += weight;
count++;
The code is writing to the array not reading it. The array is not needed for this calculation.
The code increments count twice, so the average will be out by a factor of two, and alternate locations in the array will have undefined values in them.
There are 2 stupid mistakes in your code, a nastier one, and a risk.
First the stupid ones:
You pass count to the function and increment that value twice per each value in the file. If the initialy given value was correct, you end with a count 3 times too big. You should not pass count to the function but compute it there.
You use a wrong syntax to pass an array: you are expected to pass a pointer to its first element.
Now the nasty one: while Why is “while ( !feof (file) )” always wrong? is indeed a FAQ, is is still a common thing in beginners code...
feof only returns true after a read operation returned an error. Let us examine what happens for the last value. It is read and correctly processed once. feof still returns false (no error so far) so your code re-enters the loop. scanf reaches the end of file and returns 0 (what your code ignores) but does not change the values => the last value will be processed twice. Never ever use while (!feof(...
And finally the risk.
You are summing value into an integer. Even if the average will easily fit there, if you had larger value and a very high number of them, you could get an integer overflow. The recommended way it to sum into a larger type (double?) and if possible use a guess to limit the cumulative error: average(qty-guess) + guess is indeed average(quantity), but the computed sum can be much lower, limiting the cumulative error when using floating point values or preventing overflow when using integer ones. From the number of seals and the expected average there should be no problem here so a guess is useless, but remember that for a different use case...
Last but not least, main is expected to be declared as int main() if you do not care for additional parameters but never int main(void)
Code could become:
/* The following program demonstrates the usage of fscan to read in a set of integer data into a file and then computes the sum followed by the average.
* The computation shall be encapsulated in a function and then be called in the main routine
*/
#include <stdio.h>
#define MAXSIZE 5000 /* Macro definition to pre-define the size of the array */
double average_weight(int* count, int weights_array[]);
int main()
{
int number_of_seals;
int weights_array[MAXSIZE];
double weight = average_weight(&number_of_seals, weights_array);
printf("Their number is %d and their average weight is %lf\n", number_of_seals, weight);
return 0;
}
double average_weight(int* count, int weights_array[])
{
/* Variable declaration and initialization
* Note the use of the FILE data type */
int weight;
int sum = 0;
FILE* elephant_seal_data = fopen("elephant_seal_data.txt", "r");
if (elephant_seal_data == NULL)
{
return -1;
}
*count = 0;
/* FEOF function to determine if EOF has been reached or not */
for(int i=0; i<MAXSIZE; i++) // never process more than the array size
{
if (1 != fscanf(elephant_seal_data, "%i", &weight)) {
break; // immediately stop at end of file
}
weights_array[(* count)++] = weight;
sum += weight;
}
double average_weight = (double)sum / (double)*count;
fclose(elephant_seal_data);
return average_weight;
}
I have kept your general program structure unchanged, but IMHO, you are expected to first read the data into an array, and then pass that populated array along with its count to an average function. Just split your current function into 2 steps.
You have sent the number of counts to use in the array which is great, since the function does not know the length of the weights_array. But you are not using it properly.
I'd suggest you to:
Use count to limit the number of loops based on how many data you want.
Do not change/reassign the value of count. Since this number is crucial to calculate the average. Create some other variable to do the task.
So here is how I slightly modified your code to bring those changes. I assumed the format of elephant_seal_data.txt as space separated integer values.
#include <stdio.h>
#define MAXSIZE 5000 /* Macro definition to pre-define the size of the array */
double average_weight(int count, int weights_array[]);
int main(void)
{
int number_of_seals;
int weights_array[MAXSIZE];
printf("Enter the number of seals: \n");
scanf("%i", &number_of_seals);
printf("Their average weight is %lf\n", average_weight(number_of_seals, &weights_array[number_of_seals]));
return 0;
}
double average_weight(int count, int weights_array[])
{
/* Variable declaration and initialization
* Note the use of the FILE data type */
int weight;
int sum = 0;
int i = 0;
FILE *elephant_seal_data = fopen("elephant_seal_data.txt", "r");
if (elephant_seal_data == NULL)
{
return -1;
}
/* FEOF function to determine if EOF has been reached or not */
while (i<count)
{
fscanf(elephant_seal_data, "%d", &weight);
weights_array[i++] = weight;
if (feof(elephant_seal_data)) break;
sum += weight;
}
double average_weight = (double)sum / (double)count;
fclose(elephant_seal_data);
return average_weight;
}
Edit:
I have used the elephant_seals_data.txt to simulate these in Google Colab for you. Try running the first cell there.
Google Colab Link

Array index of smallest number greater than a given number in a sorted array using C

Need to find the index of a number, that may or may not be present in the array. I tried the below code:
#include <stdio.h>
#include <stdlib.h>
int cmp(const void *lhs, const void *rhs){
return ( *(long long*)lhs - *(long long*)rhs );
}
int main(){
int size = 9;
long long a[] = {16426799,16850699,17802287,18007499,18690047,18870191,18870191,19142027,19783871};
long long x = 17802287;
long long *p = (long long *)bsearch(&x, a, size, sizeof(long long), cmp);
if (p != NULL)
printf("%lld\n", p - a);
return 0;
}
The above code works if the number, in this case 17802287 is present in the array a, but fails if the number is not present in a, e.g. doesn't give any output for x=18802288, I would like to get the index i=5 in that case 5th element onwards the elements are greater than 18802288.
Also the actual array size will have number of elements more than 4 million, would the same code work?
Thanks for the help.
From the man page for bsearch:
The bsearch() function returns a pointer to a matching member of
the array, or NULL if no match is found. If there are multiple
elements that match the key, the element returned is unspecified.
So the function will return NULL if the element in question is not found. If you want to find the first element greater than or equal to the number in question, you'll need to roll your own function to do that.
One of the possible solution can be:
int i, outcome = -1;
for( i = 0; i < size; i++ )
{
if( x == a[i] )
{
outcome = i;
break;
}
}
printf("%d\n", outcome);
You need to write a function that does approximately this:
bsearch_geq (number array low high)
if low is equal to high return high
let halfway be average of low and high
if array[halfway] is equal to number then return halfway
if array[halfway] is greater than number then
return result of "bsearch_geq number array low halfway"
else
return result of "bsearch_geq number array halfway high"
That'll get you 99% of the way, I think, but I'll leave it as an exercise to the reader to figure out the corner cases. The main one I can see is what happens when you get down to just two numbers because the naive "average" may cause infinite recursion.
If you can have multiple occurrences of the same number in the array then you'll need to drop the if array[halfway] is equal]" line.
You should ensure your solution uses tail-recursion for efficiency, but it's not too critical as 4m data-entries only amounts to about 15 recursive calls.

How can I convert a long long into an array in C?

I would like to convert an integer into an array. My goal is to be able to take a long long, for example 123456789..., and make an array in which each digit holds one spot, like this {1, 2, 3, 4, 5, 6, 7, 8, 9, ...}.
I can't use iota() because I am not allowed to, and I don't want to use snprintf because I don't want to print the array. I just want to make it.
After thinking about it for awhile, the only solution I thought of was to
Create a loop to divide the number by ten for each digit, leaving the quotient as an int
Let the decimals of the quotient go away via the restrictions of the int data type
Make a for loop to decrement the number until it becomes divisible by ten, all while incrementing a counter i
Let the i effectively become the digit and pass it into the array
But I feel like I am making this extremely overcomplicated, and there must be a simpler way to do this. So, have I answered my own question or is there and easier way?
This is an iterative approach for your problem which I guess works perfectly
The code below is commented ! Hope it helps
#include <stdio.h>
int main()
{
// a will hold the number
int a=548763,i=0;
// str will hold the result which is the array
char str[20]= "";
// first we need to see the length of the number a
int b=a;
while(b>=10)
{
b=b/10;
i++;
}
// the length of the number a will be stored in variable i
// we set the end of the string str as we know the length needed
str[i+1]='\0';
// the while loop below will store the digit from the end of str to the
// the beginning
while(i>=0)
{
str[i]=a%10+48;
a=a/10;
i--;
}
// only for test
printf("the value of str is \"%s\"",str);
return 0;
}
if you want the array to store only ints you need only to change the type of the array str and change
str[i]=a%10+48;
to
str[i]=a%10;
You can use only 1 loop :
#include <math.h>
int main() {
int number = 123456789;
int digit = floor(log10(number)) + 1;
printf("%d\n", digit);
int arr[digit];
int i;
for (i = digit; i > 0; i--) {
arr[digit-i] = (int)(number/pow(10,i-1)) % 10;
printf("%d : %d\n", digit-i, arr[digit-i]);
}
}

C program stops responding for large inputs

I am (re-)learning C and in the book I am following we are covering arrays, and the book gives an algorithm for finding the first n primes; myself being a mathematician and a decently skilled programmer in a few languages I decided to use a different algorithm (using the sieve of Eratosthenes) to get the first n primes. Well making the algorithm went well, what I have works, and even for moderately large inputs, i.e. the first 50,000 primes take a bit to run as you would expect, but no issues. However when you get to say 80,000 primes pretty much as soon as it begins a window pops up saying the program is not responding and will need to quit, I made sure to make the variables that take on the primes were unsigned long long int, so I should still be in the acceptable range for their values. I did some cursory browsing online and other people that had issues with large inputs received the recommendation to create the variables outside of main, to make them global variables. I tried this for some of the variables that I could immediately put outside, but that didn't fix the issue. Possibly I need to put my arrays isPrime or primes outside of main as well? But I couldn't really see how to do that since all of my work is in main.
I realize I should have done this with separate functions, but I was just writing it as I went, but if I moved everything into separate functions, my arrays still wouldn't be global, so I wasn't sure how to fix this issue.
I tried making them either static or extern, to try and get them out of the stack memory, but naturally that didn't work since they arrays change size depending on input, and change over time.
the code is:
#include <math.h>
#include <stdbool.h>
#include <stdio.h>
unsigned long long int i,j;
unsigned long long int numPrimes,numPlaces;
int main(void)
{
bool DEBUG=false;
printf("How many primes would you like to generate? ");
scanf("%llu",&numPrimes);
// the nth prime is bounded by n*ln(n)+n*ln(ln(n)), for n >=6
// so we need to check that far out for the nth prime
if (numPrimes>= 6)
numPlaces = (int) numPrimes*log(numPrimes)+
numPrimes*log(log(numPrimes));
else
numPlaces = numPrimes*numPrimes;
if(DEBUG)
printf("numPlaces: %llu\n\n", numPlaces);
// we will need to check each of these for being prime
// add one so that we can just ignore starting at 0
bool isPrime[numPlaces+1];
// only need numPrimes places, since that is all we are looking for
// but numbers can and will get large
unsigned long long int primes[numPrimes];
for (i=2; i<numPlaces+1;i++)
isPrime[i] = true; // everything is prime until it isn't
i=2; // represents current prime
while (i < numPlaces + 1)
{
for (j=i+1;j<numPlaces+1;j++)
{
if (isPrime[j] && j%i ==0) // only need to check if we haven't already
{
isPrime[j] = false;// j is divisibly by i, so not prime
if(DEBUG)
{
printf("j that is not prime: %llu\n",j);
printf("i that eliminated it: %llu\n\n",i);
}//DEBUG if
}//if
}//for
// ruled out everything that was divisible by i, need to choose
// the next i now.
for (j=i+1;j<numPlaces+2;j++)// here j is just a counter
{
if (j == numPlaces +1)// this is to break out of while
{
i = j;
break;
}// if j = numPlaces+1 then we are done
else if (isPrime[j]==true)
{
i = j;
if (DEBUG)
{
printf("next prime: %llu\n\n",i);
}//DEBUG if
break;
}//else if
}// for to decide i
}//while
// now we have which are prime and which are not, now to just get
// the first numPrimes of them.
primes[0]=2;
for (i=1;i<numPrimes;i++)// i is now a counter
{
// need to determine what the ith prime is, i.e. the ith true
// entry in isPrime, 2 is taken care of
// first we determine the starting value for j
// the idea here is we only need to check odd numbers of being
// prime after two, so I don't need to check everything
if (i<3)
j=3;
else if (i % 2 ==0)
j = i+1;
else
j = i;
for (;j<numPlaces+1;j+=2)// only need to consider odd nums
{
// check for primality, but we don't care if we already knew
// it was prime
if (isPrime[j] && j>primes[i-1])
{
primes[i]=j;
break;
}//if, determined the ith prime
}//for to find the ith prime
}//for to fill in primes
// at this point we have all the primes in 'primes' and now we just
// need to print them
printf(" n\t\t prime\n");
printf("___\t\t_______\n");
for(i=0;i<numPrimes;i++)
{
printf("%llu\t\t%llu\n",i+1,primes[i]);
}//for
return 0;
}//main
I suppose I could just avoid the primes array and just use the index of isPrime, if that would help? Any ideas would help thanks!
Your problem is here, in the definition of the VLA ("Variable Length Array", not "Very Large Array")
bool isPrime[numPlaces+1];
The program does not have enough space in the area for local variables for the array isPrime when numPlaces is large.
You have two options:
declare the array with a "big enough" size outside of the main function and ignore the extra space
use another area for storing the array with malloc() and friends
option 1
#include <stdio.h>
unsigned long long int i,j;
bool isPrime[5000000]; /* waste memory */
int main(void)
option 2
int main(void)
{
bool *isPrime;
// ...
printf("How many primes would you like to generate? ");
scanf("%llu",&numPrimes);
// ...
// we will need to check each of these for being prime
// add one so that we can just ignore starting at 0
isPrime = malloc(numPrimes * sizeof *isPrime);
// ... use the pointer exactly as if it was an array
// ... with the same syntax as you already have
free(isPrime);
return 0;
}
The array you allocate is a stack variable (by all likelihood), and stack size is limited, so you are probably overwriting something important as soon as you hit a certain size threshold, causing the program to crash. Try using a dynamic array, allocated with malloc, to store the sieve.

Why am I getting outputs of huge numbers with this program?

I am trying to make a program that allows the user to input a positive integer, and the program will output the sum of each digit added together. For example, if the user inputs 54, the program will output 9. For some reason, the program is outputting outrageously huge numbers. When 54 is the input, the output will read something like 5165451 or 2191235. I'm new to C programming, but I don't see a single thing wrong with this code..
//This program takes a positive integer
//from the user, and adds all the digits
//of the number together.
#include <stdio.h>
int main() {
system("clear");
int given, add, hold, i;
printf("Enter a positive integer (up to 10 digits): ");
scanf("%d", &given); //User input
for (i = 0; i < 10; i++) { //Loop to add digits
hold = (given % 10);
given = (given / 10);
add = (add + hold);
}
printf("Sum of the digits is %d\n", add); //Output
}
int given, add, hold, i;
You haven't initialized add, so it contains unspecified data, aka garbage. Using its value while it is unspecified is undefined behaviour.
Insert add = 0; before the loop to see if that helps.
I think the for loop is wrong
The loop will run 10 times whereas scanf will only take the input upto the limit of int data type i.e 32768.
You should make given a long data type.
and make the for loop as
for(;given!=0;)
{
hold = (given % 10);
given = (given / 10);
add = (add + hold);
}
and of course initialize add to zero.

Resources