Array-strings sorted using qSort in C - c

the question is simple: there is some way that the ordered array that returns me the "qsort", is returned in reverse, ie I want to avoid the use of any auxiliary array to invest the resulting array using qsort.
this is my code, which reads from standard input strings to be sorted, and uses a comparison function for sorting.
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <stdio.h>
#include <string.h>
int cstring_cmp(const void *a, const void *b)
{
const char **ia = (const char **)a;
const char **ib = (const char **)b;
return strcasecmp(*ia, *ib);
/* strcmp functions works exactly as expected from
comparison function */
}
Thanks in advance for your response, sorry for my English
int main (int argc, char *argv [])
{
int number;
char temp [4000];
printf("input number: ");
scanf("%d",&number);
char* array_string [number];
int i;
for (i=0;i<number;i++) {
scanf(" %[^\n]", temp);
array_string [i] = (char*)malloc((strlen(temp)+1)*sizeof(char));
strcpy(array_string[i], temp);
}
size_t large = sizeof(array_string) / sizeof(char *);
qsort(array_string,large ,sizeof(char *) ,cstring_cmp );
printf ("\n");
printf ("the sorted array list is:\n");
for (i=0;i<large;i++)
printf("%s\n", array_string [i]);
return 0;
}

Have you just tried reversing the order of parameters to strcasecmp?
return strcasecmp(*ib, *ia);

Does this do what you want?
int cstring_cmp(const void *a, const void *b)
{
const char **ia = (const char **)a;
const char **ib = (const char **)b;
return -strcasecmp(*ia, *ib);
/* return the negative of the normal comparison */
}

Related

Odd point issue by null pointer

I am doing a code practice using C language.
As below codes,
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define _CRT_SECURE_NO_WARNINGS
int ACDSort(const void *p1, const void *p2);
int Compare(const void *pKey, const void *pValue);
int main(void)
{
char * strAry[4] = {"Hardware","Cookie","Boy","Power"};
char * destStr = "Cookie";
//qsort((void*)strAry, sizeof(strAry) / sizeof(char*), sizeof(char*), ACDSort);
char **ptrAdr = (char**)bsearch((void*)destStr, strAry, sizeof(strAry) / sizeof(char*), sizeof(char*), Compare);
printf("%s\n", *ptrAdr);
}
int Compare(const void *pKey, const void *pValue) {
char *key = ((char*)pKey);
char *value = *((char**)pValue);
return strcmp(key, value);
}
int ACDSort(const void *p1, const void *p2) {
char * n1 = *((char**)p1);
char * n2 = *((char**)p2);
int ret;
if (strlen(n1) > strlen(n2))
ret = 1;
else if (strlen(n1) < strlen(n2))
ret = -1;
else
ret = 0;
return ret;
}
I called bsearch to find the string of cookie.
The problem is that the error occurred when I erased the // in order to sort the array based on the string length.
I don't know why the error was executed because I think that qsort couldn't be able to significant affect to my codes.
Could you tell me the reason why the error occurred returning null pointer when erasing the //?
Ps. I used qsort and bsearch to get familiar with pointer variables.
bsearch uses binary search, that's why. Binary search requires the data to be sorted. Sort the string array in alphabetic order and it will work.
As a side note, you need to get rid of all those superfluous casts, all they do is to hide potential bugs.
Working program after fixes and clean-up:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int compare (const void* p1, const void* p2);
int main (void)
{
const char* strAry[4] = {"Boy", "Cookie", "Hardware", "Power"};
const char* key = "Cookie";
char** ptrAdr = bsearch(key,
strAry,
sizeof(strAry)/sizeof(*strAry),
sizeof(*strAry),
compare);
printf("%s\n", *ptrAdr);
}
int compare (const void* p1, const void* p2)
{
const char* s1 = p1;
const char* s2 = *(const char* const*)p2;
return strcmp(s1, s2);
}
p2 will end up a const void pointer to a const char*, which is why we get that weird-looking cast when striving for const-correctness.
Type of destStr can be changed to be the same as type of strAry, e.g.:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int Compare(const void *pKey, const void *pValue)
{
char *key = *((char**)pKey);
char *value = *((char**)pValue);
return strcmp(key, value);
}
int main(void)
{
char * strAry[4] = { "Hardware", "Cookie", "Boy", "Power" };
char * destStr[1] = { "Cookie" }; // Type changing
qsort(strAry, sizeof(strAry) / sizeof(char*), sizeof(char*), Compare);
char **ptrAdr = (char**)bsearch((void*)destStr, strAry, sizeof(strAry) / sizeof(char*), sizeof(char*), Compare);
printf("%s\n", *ptrAdr);
}
Also, if you use C language (and compiler) consider using strcmp directly as callback function that compares two elements.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
/*int Compare(const void *pKey, const void *pValue)
{
char *key = *((char**)pKey);
char *value = *((char**)pValue);
return strcmp(key, value);
}*/
int main(void)
{
char * strAry[4] = { "Hardware", "Cookie", "Boy", "Power" };
char * destStr[1] = { "Cookie" }; // Type changing
//qsort(strAry, sizeof(strAry) / sizeof(char*), sizeof(char*), Compare);
qsort(strAry, sizeof(strAry) / sizeof(char*), sizeof(char*), strcmp);
//char **ptrAdr = (char**)bsearch((void*)destStr, strAry, sizeof(strAry) / sizeof(char*), sizeof(char*), Compare);
char **ptrAdr = (char**)bsearch(destStr, strAry, sizeof(strAry) / sizeof(char*), sizeof(char*), strcmp);
printf("%s\n", *ptrAdr);
}
Note:
This solution has one disadvantage that appears as ...
warning: passing argument 5 of ‘bsearch’ from incompatible pointer type [enabled by default]
But it works (I have tried with GCC version 4.8.2 and MS Visual studio 12.0)

C - Pass Array of Strings as Function Parameter

I need to pass a pre-allocated array of strings as a function parameter, and strcpy() to each of the strings within the string array, as in this example:
static void string_copy(char * pointer[]) {
strcpy(pointer[0], "Hello ");
strcpy(pointer[1], "world");
}
int main(int argc, const char * argv[]) {
char my_array[10][100];
string_copy(my_array);
printf("%s%s\n", my_array[0], my_array[1]);
}
And the resulting printed string would be 'Hello world'.
How do I pass a pre-allocated string array and fill out each string within a function as shown above?
When you are doing string_copy(my_array), you are passing a char (*)[100], i.e. pointer to char[100] array to your function. But your function is expecting a char *[], i.e. array of char pointers, because you have defined your function that way.
You can fix this by making changes so that your function (string_copy()) expects a char (*)[100], instead of a char *[].
For this, you can change your function definition as:
/* Your my_array gets converted to pointer to char[100]
so, you need to change your function parameter
from `char *pointer[]` to `char (*pointer)[100]`
*/
/* static void string_copy(char *pointer []) */
static void string_copy(char (*pointer) [100])
{
strcpy(pointer[0], "Hello ");
strcpy(pointer[1], "world");
}
* Alternative Solution *
A different design/solution would be to change in your main() function so that you are actually passing a char *[], which decays into a char ** - which is fine - to string_copy(). This way you would NOT have to change your string_copy() function.
int main(int argc, const char * argv[]) {
char my_array[10][100];
int tot_char_arrs, i;
char *char_arr_ptr[10];
/* Get total number of char arrays in my_array */
tot_char_arrs = sizeof(my_array) / sizeof(my_array[0]);
// Store all char *
for (i = 0; i < tot_char_arrs; i++)
char_arr_ptr[i] = my_array[i];
/* Actually passing a char *[].
it will decay into char **, which is fine
*/
string_copy(char_arr_ptr);
printf("%s%s\n", my_array[0], my_array[1]);
}
you need to use a pointer to the array. here is an example with 1 dimension array:
#include <stdio.h>
#include <stdbool.h>
#include <string.h>
static void string_copy(char **pointer) {
strcpy(pointer[0], "Hello ");
}
int main(int argc, const char * argv[]) {
char my_array[10];
char * p_array = my_array;
string_copy(&p_array);
printf("%s\n", my_array);
}
Your function can simply accept matrix dimensions and pass a const char * that stores the array of literals (pre-allocated) strings:
#include <stdio.h>
#include <string.h>
#define STRINGS_LENGTH 100
static void string_copy(size_t n, size_t m, char pointer[n][m], const char *strings_to_copy[])
{
for (size_t i=0; i< n; i++)
{
strcpy(pointer[i], strings_to_copy[i]);
}
}
int main( void )
{
const char *strings[] = { "hello", "World" };
char my_array[sizeof(strings)/sizeof(strings[0])][STRINGS_LENGTH];
string_copy(sizeof(strings)/sizeof(strings[0]), STRINGS_LENGTH, my_array, strings);
printf("%s %s\n", my_array[0], my_array[1]);
}
You can also change the structure of your code using dynamic allocation for your output array like:
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <stdbool.h>
static bool string_copy(char *pointer[], const char *strings_to_copy[], size_t strings)
{
for (size_t i=0; i< strings; i++)
{
pointer[i] = malloc(strlen(strings_to_copy[i])+1);
if (pointer[i] != NULL)
strcpy(pointer[i], strings_to_copy[i]);
else
return false;
}
return true;
}
int main(void)
{
const char *strings[] = { "hello", "World" };
char *my_array[sizeof(strings)/sizeof(strings[0])] = {0};
if (string_copy(my_array, strings, sizeof(strings)/sizeof(strings[0])) )
{
printf("%s %s\n", my_array[0], my_array[1]);
}
for (size_t i = 0; i<sizeof(strings)/sizeof(strings[0]); i++)
free (my_array[i]);
}

sort a 2d array using qsort - seg fault

I'm trying to sort a 2d array of strings a simplified version looks like,
( I dont want to change the datatype of "nameArray" to "char *nameArray[4]" )
#include <sys/types.h>
#include <stdio.h>
int cstring_cmp(const void *a, const void *b)
{
const char **ia = (const char **)a;
const char **ib = (const char **)b;
return strcasecmp(*ia, *ib);
}
int Test()
{
char nameArray[4][10]={"test","alpha","Hyper","city"};
// int nElem = sizeof(nameArray)/sizeof(char *);
int index = 0;
//printf("nElem =%d\n", nElem);
for(index=0; index < 4; index++)
{
printf("-> %s\n", nameArray[index]);
}
qsort( &nameArray[0], 4, sizeof(nameArray[0]), cstring_cmp);
printf("After sort\n");
for(index=0; index < 4; index++)
{
printf("-> %s\n", nameArray[index]);
}
return 0 ;
}
(
UPDATE: changed so that I'm directly using the value(4) instead of calculating nElem. My problem is getting the qsort to working. )
The arguments to the comparison function are just pointers, rather than pointers to pointers.
You also don't need to cast I believe, since the parameters are void *, you can just assign them to the local variables and the compiler takes care of them.
Try this:
int cstring_cmp(const void *a, const void *b)
{
const char *ia = a;
const char *ib = b;
return strcasecmp(ia, ib);
}
Or even get rid of the local variables if you don't need them (only need them if you're planning on adding more code to the comparison function):
int cstring_cmp(const void *a, const void *b)
{
return strcasecmp(a, b);
}
int cstring_cmp(const void *a, const void *b)
{
return strcmp(a, b);
}

Unable to sort a list of strings alphabetically in C

I wrote a program to accept 5 strings from user and then display them sorted alphabetically using bubble-sort algorithm. But, the strings are being displayed in the same order as they were entered. Please tell me what am I doing wrong here.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
void sSwap(char *s1, char *s2);
int main(){
char *sList[5],input[100],*p;
int i,j;
puts("Enter 5 strings");
for(i=0;i<5;i++){
gets(input);
sList[i] = (char *)malloc(strlen(input)+1);
strcpy(sList[i],input);
}
puts("");
for(i=3;i>=0;i--){
for(j=0;j<=i;j++){
if(strcmp(sList[j],sList[j+1])>0)
sSwap(sList[j],sList[j+1]);
}
}
for(i=0;i<5;i++)
puts(sList[i]);
return 0;
}
void sSwap(char *s1, char *s2){
char *temp;
temp = s1;
s1 = s2;
s2 = temp;
}
as you were told, your swap function getting values and swap them by value, meaning that when you leave the function the changes will not be saved and old values will return. try this
void sSwap(char **s1, char **s2);
int main(){
char *sList[5],input[100],*p;
int i,j;
puts("Enter 5 strings");
for(i=0;i<5;i++){
gets(input);
sList[i] = (char *)malloc(strlen(input)+1);
strcpy(sList[i],input);
}
puts("");
for(i=3;i>=0;i--){
for(j=0;j<=i;j++){
if(strcmp(sList[j],sList[j+1])>0)
sSwap(&sList[j],&sList[j+1]);
}
}
for(i=0;i<5;i++)
puts(sList[i]);
return 0;
}
void sSwap(char **s1, char **s2){
char *temp;
temp = *s1;
*s1 = *s2;
*s2 = temp;
}
One of your problem is that when you swap two strings, you doesn't check if you have to swap it with the new neighboors of this string.
So I would do a recursive function to solve this. Like if you swap, you call the function (let's say void sort(char **list, int index)) :
sort(sList, 0) //to start from beginning and check the new order
If the strings are equals or in the right order, like :
sort(sList, currentListIndex);
So you would have :
void sort(char **sList, int index) {
if (sList[index+1]) {
if (strcmp(sList[index],sList[index+1]) > 0){
sSwap(sList, index); // you can swap direclty on the tab
return sort(sList, 0);
}
return sort(sList, index+1);
}
return void;
}
sort(sList, 0);
It's been a while i didn't do C so maybe pointers are wrong, but it's the idea
The qsort function is in the stdlib.h
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
you define the number of elements in array
#define n_array sizeof(array)/sizeof(const char *)
and the comparison function
static int compare (const void * a, const void * b)
{
return strcmp (*(const char **) a, *(const char **) b);
}
and then in main you should use, replacing sSwap
qsort (array, n_array, sizeof (const char *), compare);

qsort of struct array not working

I am trying to sort a struct run array called results by a char, but when I print the array, nothing is sorted. Have a look at this:
struct run {
char name[20], weekday[4], month[10];
(And some more...)
};
typedef struct run run;
int name_compare(const void *a, const void *b)
{
run *run1 = *(run **)a;
run *run2 = *(run **)b;
return strcmp(run1->name, run2->name);
}
int count_number_of_different_persons(run results[])
{
int i = 0;
qsort(results, sizeof(results) / sizeof(run), sizeof(run), name_compare);
for(i = 0; i <= 999; i++)
{
printf("%s\n", results[i].name);
}
// not done with this function yet, just return 0
return 0;
}
The output from the above is just a list of names in the order they were originally placed
int count_number_of_different_persons(run results[])
This doesn't really let you use sizeof on the array, because array is decayed to pointer.
This
run *run1 = *(run **)a;
also looks weird, shouldn't it be
run *run1 = (run*)a;
?
One problem is in name_compare. Try this instead:
int name_compare(const void *a, const void *b)
{
run *run1 = (run *)a;
run *run2 = (run *)b;
return strcmp(run1->name, run2->name);
}
Check the following code:
As #michel mentioned, sizeof(array) provides size of the pointer, not the size of the array itself, as while passing array it is treated as a pointer. Hence either send the number of elements to the function count_number_of_different_persons or define a MACRO of number of elements. Hope this helps. :).
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define NOE 3
struct run
{
char name[20];
};
typedef struct run run;
int name_compare (const void *a, const void *b )
{
return strcmp (((run *)a)->name, ((run *)b)->name);
}
int count_number_of_different_persons(run results[], int noOfElements)
{
int i=0;
qsort(results, noOfElements, sizeof (run), name_compare);
for (i=0; i<noOfElements; i++)
printf ("%s\n",results[i].name);
}
int main ( int argc, char * argv[])
{
run a, b, c;
run arg[NOE];
strcpy (a.name, "love");
strcpy (b.name, "you");
strcpy (c.name, "i");
arg[0] = a;
arg[1] = b;
arg[2] = c;
count_number_of_different_persons(arg, sizeof(arg)/sizeof(run));
};

Resources