I have a structure that contains a field for student names. I'd like to order the names alphabetically. Here is the list of names that are stored into the name field of the structure:
Thui Bhu
Ariana B. Smith
Emily Gonzales
Jennifer L
Maria Jones
Bill Gates
Escobar Morris
Anne Latner
Here is the way I am defining the structure:
struct studentData {
char name[30];
int quiz1; int quiz2;
int quiz3; int quiz4;
int mid1; int mid2;
int finalexam;
} ;
Here is the code I have tried using to sort:
void SortNames(struct studentData *record, int reccount)
{
int j,i;
struct studentData temp;
for(i = 1; i < reccount; i++)
{
j = i - 1;
while( j >= 0 && strcmp( record[j+1].name, record[j].name) < 0 )
{
temp = record[j + 1]; /*errors*/
record[j+1] = record[j];
record[j] = temp; /*errors*/
j--;
}
printf("%s",record[j].name);
}
return;
}
This is the output that I am getting:
Ariana B. SmithEmily GonzalesJennifer LAriana B. SmithEmily Gonzales
Please help! I am open to using any built-in functions.
Call qsort().
#include <stdlib.h>
#include <string.h>
int cmp(const void *l, const void *r)
{
return strcmp(((struct studentData*)l)->name, ((struct studentData*)r)->name);
}
void SortNames(struct studentData *record, int reccount)
{
int i;
qsort(record, reccount, sizeof(struct studentData), cmp);
for (i = 0; i < reccount; ++i) {
printf("%s\n", record[i].name);
}
}
Unless you need to create your own sort routine, the best approach is probably using the qsort function to sort the structs by name. When using qsort your task is simply to create a comparator funciton that takes a void pointer to type struct studentData and creates a way to compare by the member of interest (here name)
The qsort comparison funciton returns type int. For your struct it would look something like:
/* qsort struct comparision function (struct studentData by name) */
int struct_cmp_by_name (const void *a, const void *b)
{
struct studentData *ia = (struct studentData *)a;
struct studentData *ib = (struct studentData *)b;
return strcmp (ia->name, ib->name);
}
(Note - you don't have qutie enough code posted to be exact, but it will be close to being) called in your code as:
qsort (record, number_structs, sizeof (struct studentData), struct_cmp_by_name);
This will sort records by the member name.
Related
So I have a struct that I want to sort by each element, ascending and descending.
I'm creating 14 different sort function because I don't know how to pass struct element as a function argument.
I want to cut it to 2 sort function ascending & descending, so I don't have 14 functions.
How do I deal with this?? Thanks in advance!
struct propertySales{
unsigned int tanggal[3];
char pelanggan[30];
char jenisProperty[30];
char namaProperty[30];
int jumlahProperty;
double hargaProperty;
double totalPembayaran;
}Arr[100], compare[100], temp;
void sort_totalPembayaran_descending(){
int currentIndex=index_counter();
for(int i=0; i<(currentIndex-1); i++){
for (int j=0; j<(currentIndex-i-1); j++){
if (compare[j].totalPembayaran < compare[j+1].totalPembayaran){
swap(&compare[j], &compare[j+1]);
}
}
}
system("cls");
printf("Sorting berdasarkan total pembayaran (Descending)\n");
print_column();
print_data(compare);
}
If you wish to sort by the totalPembayaran field, then you want to create a comparison function which takes two void pointers to propertySales structs.
int compare_totalPembayaran_asc(const void *a, const void *b) {
struct propertySales *c = (struct propertySales *)a;
struct propertySales *d = (struct propertySales *)b;
if (c->totalPembayaran < d->totalPembayaran)
return -1;
else if (c->totalPembayaran > d->totalPembayaran)
return 1;
else
return 0;
}
Now you can provide this to qsort to sort your array in ascending order.
qsort(arr, 100, sizeof(propertySales), compare_totalPembayaran_asc);
Comparing in descending order just requires writing another comparison function and changing the values returned.
int compare_totalPembayaran_desc(const void *a, const void *b) {
struct propertySales *c = (struct propertySales *)a;
struct propertySales *d = (struct propertySales *)b;
if (c->totalPembayaran < d->totalPembayaran)
return ...;
else if (c->totalPembayaran > d->totalPembayaran)
return ...;
else
return 0;
}
It's supposed to sort students in alphabetical order by their last names. I tried to do it with
qsort, but it doesn't work.
struct student {
char name[30];
char lastName[30];
char grades[30][5];
int numberOfGrades;
};
int compare(const void *a, const void *b) {
struct group *s1 = (struct group *)a;
struct group *s2 = (struct group *)b;
return strcmp(s1->lastName, s2->lastName);
}
int main()
{
struct student group[30];
group[0].lastName = "Malaska";
group[1].lastName = "Kowalski";
group[2].lastName = "Adamczyk";
group[3].lastName = "Bakiewicz";
int numberOfStudents = 4;
qsort(group, numberOfStudents, sizeof(group), compare);
}
The following is an adaptation of your code with corrections and comments:
struct student {
char name[30];
char lastName[30];
char grades[30][5];
int numberOfGrades;
};
//Note, error incomplete type occurs
//when using `struct group *s1 = (struct group *)a;`
//will replace with `struct student`
int compare(const void *a, const void *b) {
const struct student *s1 = (struct student *)a;
const struct student *s2 = (struct student *)b;
return strcmp(s1->lastName, s2->lastName);
}
int main()
{
struct student group[30];//local scope, will not be recognized in 'compare()'
strcpy(group[0].lastName, "Malaska");//string assignments need to use strcpy or similar, not =
strcpy(group[1].lastName, "Kowalski");
strcpy(group[2].lastName, "Adamczyk");
strcpy(group[3].lastName, "Bakiewicz");
int numberOfStudents = 4;
//sending correct size of each element
qsort(group, numberOfStudents, sizeof(group[0]), compare);
// ^^^^^^^^^^^^^^^^^
}
The following is also an adaptation of your code, but with some additional changes to construct that if in scope of what you are learning, should provide a few more examples of readability, use of scope, use of typedef, and dynamic memory allocation and freeing...
typedef struct { //use of `typedef struct {` rather than 'struct name {`
char name[30];
char lastName[30];
char grades[30][5];
int numberOfGrades;
}student_s; //new type, can be used in place of `struct student` anywhere.
int compare(const void *a, const void *b) {
const student_s *s1 = (student_s *)a;
const student_s *s2 = (student_s *)b;
return strcmp(s1->lastName, s2->lastName);
}
int main()
{
int numberOfStudents = 4;//moved to top so can use group
//to properly size instances of group
//dynamic memory allocation, and clean up at bottom
student_s *group = calloc(numberOfStudents, sizeof *group);
if(group)//test here to ensure success
{
strcpy(group[0].lastName, "Malaska");
strcpy(group[1].lastName, "Kowalski");
strcpy(group[2].lastName, "Adamczyk");
strcpy(group[3].lastName, "Bakiewicz");
qsort(group, numberOfStudents, sizeof(group[0]), compare);
//... more code as necessary
//when finished with 'group', free it.
free(group);
}
}
What i want to do here is to sort an Array of pointers to Structs based on a string inside the Struct .I thought it would be easy to only swapp the pointers inside the array instead of swapping the whole struct . All the Element are dynamically allocated . My code is written in German so i will be writing only the parts that i don't understand in English . thank you in advance I appreciate your help.
typedef struct Vehicle {
char *manufacturer;
char *serialnumber;
int weight;
};
void SortByID(struct fahrzeug** data, int Anzahl){
struct Vehicle *temp= (struct Vehicle*)malloc( sizeof(struct Vehicle) );
int i =0 ;// I think i've written something wrong here ( strcmp)
while ( i < Anzahl && strcmp(data[i]->serialnumber, data[i+1]->serialnumber) < 0)
{
temp = data[i+1];
data[i+1] = data[i];
data[i]=temp ;
i++;
}
free(temp);
temp=NULL;
}
int main(){
int count =0 ;
struct Vehicle **array = NULL ;
array=(struct Vehicle**)malloc( 5 * sizeof(struct Vehicle*) );
for(int i=0;i<5 ;i++){
array[i] = (struct Vehicle*)malloc( sizeof(struct Vehicle) ) ;
count++;
}
SortByID ( &array, count ) ; // is this right ?
return 0;
}
I've also tried to sort it using the qsort function but without success
int compare(const void *a, const void *b) {
struct Vehicle * const *one = a;
struct Vehicle * const *two = b;
return strcmp((*one)->serialnumber, (*two)->serialnumber);
}
void SortByID(struct Vehicle** data, int Anzahl){
qsort( data, Anzahl, sizeof(struct Vehicle*) ,compare );
}
Here's a working example using qsort(). It can sort by serial number and manufacturer.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
struct Vehicle {
char *manufacturer;
char *serialnumber;
int weight;
};
int cmp_serialnumber(const void *p1, const void *p2)
{
const struct Vehicle *v1 = *(struct Vehicle * const *)p1;
const struct Vehicle *v2 = *(struct Vehicle * const *)p2;
return strcmp(v1->serialnumber, v2->serialnumber);
/*
// Alternatively You could write this function as this less readable one liner
return strcmp((*(struct Vehicle * const *)p1)->serialnumber,
(*(struct Vehicle * const *)p2)->serialnumber);
*/
}
int cmp_manufacturer(const void *p1, const void *p2)
{
const struct Vehicle *v1 = *(struct Vehicle * const *)p1;
const struct Vehicle *v2 = *(struct Vehicle * const *)p2;
return strcmp(v1->manufacturer, v2->manufacturer);
}
void print_vehicles(struct Vehicle **vehicles, int n) {
for (int i=0; i<n; i++) {
printf("%s, %s, %d\n", vehicles[i]->serialnumber,
vehicles[i]->manufacturer, vehicles[i]->weight);
}
}
#define N_VEHICLES 5
char *manufacturers[] = {"McLaren", "Ferrari", "Renault", "Mercedes", "Alfa Romeo"};
char *serialnumbers[] = {"SN500", "SN4", "SN8", "SN2", "SN1"};
int main(){
struct Vehicle **vehicles = NULL;
vehicles = (struct Vehicle**)malloc(N_VEHICLES * sizeof(struct Vehicle *));
for(int i=0; i<N_VEHICLES; i++) {
vehicles[i] = (struct Vehicle *)malloc(sizeof(struct Vehicle));
vehicles[i]->manufacturer = manufacturers[i];
vehicles[i]->serialnumber = serialnumbers[i];
vehicles[i]->weight = 1000;
}
printf("Before\n");
print_vehicles(vehicles, N_VEHICLES);
printf("\n");
// sort by serial number
qsort(vehicles, N_VEHICLES, sizeof(struct Vehicle *), cmp_serialnumber);
printf("Sorted by serial number\n");
print_vehicles(vehicles, N_VEHICLES);
printf("\n");
// sort by manufacturer
qsort(vehicles, N_VEHICLES, sizeof(struct Vehicle *), cmp_manufacturer);
printf("Sorted by manufacturer\n");
print_vehicles(vehicles, N_VEHICLES);
return 0;
}
I have a problem to sort an array (dynamically allocated) in a structure. Firstly, the idea was to order the array i in the structure in an ascendant order. Then I was thinking to order the array i maintaining instead the array j with the same "relationship" obtained when it was constructed the initial structure. I try to work for the first idea, but without any result with qsort.So this is my code... Any ideas? I think there is a problem in the construction of the comparing function..
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <math.h>
int M =10;
int N =30;
int K = 10;
struct element {
int *i;
int *j;
int k;
};
struct element *create_structure();
void print_element(struct element *);
int compare (const void *, const void * );
struct element * sort(struct element *);
main()
{
srand(time(NULL));
struct element *lista;
int count;
lista=create_structure();
print_element(lista);
printf("\n");
lista=sort(lista);
}
struct element *create_structure()
{
int aux1,aux2,count,load;
struct element *structure;
structure = (struct element *) malloc (M*sizeof(struct element *));
structure->k=K;
structure->i= (int *)malloc(structure->k*sizeof(int));
structure->j=(int *)malloc (structure->k*sizeof(int));
for (count = 0; count < K; count ++)
{
aux1=rand()%N;
(structure->i)[count]=aux1;
do
{
aux2=rand()%N;
}while(aux2==aux1);
(structure->j)[count]=aux2;
}
return (structure);
}
void print_element(struct element *lista)
{
int count;
for(count = 0; count < K; count ++)
{
printf("%d %d\n",lista->i[count],lista->j[count]);
}
}
int compare(const void *a, const void *b)
{
struct element *ia = (struct element *)a;
struct element *ib = (struct element *)b;
int *ptr1=(ia->i);
int *ptr2=(ib->i);
return (*ptr1-*ptr2);
}
struct element * sort(struct element *list)
{
qsort(list, sizeof(list->i)/ sizeof(int) , sizeof(list->i), compare);
//qsort(list->i, K, sizeof(list->i), compare);
print_element(list);
return (list);
}
Sorry for being late to the party ! :)
So let's start first by mentioning the wrong statements in your code
>> First
in function create_structure() you want to allocate memory for your structure pointer
struct element *structure; // here your structure pointer is
//pointing to memory space of type struct element
structure = (struct element *) malloc (M*sizeof(struct element *));
|------------------------|
|
V
Here you are allocating memory space of type struct element* which is
wrong ! instead it must be sizeof(struct element)
Concerning the while loop in the same function I found that it is totally useless
aux1=rand()%N;
(structure->i)[count]=aux1; // the value is in aux1 variable
do
{
aux2=rand()%N;
}while(aux2==aux1); // the loop try to get the same value of aux1
// or you have just stored it in aux1
(structure->j)[count]=aux2; // it is easy to delete the while loop and
// change aux2 by aux1
>> Second
Concerning the sort
qsort(list, sizeof(list->i)/ sizeof(int) , sizeof(list->i), compare);
|-----|
|
V
It is not an adress of the array so it is Wrong !
after knowing the major problems here is a version of code based on your own code which works perfectly
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <math.h>
int M =10;
int N =30;
int K = 10;
struct element {
int *i;
int *j;
int k;
};
struct element *create_structure();
void print_element(struct element *);
int compare (const void *, const void * );
void sort(struct element *); // changed the return value of sort
// to void as the argument will be changed directly because it is a
// pointer
int main()
{
srand(time(NULL));
struct element *lista;
lista=create_structure();
printf("\n--------- i --- j ---------\n\n");
print_element(lista);
printf("\n---------------------------\n");
sort(lista);
print_element(lista);
return 0;
}
struct element *create_structure()
{
int aux1=0,count=0;
struct element *structure;
// Changed the allocation of structure pointer
structure = (struct element *) malloc (sizeof(struct element));
structure->k=K;
structure->i= (int *)malloc(K*sizeof(int));
structure->j=(int *)malloc (K*sizeof(int));
for (count = 0; count < K; count ++)
{
aux1=rand()%N;
// we kept only the first aux1 and copied it in the two arrays
(structure->i)[count]=aux1;
(structure->j)[count]=aux1;
}
return (structure);
}
void print_element(struct element *lista)
{
int count=0;
for(count = 0; count < K; count++)
{
printf("row=%2d : %2d %2d\n",count+1,(lista->i)[count],(lista->j)[count]);
}
}
int compare(const void *a, const void *b)
{
// compare the values of two case of array pointed by i of type int
return *(int*)a-*(int*)b;
}
void sort(struct element *list)
{
// we will sort the array pointed by i which contains K elements
// of type int and size sizeof(int) by using the compare function
qsort(list->i, K , sizeof(int), compare);
}
Hope it helps ! :)
Note: Using this code in codeblocks v13.12 generates under linux (gcc version 4.8.2) wrong output !! [ It might be a BUG in Code::Blocks]
but using it with command line with gcc gives correct output !!
So I'm attempting to implement a hash table that will hash structures containing words.
the structures will be similar to this:
#ifndef HASHTABLE_H
#def HASHTABLE_H
typedef int (*HashFunctionT) (char* string, int upperbound);
struct node_
{
char * word;
struct node * next;
}
typedef struct node_ * node;
struct nodehash_
{
int size;
struct node * hash[100];
}
typedef struct nodehash_ * nodehash;
Hashtable createHashTable();
void addtohash(node list, nodehash hash);
#endif
And I want the hash function to work something like this:
#include "hashtable.h"
int hashFunction(char *word, int hashTableSize)
{
int length = strlen(word);
int h = 0;
int i;
for(i = 0; i<length; i++)
{
h=31 *h + word[i];
}
return h % hashTableSize;
};
nodehash createHashtable()
{
nodehash hashtable;
hashtable = malloc(sizeof(struct nodehash_));
hashtable->size = 100;
hashtable->hash = malloc(100 * sizeof (node));
int i;
for (i = 0; i < hashtable->size; i++)
{
hashtable->table[i] = NULL;
}
return hashtable;
};
void addtohash(node list, nodehash hashtable)
{
int nodehashnumber;
nodehashnumber = hashfunction(list->word, hash->size);
hashtable->hash[nodehasnumber] = list;
};
And the main functio will look something like this (assume that the linked list of node structures has been created and filled).
int main()
{
nodehash hashtable = createhashtable();
node nodelist;
/* here the nodelist would be created and filled and such and such*/
while (nodelist->next != NULL)
{
addtohash(nodelist, hashtable);
}
return;
}
Assume that there can be no collisions, because every word to be hashed will be different.
BAsically, I'm wondering if I missed and glaring, obvious mistakes or flaws in logic.
Any help would be greatly appreciated.
Thanks.
I didn't give the code an extensive read, but the first thing that stood out pretty clearly is the hash table size, 100. It is best to use a prime number for the size of your hash tables to help avoid collisions.
You seem to have a problem with semicolons:
struct node_
{
char * word;
struct node * next;
} /* <<-- HERE */
typedef struct node_ * node;
But::
int hashFunction(char *word, int hashTableSize)
{
int length = strlen(word);
int h = 0;
int i;
for(i = 0; i<length; i++)
{
h=31 *h + word[i];
}
return h % hashTableSize;
}; /* <<-- NOT here */
Also, a wise advice is IMHO to use as many unsigned types as possible: for the hash value (what does modulo division do with a negative operand?) and for sizes and indexes.
Rule of thumb: if it can not be negative: it's unsigned.