Why is this code giving me segmentation error? [duplicate] - c

This question already has answers here:
Crash or "segmentation fault" when data is copied/scanned/read to an uninitialized pointer
(5 answers)
Closed 4 years ago.
I'm new to C, trying to get an user entered array into ascending order and print it. I'm trying to use selection sort for this.My devcpp crashes after accepting 1st input and when I tried to run it on an online c compiler, its giving segmentation error. Can someone tell me why is this happening here? TIA
#include<stdio.h>
void swap()
{
int *x, *y;
int temp = *x;
*x = *y;
*y = temp;
}
void ss(int A[], int n)
{
int i, j, min;
for(i=0; i<n-1;i++)
{
min = i;
for(j=i+1; j<n; j++)
{
if (A[j]< A[min])
{
min = j;
}
swap(&A[min], &A[i]);
}
}
}
void print(int A[], int n)
{
int i;
for(i=0; i<n; i++)
{
printf("%d",A[i]);
}
}
int main()
{
int A[4], i, n;
printf("Enter the elements");
scanf("%d", &A[i]);
n=4;
ss(A,n);
printf("Sorted array \n");
print(A,n);
return 0;
}
I want the user entered array in ascending order.

Your swap() function has no parameters, and the pointers x and y are not pointing to anything. Your segmentation fault is coming from statements like:
int temp = *x;
Because *x has no determined value, you didn't assign an address to x of any existing value in your program, yet your trying to indirect it here.
Instead, put parameters in your swap function:
void swap(int* x, int* y)
{
int temp = *x;
*x = *y;
*y = temp;
}
And then in the outer scope, pass proper, existing values on the stack's addresses to this swap function.

Well, this is wrong, for a start:
void swap()
{
int *x, *y;
int temp = *x;
*x = *y;
*y = temp;
}
This creates two brand new pointers within the function, with arbitrary values, and then attempts to dereference them, something that's undefined behaviour.
Since you're passing two pointers to the swap function with swap(&A[min], &A[i]), you should receive those in the parameter list so that you can operate on them:
void swap(int *x, int *y) {
int temp = *x;
*x = *y;
*y = temp;
}
And, though it's not a bug, you may want to consider using more descriptive names than A or ss (e.g., dataArray and SelectionSort).
This will tend to make your code much more readable and therefore maintainable if you have to, for example, come back and modify it twelve months in the future.
You will also need a loop in your main function to get the four values. At the moment, you get only one and with an arbitrary index i which may cause you undefined behaviour again.
Since you've already done similar loops in the other two functions, I'll assume you can handle this task without me giving you the code.

There are quite a few errors buddy. I'm listing them out below:
In the main(), check how you are accepting the array values from the user. i is undefined and you are trying to insert into just A[i] without using a for loop or without defining i either. That's where you get your seg fault.
for(i = 0; i < 4; i++)
scanf("%d", &A[i]);
Another mistake is in the way you have defined the swap() function . Since you have called swap function as swap(&A[min], &A[j]);, i.e., passing addresses as parameters, your function too needs to have pointers to these addresses.
should be something like this: void swap(int* x, int* y).
As a result of the change we made in the 2nd point above, you need to remove this line ==> int *x, *y;, which declares the 2 pointers again inside the swap function.
here is the code which should work:
#include<stdio.h>
void swap(int* x, int* y)
{
int temp = *x;
*x = *y;
*y = temp;
}
void ss(int A[], int n)
{
int i, j, min;
for(i=0; i<n-1;i++)
{
min = i;
for(j=i+1; j<n; j++)
{
if (A[j]< A[min])
{
min = j;
}
swap(&A[min], &A[j]);
}
}
}
void print(int A[], int n)
{
int i;
for(i=0; i<n; i++)
{
printf("%d\t",A[i]);
}
}
int main()
{
int A[4], i, n;
printf("Enter the elements:\n");
for(i = 0; i < 4; i++)
scanf("%d", &A[i]);
n=4;
ss(A,n);
printf("Sorted array \n");
print(A,n);
return 0;
}
Which would give the output as follows:
Enter the elements:
1 2 3 4
Sorted array
4 3 2 1

Related

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

#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

Swapping two structs from an array of structs (bubblesort)

I have a struct which holds 3 integers each resembling the size of one side of a triangle:
struct triangle{
int a; int b; int c;
};
typedef struct triangle tri;
I firstly need to read the number of triangles to come (n). Then I read 3 sides of n triangles and sort them by the area of triangles in order from smallest to largest.
Now my idea was to compare the areas with each other and if the former area is larger than the later, I swap the corresponding structures. In the end, the values of structs (sides) will be printed out as an output from smallest to largest.
I am stuck with swapping the structures. So far I have done this:
void swap(tri *a, tri *b)
{
tri t;
t = *a;
*a = *b;
*b = t;
}
void sort_by_area(tri *tr, int n)
{
int sorted, storage[n];
for(int i = 0; i <= n-1; i++)
{
storage[i] = give_area(&tr[i]);
}
do
{
sorted = 1;
for(int i = 0; i < n-1; i++)
{
if(storage[i] > storage[i+1])
{
/*swap(tr[i].a, tr[i+1].a);
swap(tr[i]->b, tr[i+1]->b);
swap(tr[i]->c, tr[i+1]->c);*/
/*the commented section was my another attempt in which I would change the swap inputs to swap(int a, int b) or swap(int *a, int *b)*/
swap(&tr[i], &tr[i+1]);
sorted = 0;
}
}
}while(!sorted);
}
I'm sure I'm definitely completely wrong with putting the structs in.
If one needs more, here is my main function:
int main()
{
int n;
scanf("%d\n", &n);
tri *tr = malloc(n*(sizeof(tri)));
for(int i = 0; i < n; i++){
scanf("%d %d %d", &tr[i].a, &tr[i].b, &tr[i].c);
}
sort_by_area(tr, n);
for(int i = 0; i < n; i++){
printf("\n%d %d %d", tr[i].a, tr[i].b, tr[i].c);
}
free(tr);
return 0;
}
From my investigation the code works properly, I think the main issue lies either within the swap function, or the nested (for/if) loop in which the swap function is run.
The swap method is fine. There is a logical error in your approach though.
You compare the storage (the areas), and if the comparison is true, you swap the triangles, but not the areas. As a result, the i-th triangle does not correspond anymore to the i-th storage necessarily.
You need to swap the areas too, when their respective triangles are swapped, like this:
(I used double to store the areas, but you could still use int for it, by losing in precision)
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
struct triangle{
int a; int b; int c;
};
typedef struct triangle tri;
void swap(tri *a, tri *b)
{
tri t;
t = *a;
*a = *b;
*b = t;
}
void swap_double(double *a, double *b)
{
double tmp = *a;
*a = *b;
*b = tmp;
}
// Heron's formula
double give_area(struct triangle *tr)
{
double t = (tr->a + tr->b + tr->c)/2.0; /* Compute half of the perimeter */
return sqrt(t * (t - tr->a) * (t - tr->b) * (t - tr->c)); /* Return area */
}
void sort_by_area(tri *tr, int n)
{
int sorted;
double storage[n];
for(int i = 0; i <= n-1; i++)
{
storage[i] = give_area(&tr[i]);
}
do
{
sorted = 1;
for(int i = 0; i < n-1; i++)
{
if(storage[i] > storage[i+1])
{
swap(&tr[i], &tr[i+1]);
// Swap the areas too!!!
swap_double(&storage[i], &storage[i + 1]);
sorted = 0;
}
}
}while(!sorted);
}
int main(void)
{
int n;
scanf("%d\n", &n);
tri *tr = malloc(n*(sizeof(tri)));
for(int i = 0; i < n; i++){
scanf("%d %d %d", &tr[i].a, &tr[i].b, &tr[i].c);
}
sort_by_area(tr, n);
for(int i = 0; i < n; i++){
printf("\n%d %d %d", tr[i].a, tr[i].b, tr[i].c);
}
free(tr);
return 0;
}
Compile like this:
gcc main.c -Wall -Wextra -lm
./a.out
Input:
2
7 8 9
4 5 6
Output:
4 5 6
7 8 9
Debug-Tip: As #alk mentioned, when you are uncertain about the correctness of a specific method, write a laconic program to test that method (a minimal complete verified example (MCVE), as we tend to say here in Stack Overflow).
The problem with the code is that the auxiliary array storage stays unchanged when structure elements are swapped.
In fact there is no need to have this auxiliary array. Without it you could just write
if( give_area(&tr[i] ) > give_area( &tr[i+1] ) )
Otherwise you have to add one more swap function like
void swap_storage(int *a, int *b)
{
int t = *a;
*a = *b;
*b = t;
}
and use it together with the already defined function swap
swap(&tr[i], &tr[i+1]);
swap_storage( &storage[i[, ^storage[i+1[ );

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];
}
}

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.

Swapping function c

I have to write a swap function for my bubble sort
That's what I've got:
void swap(int arr[], int size, int i, int j)
{
int temp = *(arr+i);
*(arr + i) = *(arr+j);
*(arr+j) = temp;
}
When I'm trying to run I get the following errors:
warning C4013: 'swap' undefined; assuming extern returning int
error C2371: 'swap' : redefinition; different basic types
When I do change the function to the type of int, it does work, any idea why?
I don't need a prototype because it's before the main function... do I?
Here's the whole code:
//BubbleSort
void bubbleSort(int arr[], int size)
{
int i,j;
for(i=0; i < size; i++)
{
for(j=i+1; j < size; j++)
{
if(*(arr+i) > *(arr+j))
{
/*temp = *(arr+i);
*(arr + i) = *(arr + j);
*(arr + j) = temp;*/
swap(arr,i,j);
}
}
}
}
void swap(int arr[], int i, int j)
{
int temp = *(arr+i);
*(arr + i) = *(arr+j);
*(arr+j) = temp;
}
void main()
{
int i, arr[] = {8,0,6,-22,9};
bubbleSort(arr, sizeof(arr)/sizeof(int));
for(i=0; i < sizeof(arr)/sizeof(int); i++)
{
printf("%d, ",*(arr+i));
}
printf("\n");
}
You seem to lack a proper prototype for the function.
Add
void swap(int arr[], int size, int i, int j);
before the first call.
Also, there's really little point in using such pointer-centric notation for the indexing, especially confusing since you declared the arr argument as an array. It's cleaner to just use:
const int temp = arr[i];
arr[i] = arr[j];
arr[j] = temp;
Notice use of const for the temp value too, since it's not going to change after being assigned. Not a big deal in a 3-line function, but a good habit.
You need place void swap(int arr[], int i, int j) on top of void bubbleSort() because you're using swap() inside bubbleSort().
If not you will run into the implicit declaration of C, that is, in main(), you're calling bubbleSort(), and bubbleSort() will call swap(), but at this point, bubbleSort() does not know about you declaration of swap() since it is declared below it. So, what your compiler understand is that you're calling a swap() which is implicitly declared.
And later, when your compiler comes across your real declaration of void swap(int arr[], int i, int j), it will complain that it is a redefinition.
Other than moving your swap() declaration on to the top most, you can also solve by making the function declaration at the top most, and the definition below separately.
Besides, you don't seem to use pointer the right way, because you already passed int arr[] into the swap() function, where you can do direct swapping as pointed out by #unwind:
const int temp = arr[i];
arr[i] = arr[j];
arr[j] = temp;
Consider this swap():
void swap(int *x, int *y){
int temp = *x;
*x=*y;
*y=temp;
}
This is important for you to learn that you can actually change the content of a variable by passing the address into a function, like swap(int *x, int *y), it will be very convenient. Example:
int x,y;
x=1;
y=1;
increment_both_coordinate(x,y);
//after this call, you want to have x = 2, y = 2
This can only be achieve using the method similar to swap(int *x, int *y). This is just an illustration, you will understand how useful this can be when you see them in future.
Inside bubbleSort() you call a function named swap() but, at that point in the code, there is no function named swap() either defined or declared.
Solution 1: move the defintion of swap() to before the definition of bubbleSort()
Solution 2: specify the prototype of swap() before defining bubbleSort()
If the function is void, you can't return a number.
Change your
return 0;
to
return;
Because you're returning 0. Take out the return statement and you should be fine, especially since you're operating on pointers instead of copy values.
Using "void" means the function doesn't return any value,but actually your function return "0",which is an int type.So you should use int instead of void before function definition.
Here is a function for swapping integers:
void swap(int *x, int *y) {
*x = *x ^ *y;
*y = *x ^ *y;
*x = *x ^ *y;
}
int main(int argc, char* argv) {
int a,b;
a = 5;
b = 10;
swap(&a, &b);
printf("a = %d, b = %d\n", a, b);
return 0;
}
You can swap two array cells this way: swap(&arr[i], &arr[j]);

Resources