C qsort strange behaviour - c

I'm trying to do the following:
Allocate memory for array of dimension 7
Write the first 4 positions
Sort those 4 positions.
Write the remaining 3 positions
Sort the entire array.
I have the array (1,6,2,3), which after sorting becomes (1,2,3,6)
Then I write the remaining positions, which are (1,2,3,6,1,5,1)
After sorting it, I should be getting (1,1,1,2,3,5,6), but instead I'm getting
(6,2,3,1,1,5,1).
Here is the code:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int comp(const void* a, const void* b);
typedef struct{
int peso;
}aresta_;
int main(int argc, const char * argv[]) {
aresta_* array /*struct array, has field peso of type int*/;
int dim=7;
int dim_aux=4;
int i;
array = (aresta_*) malloc(dim * sizeof(aresta_));
array[0].peso=1;
array[1].peso=6;
array[2].peso=2;
array[3].peso=3;
printf("First sort:\n");
for(i=0; i<dim_aux; i++)
printf("%d ",array[i].peso);
printf("\n");
qsort(array, dim_aux, sizeof(array[0]), comp);
for(i=0; i<dim_aux; i++)
printf("%d ",array[i].peso);
printf("\n\n");
array[4].peso=1;
array[5].peso=5;
array[6].peso=1;
printf("Second sort:\n");
for(i=0; i<dim; i++)
printf("%d ",array[i].peso);
printf("\n");
qsort(array, dim, sizeof(array[0]), comp);
for(i=0; i<dim; i++)
printf("%d ",array[i].peso);
printf("\n");
}
My comp function:
int comp(const void* a, const void* b)
{
aresta_* a1 = (aresta_*)a;
aresta_* b1 = (aresta_*)b;
return a1->peso > b1->peso;
}
The Output:
First sort:
1 6 2 3
1 2 3 6
Second sort:
1 2 3 6 1 5 1
6 2 3 1 1 5 1
Program ended with exit code: 0
Where did I go wrong? Any help would be greatly appreciated.

OP's function only returned 0 and 1. #Weather Vane
As this "worked" for OP for the first 4 values is "luck".
The compare function needs to return 1 of 3 results: negative, 0 or positive.
The function shall return an integer less than, equal to, or greater than zero if the first argument is considered to be respectively less than, equal to, or greater than the second.
C11dr ยง7.22.5.2 3
int comp(const void* a, const void* b)
{
const aresta_* a1 = (const aresta_*)a;
const aresta_* b1 = (const aresta_*)b;
// return a1->peso > b1->peso;
return (a1->peso > b1->peso) - (a1->peso < b1->peso);
}
return (a1->peso > b1->peso) - (a1->peso < b1->peso); has advantages over return a1->peso - b1->peso;. This answer does not overflow. It is valid and functionally correct for all pairs of int. Various compilers recognize this idiom and produce tight code. int - int can overflow which is undefined behavior, UB.

int comp(const void* a, const void* b)
{
aresta_* a1 = (aresta_*)a;
aresta_* b1 = (aresta_*)b;
----> return a1->peso > b1->peso; <---- Watch carefully out! What it does!
}
The return line just checks merely greater or not. If,
a1->peso is greater, it returns 1
b1->peso is greater, it returns 0 (It is also not right result because zero must mean equal)
What about equality case that the values equal each other?
You didn't check the last case. To do you can write with if-else cases like
if(a1->peso > b1->peso) {
// ....
} else if (a1->peso < b1->peso) {
// ....
} else {
// equality case....
}
or simply do return a1->peso - b1->peso giving expected result that
> 0 so positive
< 0 so negative
== 0 so equal each other
According to chux nicely drawing attention to overflow point, it can be handled for overflow case.
#include <limits.h>
if ((b1->peso > 0 && a1->peso < INT_MIN + b1->peso) ||
(b1->peso < 0 && a1->peso > INT_MAX + b1->peso)) {
/* Handle error */
} else {
return a1->peso - b1->peso;
}

Related

Is there any way to create loops based on user input?

I wanna create all possible 5 digit numbers that can be created from the numbers (0-7).
The code below achieves this, but is there any way to make this depend on user input?
The number of loops equals the number of digits I want and each individual loop must be:
for(1st number;condition<=last number;1st number++)
So, for five digits, I have:
for(i=0;i<8;i++){
for(j=0;j<8;j++){
for(k=0;k<8;k++){
for(m=0;m<8;m++){
for(n=0;n<8;n++){
printf("%d %d %d %d %d\n",i,j,k,m,n);
}
}
}
}
}
Keep iterators in an array and increment them manually.
#include <assert.h>
#include <stdio.h>
#include <string.h>
void callback(unsigned n, int i[n]) {
assert(n == 5);
printf("%d %d %d %d %d\n", i[0], i[1], i[2], i[3], i[4]);
}
void iterate(unsigned n, unsigned max, void (*callback)(unsigned n, int i[n])) {
// VLA, use *alloc in real code
int i[n];
memset(i, 0, sizeof(i));
while (1) {
for (int j = 0; j < n; ++j) {
// increment first number, from the back
++i[n - j - 1];
// if it didn't reach max, we end incrementing
if (i[n - j - 1] < max) {
break;
}
// if i[0] reached max, return
if (j == n - 1) {
return;
}
// if the number reaches max, it has to be zeroed
i[n - j - 1] = 0;
}
// call the callback
callback(n, i);
}
}
int main() {
// iterate with 5 numbers to max 8
iterate(5, 8, callback);
}
The beginning and ending of what the code prints:
0 0 0 0 0
0 0 0 0 1
...
...
7 7 7 7 6
7 7 7 7 7
If you want variable numbers of loops, you generally need to use recursion.
Say if you want n digits, with the ith digit be in the range of a[i],b[i], then you will do the following:
/* whatever */
int n;
int *a,*b,*number;
void recursion(int whichdigit){
if (whichdigit==n){
/* Say you managed to output number */
return;
}
for (int i=a[whichdigit];i<=b[whichdigit];i++){
number[whichdigit]=i;
recursion(whichdigit+1);
}
return;
}
int main(){
/* Say somehow you managed to obtain n */
a=malloc(n*sizeof(int));
b=malloc(n*sizeof(int));
number=malloc(n*sizeof(int))
if (!a||!b||!number){
/* unable to allocate memory */
}
/* Say somehow you managed to read a[i],b[i] for all i in 0..n-1 */
recursion(0);
return 0;
}
Warning: if you tries to have too many digits, you will likely get a segmentation fault or stack overflow error.

Base case of recursion function for Fibonacci sequence

I'm trying to write the function void fib(int arr[], int n), which would fill the array with Fibonacci numbers until index n.
I've tried to find base cases, and chose these:
void fib(int arr[], int num){
int arrLength = num + 1;
if(num<0){
return;
}else if(num == 0){
arr[num] = 1;
}else if(num == 1){
arr[num-1] = 1;
arr[num] = 1;
}
}
But, as you can see, I did not find recursive method itself.
Here's sample output, for example, for call fib(arr, 5):
0 1 2 3 4 5
1 1 2 3 5 8
My main function for testing case:
int main(){
int n = 10, i;
int arr[n+1];
fib(arr, n);
for(i=0;i<=10;i++){
printf("%i ", arr[i]);
}
return 0;
}
Is there any other way to make base cases more "elegant"? Also, I would truly appreciate hints using which I could fill the array with numbers starting from 2 with recursive option.
You question is asking for recursion but the program you write is just using function, because of this reason I am writing very basic code for your better understanding, you can improve this after understanding the flow and functionality or ask new question with some work.
Below one is a working code tested on TurboC, I am sharing complete test code.
#include <stdio.h>
#include<conio.h>
#define MAX 100
void fib(int *arr, int num, int a, int b, int term){
if(term == 0 && term <= num){
arr[term] = 1;
term++;
fib(arr,num,a,b,term);
}else if(term ==1 && term <= num){
arr[term] = 1;
term++;
fib(arr,num,a,b,term);
}else if(term <= num){
arr[term] = a+b;
term++;
fib(arr,num,b,a+b,term);
}
}
void main()
{
int firstTerm = 1;//First term of fibbo series
int secondTerm = 1;//Second term of fibbo series
int tracker = 0; // Tracker to track how much term we printed
int i;//To run loop here to check array after recursive function
int ar[MAX],n=5;// n is number of term we want to print
clrscr();
fib(ar,n,firstTerm,secondTerm,tracker);//recursive function call
// below is printing array to check
for(i=0;i<=n;i++){
printf("%d\t",ar[i]);
}
getch();
}
One thing I have to suggest is, if n is 5 then you just get 1 1 2 3 5, In code I did according to your requirement, so here it will print 1 1 2 3 5 8
I'd state that the "elegant" solution should be a simple loop, without any recursion, but let's see how it could be done in the less efficient and more error prone way.
// I'll assume that the function signature can't be changed
void fib(int arr[], int num)
{
// In the general case, use the well known recurrence relation.
if ( num > 1 )
{
// Use recursion here to calculate the previous elements of the array.
fib(arr, /* ... */);
// ^^^^^^^^^ Can you figure out what index should be passed here?
// Then, calculate the element at index num using the recurrence relation.
arr[num] = arr[num - 1] + arr[num - 2];
// ^^^^^^^ ^^^^^^^ Note the indices.
// Are those values alredy known?
}
// When num is 0 or 1, we can't use the general formula. Can you tell why?
else if ( num >= 0 )
{
fib(arr, /* ... */);
// ^^^^^^^^^ Same as before.
arr[num] = 1;
}
// If num is less than 0, it just do nothing.
}

Read an array recursively

I am learning how to apply recursion to arrays.
For example, I usually read arrays itiratively, this way:
void read_array(int *a, int n){
int i;
for(i = 0; i < n; ++i)
scanf("%d", &a[i]);
return;
}
I would like to read an array recursively. I wrote the following function:
void read_array(int *a, int n){
int i = n - 1;
if (n < 0)
return;
else{
if(scanf("%d", &a[n - 1 - i]) == 1){
read_array(a, n - 1);
return;
}
}
}
It compiles, but when running it trows a segmentation fault error. It confuses me since the function contemplates a base case 0 that should stop it.
Your calculation of the array index is wrong. This line:
if(scanf("%d", &a[n - 1 - i]) == 1){
assumes the initial value of n, but at the same time, you decrease n with every recursion step. That being said, it shouldn't crash but just repeatedly write the first element of a, because with i = n - 1, n - 1 - i is always zero.
The idiomatic way to write such a recursion would be to recurse on i:
void read_array(int *a, int n, int i)
{
if (i < n)
{
if(scanf("%d", &a[i]) == 1)
{
read_array(a, n, i+1);
}
}
}
and call it with the initial value for i, e.g. read_array(a, 10, 0) for reading a 10-element array.
In practice, recursion in C is to be avoided.*
* Functional languages can typically optimize recursion, C just uses the call stack with a lot of overhead.
In this example, the theoretical purpose of recursion for writing a pure function is somewhat defeated with a function returning void. If this is just about learning the principle, the functions actually should return something. You could for example create a functional "list builder":
#include <stdio.h>
#include <stdlib.h>
// place the side effect in a separate function
int getValue(void)
{
// could have `scanf()` here:
return rand();
}
typedef struct List
{
int a[10];
size_t length;
} List;
// non-functional helper to get around limitations of C:
// (if it could initialize result directly with the new values, it would
// be functional)
List listAppend(List list, int val)
{
List result = list;
result.a[result.length++] = val;
return result;
}
// recursive function without side effects:
List buildList(List list, int (*value)())
{
if (list.length >= 10) return list;
return buildList(listAppend(list, value()), value);
}
int main(void)
{
List myList = buildList((List){0}, &getValue);
for (size_t i = 0; i < myList.length; ++i)
{
printf("myList.a[%zu] is %d\n", i, myList.a[i]);
}
}
There is a bug in the function.
As the variable i is initialized the following way
int i = n - 1;
then the second argument in this call
scanf("%d", &a[n - 1 - i])
is evaluated like
scanf("%d", &a[n - 1 - (n - 1)])
that is it is always equal to zero
scanf("%d", &a[0])
As the recursive function is called with the same value of the pointer a then all entered values are assigned to a[0]. All other elements of the array are still uninitialized.
Though this does not serve as a reason for the abnormal execution of the function.
It is possible that there is used a big array and the stack is too small to call the function recursively.
In any case the function can be defined more simply and correctly the following way
size_t read_array( int *a, size_t n )
{
return n && scanf( "%d", a ) == 1 ? 1 + read_array( a + 1, n - 1 ) : 0;
}
Take into account as the input can be interrupted by the user. In this case the function returns the number of initialized elements of the array.
Here is a demonstrative program.
#include <stdio.h>
size_t read_array( int *a, size_t n )
{
return n && scanf( "%d", a ) == 1 ? 1 + read_array( a + 1, n - 1 ) : 0;
}
#define N 10
int main(void)
{
int a[N];
size_t n = read_array( a, N );
for ( size_t i = 0; i < n; i++ ) printf( "%d ", a[i] );
putchar( '\n' );
return 0;
}
If to enter sequence of numbers
0 1 2 3 4 5 6 7 8 9
then the output will be
0 1 2 3 4 5 6 7 8 9
Example:
int read_array_aux(int *i, int *n) {
if (i == n) {
return 0;
}
if (scanf("%d", i) != 1) {
return -1;
}
return read_array_aux(i + 1, n);
}
int read_array_aux2(int *a, size_t i, size_t n) {
if (i == n) {
return 0;
}
if (scanf("%d", a + i) != 1) {
return -1;
}
return read_array_aux2(a, i + 1, n);
}
int read_array(int *a, size_t n) {
return read_array_aux(a, a + n);
// return read_array_aux2(a, 0, n);
}
First, condition n<0 is wrong. Probably this is the cause of segfault.
Also, why even bother about calculating the index? When processing any kind of list recursively it's worth to grasp the concept of head (first element of list) and tail (everything except head) of the list. So, filling an array recursively would be defined as (in pseudo code):
void read_array() {
read_head();
read_tail();
}
What is head? It's the first element of current array. What's the tail? The array starting from next element. So, read_tail is equivalent of read_array, but with the beginning moved forward by one element.
And, finally, to gather everything into one place:
void read_array(int *a, int n) {
if(n<=0) {
return;
} else {
if(scanf("%d", a) == 1) {
read_array(a+1,n-1);
}
}
}
As other answers have mentioned, your handling of n is leading to problems. You can return 0 from the base case of sz == 0, otherwise return the result of the next recursive call, or -1 if scanf() fails. At each recursive call, increment a and decrement sz. The value returned in the calling function should be checked for input errors: 0 on success, -1 on failure.
Note that this is a tail recursion, which should be optimized by most good compilers.
#include <stdio.h>
int read_array(int *a, size_t sz);
int main(void)
{
int arr[5];
puts("Enter array elements:");
if (read_array(arr, 5) != 0) {
fprintf(stderr, "Input error\n");
} else {
for (size_t i = 0; i < 5; i++) {
printf("%8d", arr[i]);
}
putchar('\n');
}
return 0;
}
int read_array(int *a, size_t sz)
{
if (sz == 0 ) {
return 0;
}
if (scanf("%d", a) == 1){
return read_array(a + 1, sz - 1);
} else {
return -1;
}
}
Sample interaction:
Enter array elements:
1 2 3 4 5
1 2 3 4 5
Enter array elements:
1 2 3 x 5
Input error

Optimizing a recursive counting algorithm

I hate posting for homework help on here, but I've exhausted my abilities. I am faced with a Stack Overflow (at least thats what its called in Java) issue while writing a simple recursive function in C.
I need every r-permutation of n numbers, and I figured the best way to do that would be counting in base n to length r.
It works fine for smaller amounts of numbers, but the highest case (n=10, r=6) ends up running out of memory. I could easily have written this iteratively but its required to be recursion. Heres what I have so far:
int permute(int *tempArray, int amtNums, int goalLength, int totalMatches) {
totalMatches += 1; //Temporary, will be replaced by a function later
printArray(tempArray, goalLength);
tempArray[0]++;
int j = 0;
while(tempArray[j] >= amtNums) {
tempArray[j+1]++;
tempArray[j] = 0;
j++;
}
if(j+1 > goalLength) return totalMatches;
return permute(tempArray, amtNums, goalLength, totalMatches);
}
Being called as permute((int*)calloc(numSlots, sizeof(int)), 10, 6, 0); for the max case, n=10 r=6
I should Note: The counting isn't exactly intuitive, its a bit backwards but generates all the number combinations I wanted. As an example: n=4, r=3
0 0 0
1 0 0
2 0 0
3 0 0
0 1 0
1 1 0
2 1 0
3 1 0
.....
0 2 3
1 2 3
2 2 3
3 2 3
0 3 3
1 3 3
2 3 3
3 3 3
I belive that you have to modify your recursive function in order to have a maximum depth of the stack of function calls of goalLength. You can accomplish that adding a parameter depth like I did here:
int permute( int *tempArray, int amtNums, int goalLength, int depth, int totalMatches) {
int i;
if ( depth < goalLength - 1) {
for ( i = 0; i < amtNums; ++i ) {
tempArray[depth] = i;
totalMatches = permute(tempArray, amtNums, goalLength, depth + 1, totalMatches);
}
} else {
for ( i = 0; i < amtNums; ++i ) {
tempArray[depth] = i;
printArray(tempArray, goalLength);
++totalMatches;
}
}
return totalMatches;
}
You can of course rewrite it putting the for loop outside and the if inside. I tryed that code with this little test program:
#include <stdio.h>
#define NDIGIT 4
#define NLENGTH 3
void printArray( int *temp, int size ) {
int i;
for ( i = 0; i < size; ++i ) {
printf("%d ", temp[i]);
}
printf("\n");
}
int permute( int *tempArray, int amtNums, int goalLength, int depth, int totalMatches);
int main(void) {
int results[NLENGTH];
int n = permute(results, NDIGIT, NLENGTH, 0, 0);
printf("Total number of permutations: %d\n", n);
return 0;
}
Setting NDIGIT to 10, NLENGTH to 6 and commenting out the printing function (you can keep it if you want...) the program run fine and the output was:
Total number of permutations: 1000000
Your function uses a tail call to itself, the compiler should be able to turn this recursion into a loop. Enable optimisations with command line option -O3 or whatever your IDE provides. If the compiler implements the recursion, the function will recurse amtNumsgoalLength, which is a large number for n=10 and r=6: 1 000 000 recursion levels likely causes a Stack Overflow

Appending a value to the end of a dynamic array

Well I have been studying a little C this winter break and in my adventures I stumbled upon an issue with a Dynamic Array.
It's a fairly simple program really. What I am trying to do is to create an array that holds the numbers of the Fibonacci series. Here is the code:
#include <stdio.h>
#include <stdlib.h>
int dynamic_arry_append(int* arry, int* number, int* size);
int main() {
int i, n, size = 3, *arry = NULL, fibarr[size];
printf("Dynamic array, Fibonacci series. \n");
printf("Capture upto element: ");
scanf("%d", &n);
i = 0;
// passing the first elements
fibarr[0] = 0;
fibarr[1] = 1;
fibarr[2] = 1;
while ( i < n ) {
printf("**%d\n",fibarr[0]);
dynamic_arry_append( arry, &fibarr[0], &size );
fibarr[0] = fibarr[1];
fibarr[1] = fibarr[2];
fibarr[2] = fibarr[1] + fibarr[0];
i++;
}
for ( i = 0 ; i < size ; i++)
printf("Element %d of the array: %d.\n", i, arry[i]);
return 0;
}
int dynamic_arry_append(int* arry, int* number, int* size) {
int i;
int bacon = *size; // first name i thought of
bacon++;
int *new_addr = realloc(arry, bacon * sizeof(int));
if( new_addr != NULL ) {
arry = new_addr;
arry[bacon-1] = *number;
// printf for easier debugging, or so i thought
for ( i = 0 ; i < bacon ; i++ )
printf("%d\t%d\n", i+1, arry[i]);
printf("\n");
*size = bacon;
} else {
printf("Error (re)allocating memory.");
exit (1);
}
return 0;
}
At least in my mind this works. However, in practice I get funny results:
Dynamic array, Fibonacci series.
Capture upto element: 5
**0 // next fibonacci number
1 5256368
2 5246872
3 1176530273
4 0
**1
1 5256368
2 5246872
3 1768053847
4 977484654
5 1
**1
1 5256368
2 5246872
3 1551066476
4 1919117645
5 1718580079
6 1
**2
1 5256368
2 5246872
3 977484645
4 1852397404
5 1937207140
6 1937339228
7 2
**3
1 5256368
2 5246872
3 1551071087
4 1953724755
5 842231141
6 1700943708
7 977484653
8 3
/* Code::Blocks output */
Process returned -1073741819 (0xC0000005) execution time : 17.886 s
Press any key to continue.
I am really baffled by this error, and after searching around I found no solution...Can anyone help? Thank you very much.
#include <stdio.h>
#include <stdlib.h>
int * dynamic_array_append(int * array, int size);
int main() {
int i, n, size=0, *array = NULL;
printf("Dynamic array, Fibonacci series. \n");
printf("Capture upto element: ");
scanf("%d", &n);
for (i=0 ; i<n ; i++)
array = dynamic_array_append(array, i);
for (i=0 ; i<n ; i++)
printf("array[%d] = %d\n", i, array[i]);
return 0;
}
int * dynamic_array_append(int * array, int size)
{
int i;
int n1, n2;
int new_size = size + 1;
int * new_addr = (int *) realloc(array, new_size * (int)sizeof(int));
if (new_addr == NULL) {
printf("ERROR: unable to realloc memory \n");
return NULL;
}
if (size == 0 || size == 1) {
new_addr[size] = size;
return new_addr;
}
n1 = new_addr[size-1];
n2 = new_addr[size];
new_addr[new_size-1] = new_addr[new_size-2] + new_addr[new_size-3];
return new_addr;
}
/*
Output:
Dynamic array, Fibonacci series.
Capture upto element: 10
array[0] = 0
array[1] = 1
array[2] = 1
array[3] = 2
array[4] = 3
array[5] = 5
array[6] = 8
array[7] = 13
array[8] = 21
array[9] = 34
*/
Points to note:
The newly (re)allocated array should be returned back to main and stored in a pointer-to-int (or) pass pointer-to-pointer-to-int and update it accordingly once after reallocing
The fibarr is not needed. It doesn't solve any problem.
You don't have to pass the size and the number. Just send the size and it will pick the n-1 and n-2 to calculate n.
This is considered to be highly inefficient. Because if you know the n then you can allocate memory for n integers in one shot and calculate the fib series.
The problem may be that the arry pointer variable is passed by value to the function dynamic_arry_append. That means, that changes that you make to the arry variable within that function will not be reflected by any variables outside of that function. For example:
int *a = NULL;
someFunc(a);
// a will still be NULL here no matter what someFunc does to it.
You should declare your fibarr as a pointer (so name it differently) not an array. And you should pass to your dynamic_arry_append the address of that pointer, like &fibarr. And you should initialize fibarr in your main with calloc. At last you should dynamically update (and keep, and pass) the size of the allocated array.
You are not returning the new address of the array... and you are reading/writing not your memory. Run the program with all error messages under debugger and you'll see the problem is in this line:
dynamic_arry_append( arry, &fibarr[0], &size );

Resources