I am getting error on the line where I put "<<--" (line 9) sign. it didn't had any compiling error , but while giving input it says "Segmentation fault: 11". I don't know what went wrong.
input:
3 3
1 1 1
2 2 2
3 1 5
The code:
#include <stdio.h>
#include <stdlib.h>
int comp (const void * x, const void * y)
{
int *a = *(int **)x;
int *b = *(int **)y;
//getting error here
if (a[0] == b[0]) // <<-- here
{
if (a[2] == b[2])
{
return -(a[1] - b[1]);
}
else
{
return a[2] - b[2];
}
}
else
{
return a[0] - b[0];
}
}
int main()
{
int n;
long long d;
scanf("%d %lld", &n, &d);
int t[n][3];
for (int i = 0; i < n; i++)
{
scanf ("%d %d %d", &t[i][0], &t[i][1], &t[i][2]);
}
printf("%lu\n", sizeof(t[0]));
qsort(t, n, sizeof(t[0]), comp);
for (int i = 0; i < n; ++i)
{
printf("%d-%d-%d\n", t[i][0], t[i][1], t[i][2]);
}
}
Can anyone help me with this?
Your
int t[n][3];
array is actually an 1D array consisting of n 1D arrays of type int [3]. These int [3] objects is what you are trying to sort by your
qsort(t, n, sizeof(t[0]), comp)
call.
So, in order to properly compare these objects you have to interpret the parameters of your comparison callback as pointers to int [3] objects. Meanwhile, your current implementation of comp is written as if the parameters are pointing to int * objects, which is incorrect. int [3] and int * are two very different things.
This is how you can do it
int comp (const void * x, const void * y)
{
int (*a)[3] = x;
int (*b)[3] = y;
// And now compare the arrays by accessing them as `(*a)[1]`,
// `(*b)[2]` and so on
}
Alternatively, you can write the comp prologue code as
int comp (const void * x, const void * y)
{
const int *a = *(int (*)[3]) x;
const int *b = *(int (*)[3]) y;
// And now compare the arrays by accessing them as `a[1]`,
// `b[2]` and so on, i.e. keep the rest of your code unchanged
}
This assumes that the rest of your comparison logic is correct. Note though that comparing int values by subtracting them from each other is risky, since it can overflow.
Related
I created an insertion sort method which accepts an array, its size and a comparator. The comparator function is this:
int compare_int_ptr(void* ptr1, void* ptr2) {
double i1 = *(double*)ptr1;
double i2 = *(double*)ptr2;
if(i1<i2) {
return -1;
}
if(i1 == i2) {
return 0;
}
return 1;
}
The insertion is this:
void insertion_sort(void** array, int size, CompFunction compare){
int i,j;
void* key;
for(i = 1; i<size;i++){
key = array[i];
for(j = i-1; j>=0 && compare(array[j],key)>=0;j--){
swap(&array[j+1],&array[j]);
}
array[j+1] = key;
}
}
If I try to execute it, I get the segmentation fault error, so I think that I didn't used the pointer correctly. Is it correct that when I do the swap i pass it with the &?
EDIT: this is where I call the method:
int main(int argc, char const *argv[]) {
if(argc < 2) {
printf("Usage: sortingfirstusage <file_name>\n");
exit(EXIT_FAILURE);
}
double* array = load_array(argv[1]);
insertion_sort((void**)array, 3, compare_int_ptr);
free(array);
return 0;
The array is correctly loaded because I printed all the elements before calling the insertion sort and they were in.
You are trying to sort an array of doubles. double *array points to the first of n elements:
array ==> [ double ] \
[ double ] |
. > n elements
. |
[ double ] /
You are casting array to a void **:
(void **)array ==> [ void * ] \
[ void * ] |
. > n elements
. |
[ void * ] /
It should not be hard to determine that trouble lies ahead. A void * is not a double. It may or may not be the same size as a double. It almost certainly doesn't point to a valid memory location, so if you dereference it you will invoke undefined behavior, almost certainly resulting in your program being killed by a signal. Unfortunately, your insertion_sort function does dereference it when it calls the comparison function:
key = array[i];
for(j = i-1; j>=0 && compare(array[j],key)>=0;j--){
array[i] and array[j] are both invalid void * values (because the underlying memory contains doubles, not void *s). Your comparison function dereferences them here:
double i1 = *(double*)ptr1;
double i2 = *(double*)ptr2;
ptr1 and ptr2 contain meaningless pointer values. They do not point to doubles. Dereferencing them invokes undefined behavior.
Here is a working version of insertion_sort using the same function type and equivalent functionality to the qsort function from the C standard library (although the function is a lot less efficient than qsort):
insertion_sort.h:
#ifndef INSERTION_SORT_H_INCLUDED__
#define INSERTION_SORT_H_INCLUDED__
#include <stddef.h>
void insertion_sort(void *base, size_t nmemb, size_t size,
int (*compar)(const void *, const void *));
#endif
insertion_sort.c:
#include <string.h>
#include "insertion_sort.h"
void insertion_sort(void *base, size_t nmemb, size_t size,
int (*compar)(const void *, const void *))
{
char (*b)[size] = base;
size_t i;
size_t j;
int cmp;
for (i = 1; i < nmemb; i++) {
j = i - 1;
/* search backwards for insertion point */
while ((cmp = compar(b + j, b + i)) > 0 && j > 0)
j--;
if (cmp <= 0)
j++; /* went back one too far */
if (j < i) {
/* rotate element i to position j, j to j+1, ..., i-1 to i */
char tmp[size];
memcpy(&tmp[0], &b[i][0], size);
memmove(&b[j + 1][0], &b[j][0], size * (i - j));
memcpy(&b[j][0], &tmp[0], size);
}
}
}
Here is an example of the usage of the above function:
main.c:
#include <stdio.h>
#include "insertion_sort.h"
int compar_double(const void *a, const void *b)
{
double d1 = *(const double *)a;
double d2 = *(const double *)b;
if (d1 < d2)
return -1;
if (d1 > d2)
return 1;
return 0;
}
void print_doubles(const double *d, size_t n)
{
size_t i;
for (i = 0; i < n; i++)
printf("%g\n", d[i]);
}
int main(void)
{
double numberlist[] = { 3.0, 1.0, 5.0, -4.0, 2.0 };
size_t len = sizeof numberlist / sizeof numberlist[0];
printf("Unsorted:\n");
print_doubles(numberlist, len);
printf("\n");
insertion_sort(numberlist, len, sizeof numberlist[0], compar_double);
printf("Sorted:\n");
print_doubles(numberlist, len);
return 0;
}
Here is the output produced by the above program:
Unsorted:
3
1
5
-4
2
Sorted:
-4
1
2
3
5
void qsort( void *ptr, size_t count, size_t size,
int (*comp)(const void *, const void *) );
Like qsort, your sorting function should take a void * as the first parameter, not void **. The double indirection is a mistake that you should have noticed when calling insertion_sort. Converting a double[] array to void ** requires a cast, whereas it can be converted automatically to void * without one.
Without knowing what load_array(argv[1]); does, the answer is impossible to predict as Peter suggested in the comments.
Assuming this function call is doing something legitimate and loading the array with pointers that can be de-referenced properly then your problem is the cast. You cannot make a pointer into a pointer to pointers. You have to pass the address of the pointer to accomplish what you want.
insertion_sort(&array, 3, compare_int_ptr);
How to write this C program pass by pointers and pass by value? I created this program that generates a 10x10 array from -100 to 100 and the main diagonal is read from bottom to top, but I do not know how to create two other programs that are pass by pointers and value
I have to write two more programs with the same input and output only through these two methods. I am a beginner in C and I do not know how to make this.
#include <stdio.h>
#include <stdlib.h>
#define N 10
#define M 10
int my_rand(int max, int min)
{
return (min + rand() / (RAND_MAX / (max - min + 1) + 1));
}
void generate_array(int(*array)[M])
{
printf("Table:");
for (int i = 0; i < N; i++)
{
printf("\n");
for (int j = 0; j < M; j++)
{
array[i][j] = my_rand(-100, 100);
printf("%4d ", array[i][j]);
}
}
}
void print_diagonal(int(*array)[M])
{
printf("\n\nThe main diagonal read from bottom to top:\n");
for (int i = N - 1; i >= 0; i--)
{
printf("%4d ", array[i][i]);
}
}
int *create_array(int(*array)[M])
{
static int new_array[M] = { 0 };
for (int i = 0; i < N; i++)
new_array[i] = array[i][i];
return new_array;
}
void reverseArray(int arr[], int start, int end)
{
int temp;
while (start < end)
{
temp = arr[start];
arr[start] = arr[end];
arr[end] = temp;
start++;
end--;
}
}
void printArray(int arr[])
{
int i;
for (i = N; i < N; i++)
printf("%4d ", arr[i]);
printf("\n");
}
int main(void)
{
int array1[N][M] = { 0 }, *aux_array;
generate_array(array1);
print_diagonal(array1);
aux_array = create_array(array1);
reverseArray(aux_array, 0, N - 1);
printArray(aux_array);
}
Any help would be much appreciated.
C only supports pass by value. The formal argument in the function definition is always a different object in memory from the actual argument in the function call (assuming the actual argument is itself an object, which it doesn't have to be).
We can fake pass-by-reference semantics by passing a pointer (which is passed by value). Here's a typical example:
void swap( int *a, int *b )
{
int tmp = *a;
*a = *b;
*b = tmp;
}
Instead of receiving to integer objects, we receive pointers to two integer objects. We use the unary * operator to dereference the pointers and access the pointed-to objects. If we call that function like so:
int main( void )
{
int x = 1;
int y = 2;
...
swap( &x, &y );
...
return 0;
}
Given the above code, the following are true when we enter the swap function:
a == &x // int *
*a == x == 1 // int
b == &y // int *
*b == y == 2 // int
After we execute the body of the swap function, the following are true:
a == &x // no change
*a == x == 2
b == &y // no change
*b == y == 1
Where things get weird is when you pass array expressions as function arguments. C has a rule that when an array expression is not the operand of the sizeof or unary & operators, or is not a string literal used to initialize a character array in a declaration, the expression is converted ("decays") from an array type to a pointer type, and the value of the expression is the address of the first element.
IOW, given the code
int arr[10];
foo( arr );
Since it's not the operand of the sizeof or unary & operators, the expression arr in the call to foo is automatically converted from type "10-element array of int" to "pointer to int", and the value that gets passed to foo is the address of the first element; IOW, that call is identical to writing
foo( &arr[0] );
and the function definition would be written as
void foo( int *a ) // or int a[], which means the same thing
{
// do something with a[i]
}
IOW, you cannot pass arrays by value in C.
So, looking at your code:
int my_rand(int max, int min)
Both max and min are being passed by value
void generate_array(int(*array)[M])
void print_diagonal(int(*array)[M])
These are receiving a pointer to the first element of a 2D array, so we're faking pass-by-reference.
void reverseArray(int arr[], int start, int end)
We're receiving a pointer to first element of the array (T a[] and T a[N] are both interpreted as T *a in a function parameter declaration), start and end are being passed by value.
void printArray(int arr[])
Again, we're receiving a pointer to the first element of the array.
I don't understand so well how this code works:
#include <stdio.h>
void gswap(void* ptra, void* ptrb, int size)
{
char temp;
char *pa = (char*)ptra;
char *pb = (char*)ptrb;
for (int i = 0 ; i < size ; i++) {
temp = pa[i];
pa[i] = pb[i];
pb[i] = temp;
}
}
int main()
{
int a=1, b=5;
gswap(&a, &b, sizeof(int));
printf("%d , %d", a, b)
}
What I understand is that char has 1 byte(size) in memory and we are using pointers to swap each byte of the int value(4 bytes).
But in the end, how it is possible to dereference a char pointer to int value?
Let's try and figure this out, step by step, with code comments
#include <stdio.h>
//gswap() takes two pointers, prta and ptrb, and the size of the data they point to
void gswap(void* ptra, void* ptrb, int size)
{
// temp will be our temporary variable for exchanging the values
char temp;
// We reinterpret the pointers as char* (byte) pointers
char *pa = (char*)ptra;
char *pb = (char*)ptrb;
// We loop over each byte of the type/structure ptra/b point too, i.e. we loop over size
for (int i = 0 ; i < size ; i++) {
temp = pa[i]; //store a in temp
pa[i] = pb[i]; // replace a with b
pb[i] = temp; // replace b with temp = old(a)
}
}
int main()
{
// Two integers
int a=1, b=5;
// Swap them
gswap(&a, &b, sizeof(int));
// See they've been swapped!
printf("%d , %d", a, b);
}
So, basically, it works by going over any given datatype, reinterpreting as bytes, and swapping the bytes.
This question already has answers here:
Why does this code not swap the numbers? [duplicate]
(2 answers)
Closed 6 years ago.
I am asked to make a swap between 2 integers.
#include <stdio.h>
#include <stdlib.h>
void swaplol(int a, int b)
{
int tmp;
tmp = a;
a = b;
b = tmp;
printf("After the swap : a= %d, b=%d\n",a,b);
}
I dont see where the problems lies. Everything seems good synthax wise...
int main(void)
{
int a,b;
a = 666;
b = 998;
printf("Before the swap a = %d, b = %d\n",a,b);
swaplol(a,b);
return 0;
}
Thanks
You need to pass the address of the integer to the swap function, so that when the value is swapped, you get swapped a and b values back in main. You therefore have to change the swaplol function to accept pointers instead of ints.
#include <stdio.h>
#include <stdlib.h>
void swaplol(int *a, int *b)
{
int tmp;
tmp = *a;
*a = *b;
*b = tmp;
printf("After the swap : a= %d, b=%d\n",*a,*b);
}
int main(void) {
// your code goes here
int a,b;
a = 666;
b = 998;
printf("Before the swap a = %d, b = %d\n",a,b);
swaplol(&a,&b);
printf("After the swap : a= %d, b=%d\n",a,b);
return 0;
}
The swap function should swap values of the original variables declared in main.
To do this the function has to accept the variables by reference.
And you should remove the output statement from the function and place it in main to demonstrate that the original variables were swapped.
For example
#include <stdio.h>
void swaplol( int *a, int *b )
{
int tmp = *a;
*a = *b;
*b = tmp;
}
int main( void )
{
int a, b;
a = 666;
b = 998;
printf( "Before the swap a = %d, b = %d\n", a, b );
swaplol( &a, &b );
printf( "After the swap : a = %d, b = %d\n", a, b );
return 0;
}
There is no need to include header <stdlib.h>
Use pointers:
void swaplol( int * a, int * b )
{
int tmp;
tmp = *a;
*a = *b;
*b = tmp;
}
int main(void)
{
int a, b;
a = 666;
b = 998;
printf( "Before the swap a = %d, b = %d\n", a ,b );
swaplol( &a, &b);
printf( "After the swap : a= %d, b=%d\n", a, b );
return 0;
}
Just add pointers.. i'm providing a code snippet without using a temp variable.
int main()
{
....
....
swaplol(&a,&b);
}
int swaplol(int *a,int *b)
{
*a=*a+*b;
*b=*a-*b;
*a=*a-*b;
printf("a=%d,b=%d",a,b);
}
In C there is The call by value and call by address with help of the Pointers. There you can "simulate" a call by reference which is present in other Languages.
Any way by default, C uses call(pass) by value to pass arguments. This means that the code within a function cannot alter the arguments used to call the function.
Lets take the following example:
#include <stdio.h>
void foo( int x );
int main( void ){
int x = 5;
foo(x);
printf("X = %d\n", x);
}
void foo( int x ){
x = 10;
}
The output will be 5.
If you are using a good compiler with settings turned ON you will see this kind of warning:
program.c:14:15: error: parameter ‘x’ set but not used [-Werror=unused-but-set-parameter]
void foo( int x ){
^
Now what did just happen?
By definition, call(pass) by value means you are making a copy in memory of the actual parameter's value that is passed in, a copy of the contents of the actual parameter.
If you really need to modify a value you need to pass the address of that variable and use a pointer to point to it:
#include <stdio.h>
void foo( int *x );
int main( void ){
int x = 5;
foo(&x);
printf("X = %d\n", x);
}
void foo( int *x ){
*x = 10;
}
Now the Output will be 10.
I have been asked to write a function that prints the content of an array after the xth element (as in, x and forth, as x is a pointer inside the array). I am not allowed to use [] for anything other than initialization, and not allowed to create variables inside the function - I may only use what the function receives from the main, which is the length (int n), the array (int* arr) and element x (int* x).
My question is how can I print x and forth in the array using only pointers without an index from a loop?
Here is what I wrote:
void printAfterX(int* arr, int n, int* x)
{
if ((arr <= x) && (x < arr + n))
{
while(x < (arr + n))
{
printf("%8d", *(arr+x)); //I know you can't do this
x++;
}
}
}
For this:
int arr[] = { 0,5,6,7,8,4,3,6,1,2 };
int n=10;
int* x = (arr+3);
printAfterX(arr, n, x);
The output should be:
7 8 4 3 6 1 2
Edit: Thanks y'all for the help! Works just fine. :)
void printAfterX(int* arr, int n, int* x)
{
arr += n; // make arr to point past the last element of the array
for( ; x < arr; x++) // walk till the end of array
printf("%8d", *x); // print the current item
}
Example https://ideone.com/Ea3ceT
You want this:
#include <stdio.h>
#include <stdlib.h>
void printAfterX(int* arr, int n, int* x)
{
while(x < (arr + n))
{
printf("%d ", *x);
x++;
}
}
int main()
{
int arr[] = { 0,5,6,7,8,4,3,6,1,2 };
int n = 10;
int *x = (arr+3);
printAfterX(arr, n, x);
return 0;
}
Change the printf line for this:
printf("%8d", *x);