why am i getting segmentation fault when i run this code? - c

#include <stdio.h>
void avg_sum(double a[], int n, double *avg, double *sum)
{
int i;
sum = 0;
printf("%f", *sum);
for(i=0; i<n; i++)
*sum += a[i];
*avg = *sum/n;
}
int main()
{
double arr[2] = {0.0,1.0};
double *sum;
double *avg;
int n = 2;
avg_sum(arr, n, avg, sum);
printf("...Done...\n");
return 0;
}
Tried using both GCC(https://www.tutorialspoint.com/compile_c_online.php) and clang(from repl.it) online compilers

double *sum;
This creates a pointer to a double but it has an arbitrary value and therefore points at no dedicated memory.
In addition, in the called function, you set the sum pointer to zero (the null pointer) then try to use that pointer to dereference memory - that's a big non-no.
I'd also be wary of for(i=0; i<n-2; i++) for summing the values in the array. It's not going to include the final two which, since n is two, means it won't accumulate any of them.
The correct way to do this would be with:
void avg_sum(double a[], int n, double *avg, double *sum) {
int i;
*sum = 0; // set content, not pointer.
for(i=0; i<n; i++) // do all elements.
*sum += *(a+i);
*avg = *sum/n;
}
int main(void) {
double arr[2] = {0.0,1.0};
double sum; // ensure actual storage
double avg; // and here
int n = 2;
avg_sum(arr, n, &avg, &sum); // then pass pointers to actual storage
printf("Sum=%f, Avg=%f\n", sum, avg);
return 0;
}
This gives you, as expected:
Sum=1.000000, Avg=0.500000

Easy. In line 6 you assign 0 to sum but sum is not the actual sum but a pointer to it. When you try to print it you access invalid memory.
Edit:
BTW if you try compling with -fanalyzer you will get a warning and an explanation.
https://godbolt.org/z/W6ehh8

Related

Error in C program in Dynamic memory allocation

I am using gcc compiler in ubuntu18.10 os. And I don't know why this program is giving Error and Can't even understand the error. The Program is as follows and I presented ERRORS also.
#include<stdio.h>
#include<stdlib.h>
float Average(int*, int);
int main()
{
int *arr;
int n;
scanf("%d",&n);
float sum;
arr = (int *)malloc(n * sizeof(int));
for(int i=0;i<n;i++)
scanf("%d",&arr[i]);
sum = Average(int *arr, int n);
printf("%f\n",sum);
return 0;
}
float Average(int *arr, int size)
{
int sum;
int n = size;
printf("arr: %p\n",&arr);
printf("size: %p\n",&size);
printf("sum: %p\n",&sum);
for(int i=0;i<n;i++)
{
sum += arr[i];
}
return (sum * 1.0f) / size;
}
Errors are:
Test.c: In function ‘main’:
Test.c:16:16: error: expected expression before ‘int’
sum = Average(int *arr, int n);
^~~
Test.c:16:8: error: too few arguments to function ‘Average’
sum = Average(int *arr, int n);
^~~~~~~
Test.c:4:7: note: declared here
float Average(int*, int);
^~~~~~~
Please Help me to find out why and any reference materials to understand the concept clearly.
Thank you
sum = Average(int *arr, int n);
Type specifiers are something you give in the declaration and definition of the function, not in calls to it. You want:
sum = Average(arr, n);
Some other things you may want to check.
First, the int sum; in Average() does not initialise the value to zero, it sets it to some arbitrary value. That's not going to end well when you just add the integers to it. It should instead be:
int sum = 0;
Second, unless you're using massive arrays of floating point numbers, it's almost always better to use double for its greater range and precision.
Taking those into account, I probably would have written the function:
double Average(int *arr, int size) {
double sum = 0;
for (int i = 0; i < size; ++i)
sum += arr[i];
return sum / size;
}
When you call a function you don't specify the types of the arguments. That's a syntax error. If you look at where you call printf, you'll see that you don't specify the parameter types there. The same goes for your own functions.
So change this:
sum = Average(int *arr, int n);
To this:
sum = Average(arr, n);

created a function that reverses the contents of an array of double in C? but not working

i wanted to create a function that reverses the contents of an array of double in C but its not working
My function is not returning the reversed array? Please help
//Reverse the content of an array of double
#include<stdio.h>
#define SIZE 5
double *reverse(double *func[],int n);
int main()
{
int i;
double *arr[SIZE];
printf("Please enter 5 numbers\n");
for(i=0;i<SIZE;i++) {
scanf("%lf",arr[i]); // takes the the content of array
}
double arr = reverse(&arr,SIZE); // takes the return value from the function
for(i=0;i<SIZE;i++) {
printf("%.2lf\n",arr[i]);
}
}
double *reverse(double *func[],int n)
{
int i,j;
static double *base[SIZE];
for(i=4,j=0;i>=0,j<n;i--,j++) {
base[j] = func[i]; // reverses the content of array
}
return *base;
}
I guess there is a problem in my function, but i am not able to find it
There are a number of issues with your code. Most important this:
double *arr[SIZE];
That is not an array of double (it is an array of pointers to double). That misunderstanding seem to go through all the program and cause several other mistakes.
For instance this:
scanf("%lf",arr[i]);
Here arr[i] is an uninitialized pointer so scanning into it is undefined behavior.
Further, your function call suffers from the array mistake as well.
A more correct version of your code could be:
#include<stdio.h>
#define SIZE 5
void reverse(double* d, int n);
int main()
{
int i;
double arr[SIZE]; // Array of double
printf("Please enter %d numbers\n", SIZE);
for(i=0;i<SIZE;i++)
{
scanf("%lf", &arr[i]); // TODO: Check scanf return value....
// ^ Notice the & (i.e. address-of)
}
reverse(arr, SIZE); // Just pass arr as it will decay into a double pointer
for(i=0;i<SIZE;i++)
{
printf("%.2lf\n",arr[i]);
}
return 0;
}
void reverse(double* d, int n) // Just pass a pointer to first double in the array
{
int i, j=0;
double temp;
for(i=n-1; i>j; i--,j++) // Stop when you reach the middle of the array
{
// Swap using a temp variable
temp = d[j];
d[j] = d[i];
d[i] = temp;
}
}
void reverse(double *arr,int n)
{
for(int i=0;i<n/2;i++)
{
double temp = arr[i];
arr[i] = arr[n-i-1];
arr[n-i-1] = arr[i];
}
}

Finding minimal number in array

I would like to write a program which finds the minimal number of 5 inputted numbers. I'm stuck at the point when I want to use function getMinNum, but there is an error saying: expected expression before ']' token
I understand it has a connection with pointers, however I would like to do it without them if it is possible of course.
#include <stdio.h>
#include <stdlib.h>
float getMinNum(float a[], int x);
int main()
{
int n = 5;
int i;
float z[n];
for(i=0; i<n; i++){
scanf("%f", &z[i]);
}
printf("%6.2f", getMinNum(z[], n));
return 0;
}
float getMinNum(float a[], int x)
{
int i, min = a[0];
for(i=0; i<x; i++){
if(min > a[i+1]){
min = a[i+1];
}
}
return min;
}
You shouldn't append '[]' to the variable name.
Instead of:
printf("%6.2f", getMinNum(z[], n));
do:
printf("%6.2f", getMinNum(z, n));
Your a[i+1] will be using values outside the array, so use a[i] instead.
So the code should look like
float getMinNum(float a[], int x){
int i;
float min = a[0]; // Min needs to be a float
for(i=1; i<x; i++){ // Do not need to check a[0]
if(min > a[i]){
min = a[i];
}
}
return min;
}
And call it as
printf("%6.2f", getMinNum(z, n));

Sum of array in C

I'm working on a small program for school and can't get my array of doubles to sum properly. The specific error I'm getting is
warning C4244: 'return': conversion from 'double' to 'int', possible loss of data
on the line where sum is returned. And the sum displayed is gibberish.
The code is intended to:
fill an array of doubles with user input,
print the doubles on the screen in a column,
add up all the doubles in the array, and
print the sum onto the screen.
Code
#define _CRT_SECURE_NO_WARNINGS 1
#include<stdio.h>
#define MAX_SIZE 15
void FillArray(double a[], int *i);
void PrintArray(double a[], int i);
SumArray(double a[], int *i);
int main()
{
double input[15];
int input_size;
double sum;
FillArray(input, &input_size);
PrintArray(input, input_size);
sum = SumArray(input, &input_size);
printf("The sum is %f\n", sum);
return 0;
}
void FillArray(double a[], int *i)
{
int k;
printf("Filling an array of doubles\n");
printf("How many doubles do you want to enter (<15)\n");
scanf(" %d", i);
for (k = 0; k <*i; k++)
{
printf("Enter double:\n");
scanf("%lf", &a[k]);
}
}
void PrintArray(double a[], int i)
{
int k;
printf("Printing an array of integers:\n");
for (k = 0; k<i; k++)
{
printf("%f\n", a[k]);
}
printf("\n");
}
SumArray(double a[], int *i)
{
int k;
double sum = 0;
for (k = 0; k<*i; k++);
{
sum +=a[k];
}
return (sum) ;
}
You need to specify double SumArray(...) instead of merely SumArray(...) where you declare and define the function. If you do not specify a return type, int is assumed. Specifically:
void FillArray(double a[], int *i);
void PrintArray(double a[], int i);
double SumArray(double a[], int *i);
/*^^^^^^-- add return type*/
int main()
and
double SumArray(double a[], const int numElements)
/*^^^^^^- same deal*/ /* also ^^^^^ ^^^^^^^^^^^ */
{
int k;
double sum = 0.0; /* Edit 3: 0.0 rather than 0 for clarity */
for (k = 0; k < numElements; ++k) /* no ; here! --- Edit 3: ++k for speed and good practice */
{ /* ^^^^^^^^^^^ */
sum +=a[k];
}
return (sum) ;
}
Edit Also, you can use const int numElements instead of int *i in SumArray. You don't need to modify the value inside SumArray, so you don't need the * and you can specify const. And it's a good practice to give your variables descriptive names, e.g., numElements instead of i. That will help you understand your own code when you have to maintain it later! (Ask me how I know. ;) )
To use this, you also need to change the call in main to remove the &:
sum = SumArray(input, input_size);
/* ^ no & here */
Edit 2 As #BLUEPIXY pointed out, the trailing ; on the for loop was misplaced. As a result, the {} block ran once, after the loop had completed. That would be a significant cause of the "gibberish" you saw: the effect was to set k=numElements and then set sum=a[numElements], which was a non-existent element. So the sum was being set to whatever random memory contents happened to be after a.

Program for 1-D Statistics

So I'm having some issues with a program I'm writing to calculate statistics of an arbitrary amount of numbers. As you probably know, C does not have a native way of growing an array based on user input, so I made one. I'm not too familiar with pointers as I have not learned them yet. However, the main issue I'm having is that my program will not allow me to input anymore than 16 numbers. Any ideas on why?
#include <stdio.h>
#include <math.h>
float getMin(float arr[], int size)
{
int i;
float minimum = arr[0];
for (i=1; i < size; i++) {
if (arr[i] < minimum) {
minimum = arr[i];
}
}
return(minimum);
}
float getMax(float arr[], int size)
{
int i;
float maximum;
for(i=0; i<size; i++) {
if (arr[i] > maximum) {
maximum = arr[i];
}
}
return(maximum);
}
float getAverage(float arr[],int size)
{
int i;
float avg, sum;
for(i=0; i<size; i++) {
sum += arr[i];
}
avg = sum/size;
return avg;
}
float getVar(float arr[], int size, float average)
{
int i;
float var, diff[size], sq_diff[size], sum;
for(i=0; i<size; i++) {
diff[i] = arr[i] - average;
}
for(i=0; i<size; i++)
{
sq_diff[i] = pow(diff[i], 2);
}
var=getAverage(sq_diff, size);
return(var);
}
float getStdDev(float var)
{
float std_dev = sqrt(var);
return(std_dev);
}
int main(void)
{
int n=0, i=0;
float array[n], x;
printf("This program computes 1-D statistics.");
printf("\nEnter a negative number to stop input.\n");
do {
printf("Number %d: ", i+1);
scanf("%f", &x);
n++;
array[i] = x;
i++;
}while(x >= 0);
float avg = getAverage(array, n-1);
float var = getVar(array, n-1, avg);
printf("\nMinimum: %f", getMin(array, n-1));
printf("\nMaximum: %f", getMax(array, n));
printf("\nAverage: %f", getAverage(array, n-1));
printf("\nVariance: %f", getVar(array, n-1, avg));
printf("\nStandard Deviation: %f", getStdDev(var));
return(0);
}
I am afraid you have some general miss-understanding of how C and programming languages work in general. Programming is not exactly the same as math. If you declare a variable n and an array myarr[n], your array won't grow as n grows. The array will take the value n had at the point you declared it and will use that. Also declaring arrays like that is probably not a good idea, I don't think many C compilers will compile what one would expect. In your case you are declaring an array of size 0, the fact that it seems to work up to 16 numbers is completely system dependent. You can not expect this kind of behavior to be consistent over different systems/compilers.
Instead what you should do if you really need this is use dynamic memory. I have written a simple example really fast you could use. This is by no means a complete but for your needs it should be good enough. Use the initArr(&arr) whenever you create a new growing array. If for example you have an array of type MyArr with name arr you can get the data of the array like this arr.data[i] while you can get the length of the array (the meaningful data) like this arr.len. Finally you can get the current max size of your array like this arr.size. Please not that you should only add new elements using addElement(&arr, x) as this function will take care of the array growth. When you are done using your array you can use destrArr(&arr) to free the memory. This is good practice even though when your program exits the memory is freed anyway.
Finally please review your functions. I haven't been through your logic but remember that you should never exceed boundaries. For example you should not try to access array[-1] or array[size_of_array] where size_of_array is the total size of your array. Remember that an array declared as float arr[100] can only safely be used in the region arr[0] to arr[99]. Also doing sum += x is equivalent to doing sum = sum + x. Consider what the initial value of sum is if you do not initialize it. In fact it depends but could contain garbage values.
Try looking at your compiler warnings and fix them. It is worth understanding them and are rarely worth neglecting. Try the -Wall flag if you are using gcc, it might give you some more warnings worth looking at.
I hope this was helpful and not too confusing. In any case have a look at the following code and add your functions and libraries back. This should work out of the box.
Good Luck! :)
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define INIT_SIZE 2
typedef struct MyArr {
float *data;
int size;
int len;
} MyArr;
int initArr(MyArr *arr) {
arr->data = (float *)malloc(INIT_SIZE*sizeof(float));
if (arr->data == NULL) {
printf("OUT OF MEMORY\n");
return -1;
}
arr->size = INIT_SIZE;
arr->len = 0;
return 1;
}
int addElement(MyArr *arr, float x) {
if (arr->len == arr->size) {
int i;
float *tmp = (float *)malloc(2*arr->size);
if (tmp == NULL) {
printf("OUT OF MEMORY\n");
return -1;
}
for (i = 0; i < arr->size; ++i) {
tmp[i] = arr->data[i];
}
free(arr->data);
arr->data = tmp;
arr->size = 2*arr->size;
}
arr->data[arr->len] = x;
arr->len++;
return 1;
}
void destrArr(MyArr *arr) {
free(arr->data);
arr->size = 0;
arr->len = 0;
}
int main(void)
{
int n=0, i=0;
float x;
MyArr array;
initArr(&array);
printf("This program computes 1-D statistics.");
printf("\nEnter a negative number to stop input.\n");
do {
printf("Number %d: ", i+1);
scanf("%f", &x);
n++;
addElement(&array, x);
i++;
}while(x >= 0);
float avg = getAverage(array.data, n-1);
float var = getVar(array.data, n-1, avg);
printf("\nMinimum: %f", getMin(array.data, n-1));
printf("\nMaximum: %f", getMax(array.data, n));
printf("\nAverage: %f", getAverage(array.data, n-1));
printf("\nVariance: %f", getVar(array.data, n-1, avg));
printf("\nStandard Deviation: %f", getStdDev(var));
destrArr(&array);
return(0);
}

Resources