c standard library sort function from programming pearls - c

#include <algorithm>
#include <stdio.h>
#include <iostream>
int intcomp(int *x,int *y) { return *x-*y;};
int a[10000];
int main(void){
int i; int n=0;
while (scanf("%d",&a[n])!=EOF)
n++;
qsort(a,n,sizeof(int),intcomp);
for (int i=0;i<n;i++)
printf("%d\n",a[i]);
return 0;
}
it is just copy of code i have two question it show me that intcomp is incompatible in this code
and also what does intcomp function?
and also what is in windows 7 EOF? how tell program that it reached EOF?

the qsort() function requires a pointer with a particular signature.
Your function has the wrong signature so it is complaining.
Your function has the signature:
int intcomp(int *x,int *y)
While qsort requires the signature:
int intcomp(void const* xp,void const* yp)
Please note the difference in the parameter types.
A corrected version of the function is:
int intcomp(void const* xp,void const* yp)
{
// Modified for C as the tag on the question changed:
// int x = *static_cast<int const*>(xp);
// int y = *static_cast<int const*>(yp);
int x = *((int const*)(xp));
int y = *((int const*)(yp));
return x-y;
}
The function qsort() is passed a function pointer as the third parameter.
This function pointer (in your case intcomp()) is used to compare values in the array passed. Each call provides pointers into the array. The result of the function should be:
Less than 0: if x is smaller than y
0: If x is equal to y
Greater than 0: If x is larger than y

First of all: the question is labeled C++ and you #include <algorithm> and <iostream>, but your code is 100% C.
Martin York already gave the answer how to correct the signature of the function you pass to qsort().
However, the "true"(TM) C++ solution would be to use std::sort<> instead of qsort!
#include <algorithm>
#include <stdio.h>
bool intcomp(int a, int b) { return a<b; }
int a[10000];
int main(void){
int n=0;
while (scanf("%d",&a[n])!=EOF)
n++;
std::sort(&a[0], &a[n], intcomp);
for (int i=0;i<n;i++)
printf("%d\n",a[i]);
return 0;
}
Note that incomp() takes ints and not int pointers, and returns a bool. Just like operator<() would.
Also note that in this case, you could forget the intcomp and just use std::sort(&a[0], &a[n]), which will use std::less<>, which will use operator<(int, int).

intcomp is an "Int Compare" function. It is passed a pointer to 2 ints and returns 0 if they are the same, a positive value is x > y and a negative value is x < y.
qsort is passed a pointer to this function and calls it each time it wants to know how to sort a pair of values.
The docs for qsort should give you some more details.
eg http://www.cppreference.com/wiki/c/other/qsort

qsort is in stdlib.h, so include that file at the beginning. Note that algorithm and iostream aren't needed.
#include <stdlib.h>

As Martin York mentioned, qsort needs a function which it will use to compare the values:
void qsort( void *buf, size_t num, size_t size, int (*compare)(const void*, const void *) );
Here is a good example on how to use qsort: http://www.cppreference.com/wiki/c/other/qsort
Edit: Ri was faster....

Related

Change Array without returning it [C]

I just have a basic question concerning arrays in functions.
I am trying to change an array in a function without returning it.
I know how to do this for integers or doubles but i didn't know how to do this for arrays. So i experimented a little bit and now I am confused.
I have 2 variations of my code which i thought should do the same thing , but they don't. I pass the array b to the function Test. In the function I try to fill the array with the values 0, 1 ,2
#include <stdlib.h>
#include <stdio.h>
void Test(int * vector){
vector = malloc(3*sizeof(int));
int i;
for(i=0;i<3;i++){
*(vector+i)=i;
}
}
int main(){
int b[3];
Test(b);
printf("%i\n",b[0]);
printf("%i\n",b[1]);
printf("%i\n",b[2]);
return EXIT_SUCCESS;
}
This Version doesnt work, i don't get the expected result 0,1,2
This Code on the other hand does seem to work:
#include <stdlib.h>
#include <stdio.h>
void Test(int * vector){
int * b = malloc(3*sizeof(int));
int i;
for(i=0;i<3;i++){
*(b+i)=i;
*(vector+i) = *(b+i);
}
}
int main(){
int b[3];
Test(b);
printf("%i, ",b[0]);
printf("%i, ",b[1]);
printf("%i ",b[2]);
return EXIT_SUCCESS;
}
Can somebody explain to me why only the second one works?
Best Regards,
Rob
When you pass an array to a function, it decays into a pointer to the first element. That's what the function sees. But then you take the function parameter vector and overwrite it with dynamically allocated memory. Then you don't have access to the array you passed in. Additionally, you have a memory leak because you didn't free the allocated memory.
In the case of the second function you don't modify vector, so when you dereference the pointer you're changing b in main.
Also, instead of this:
*(vector+i)
Use this:
vector[i]
It's much clearer to the reader what it means.
test doesn't need to call malloc(). When you use an array as a function argument, it passes a pointer to the array. So you can simply write into vector[i] and it will modify the caller's array.
void Test(int * vector){
int i;
for(i=0;i<3;i++){
*(vector+i)=i;
}
}

Passing a multidimensional array of variable size

I'm trying to understand what "best practice" (or really any practice) is for passing a multidimensional array to a function in c is. Certainly this depends on the application, so lets consider writing a function to print a 2D array of variable size. In particular, I'm interested in how one would write the function printArry(__, int a, int b) in the following code. I have omitted the first parameter as I'm not exactly sure what that should be.
void printArry(_____, int a, int b){
/* what goes here? */
}
int main(int argc, char** argv){
int a1=5;
int b1=6;
int a2=7;
int a2=8;
int arry1[a1][b1];
int arry2[a2][b2];
/* set values in arrays */
printArry(arry1, a1, b1);
printArry(arry2, a2, b2);
}
The easiest way is (for C99 and later)
void printArry(int a, int b, int arr[a][b]){
/* what goes here? */
}
But, there are other ways around
void printArry(int a, int b, int arr[][b]){
/* what goes here? */
}
or
void printArry(int a, int b, int (*arr)[b]){
/* what goes here? */
}
Compiler will adjust the first two to the third syntax. So, semantically all three are identical.
And a little bit confusing which will work only as function prototype:
void printArry(int a, int b, int arr[*][*]);
This is not really an answer, but extended comment to the OP's comment question, "well you can pass the array without knowing the number of rows with this, but then how will you know when to stop printing rows?"
Answer: generally, you can't, without passing the array size too. Look at this 1-D example, which breaks the array size.
#include <stdio.h>
int procarr(int array[16], int index)
{
return array[index];
}
int main (void)
{
int arr[16] = {0};
printf("%d\n", procarr(arr, 100));
return 0;
}
Program output (although all elements initialised to 0):
768
That was undefined behaviour and there was no compiler warning. C does not provide any array overrun protection, except for array definition initialisers (although such initialisers can define the array length). You have to pass the array size too, as in
#include <stdio.h>
int procarr(int array[16], size_t index, size_t size)
{
if (index < size)
return array[index];
return -1; // or other action / flag
}
int main (void)
{
int arr[16] = {0};
printf("%d\n", procarr(arr, 100, sizeof arr / sizeof arr[0]));
return 0;
}
Program output:
-1

Initializing arrays and structures in a function

I am trying to initialize an array of elements to a finite value in a c function.
one way i know is to use a for loop to initialize those values but I am wondering if there is a simple way? I know that they can be initialized during array declaration though but I wouldn't prefer that way.
ex:
int a[10];
void foo(void)
{
for (int i=0; i<10;i++)
{
a[i] = 10;
}
}
Thanks
For the special case, that it is an char/byte array you could use the memset function:
#include <string.h>
void * memset ( void * ptr, int value, size_t num );
Attention: Thoug an 'int' is passed to memset, the ptr will increase in char/byte steps. So it is not suitable for an int array!
But you could use memfill:
#include <publib.h>
void *memfill(void *buf, size_t size, const void *pat, size_t patsize);
See http://manpages.ubuntu.com/manpages/saucy/man3/memfill.3pub.html for details. But it is probably not everywhere available.

Pass a 2D char array to a function in C

I'm a beginning programmer who is confused with passing a two dimensional array to a function. I think it may just be a simple syntax problem. I've looked for an answer, but nothing I've found seems to help, or is too far above my level for me to understand.
I identify the array and the function in the main function as, and after initializing it, attempt to call it:
#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>
int const ROWS = 8;
int const COLS = 8;
int main(int argc, char** argv) {
char board[ROWS][COLS];
bool canReach(char board[][], int i, int j);
//initialize array
//values of i and j given in a for loop
canReach(board, i, j);
return (EXIT_SUCCESS);
}
While writing the function outside the main function, I defined it exactly the same as I did in the main function.
bool canReach(char board[][], int i, int j){
//Functions purpose
}
When I attempt to build the program, I'm given this error twice and the program does not build:
error: array has incomplete element type 'char[][]'
bool canReach(char board[][], int i, int j)
^
Please note that I'm trying to pass the entire array to the function, and not just a single value. What can I do to fix this problem? I would appreciate it if it didn't have to use pointers, as I find them quite confusing. Also, I've tried to leave out things that I thought weren't important, but I may have missed something I needed, or kept in things I didn't. Thank you for your time in helping out this starting programmer!
You can just pass arrays as function arguments with definition of their size.
bool canReach(char board[ROWS][COLS], int i, int j);
When the size is unknown, pointers are the way.
bool canReach(char* board, int i, int j);
You should know, that arrays != pointers but pointers can storage the address of an array.
Here is a demonstrative program
#include <stdlib.h>
#include <stdio.h>
#include <stdbool.h>
bool canReach( int n, int m, char board[][m] )
{
for ( int i = 0; i < n; i++ )
{
for ( int j = 0; j < m; j++ )
{
board[i][j] = 0;
}
}
return printf( "Hello SaarthakSaxena" );
}
int main( void )
{
const int ROWS = 8;
const int COLS = 8;
char board[ROWS][COLS];
canReach( ROWS, COLS, board );
return EXIT_SUCCESS;
}
Its output is
Hello SaarthakSaxena
Defining a function inside another function (here: main) is not allowed in C. That is an extension of some compilers (e.g. gcc), but should not be used.
You have to specify the dimension of the array. C arrays do not have implicit size information as in HLL.
It also is not a good idea to use const variables for array dimensions in C. Instead
#define ROWS 8
#define COLS 8
Assuming i and j are the indexes of an element in the array, you can use the signature:
bool canReach(size_t rows, size_t cols, char board[rows][cols],
size_t i, size_t j);
This allows to pass arrays of (run-time) variable size to the function. If the dimensions are guaranteed fixed at run-time:
bool canReach(char board[ROWS][COLS], size_t i, size_t j);
But only if using the macros above. It does not work with the const variables.
Both versions tell the compiler which dimension the array has, so it can calculate the address of each element. The first dimension might be omitted, but there is nothing gained and it would imhibit optional bounds checking (C11 option). Note the 1D-case char ca[] is just a special version of this general requirement you can always omit the left(/outer)most dimension.
Note I changed the types to the (unsigned) size_t as that is the appropriate type for array-indexing and will generate a conversion warning if properly enabled (strongly recommended). However, you can use int, but have to ensure no value becomes negative.
Hint: If you intend to store non-character integers in the array or do arithmetic on the elements, you should specify the signed-ness of the char types. char as such can be either unsigned or signed, depending on implementation. So use unsigned char or signed char, depending what you want.

How pass(to function) by value variable size array?

First of all I know that array A degrades to pointer when we call function f(int a[]) and f(int *p) is same.
BUT:
1.I really need sending by value all array.
2.I really need that sending size is non const in function (but const size in plase we calling function)
I write some example:
http://ideone.com/ZbW0wT
#include <stdio.h>
#define SZ 15
typedef struct {int a[SZ];} rec;
int main(){
void pa(rec);
int value[SZ] ={9,8,7,6,5,4,3,2,1,0};
pa(*(rec*)value);
printf("%u %u\n",sizeof(rec),sizeof(value));
return 0;
}
void
pa(rec b){
int z;
for(z=0;z<SZ;z++){
printf("array[%2d] is %d\n",z,b.a[z]);
}
}
This code work for const size , but how change so pa would get by value some rec which size depend on passed array?
Update: it must by value sended , but not const sized as in Pascal etc , but in true C way , all pass by value not by pointer on 0 element
and function need universal so user can write func(variablesizeArrayOfT) where arg passed by value.
if possible need standard way (C11 or better C99 or better C89 or better K&R), if cant then gcc
UPD2: http://ideone.com/H4XGqC
#include
typedef struct{
int len;
int a[];
} av;
void f(av a){
while(a.len--){
printf("array[%2d] is %d\n",a.len,a.a[a.len]);
}
}
int main(){
int b[]={3,1,2,3};
int c[]={7,1,2,3,4,5,6,7};
f(*(av*)b);
f(*(av*)c);
return 0;
}
all good by probably bug in alignment so size(3 and 7) is right but value of a[] is not
UPD3 see throw gcc -g -c 2ndSRC.c &&objdump -d -M intel -S 2ndSRC.o
it just send only size (b[0] and c[0]) but not all array
An idiomatic way to have arrays containing data of variable length in C is to use a buffer with a maximum size which is known at compile time, is that what you wanted?
#include <stdio.h>
#define MAX_SIZE 15
typedef struct {
int arr[MAX_SIZE];
size_t arr_len;
} rec_t;
void pa(rec_t rec){
for(int z=0; z<rec.arr_len; z++){
printf("array[%2d] is %d\n", z, rec.arr[z]);
}
}
int main(void){
rec_t rec ={
.arr = {9,8,7,6,5,4,3,2,1,0},
.arr_len = 10
};
pa(rec);
}

Resources