I'm currently sorting the count
fields of the obj
elements in the objArray
in descending order
as you can see in the program below but i also want my program to check if the two current objA.count
and objB.count
fields that are being used in the cmpfunc()
are equal, then check if the objb.word
string is greater than the objA.word
string, and if so swap them. However, using the input.txt
file that i've included below you can see in the output that something's not working.Can you help me figure out what that is? The logic seems right to me but maybe i've missunderstood something in how the cmpfunc()
works or which string is "bigger".
Program.c:
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <math.h>
/* PREPROCESSOR */
#define MAX_STRING_SIZE 512 /* each line in the file can have up to 512 chars */
/* Function Declarations */
void sortedCount(int,char **);
void *malloc_or_end(size_t);
/* Function Definitions */
/**
* Allocates sz bytes of memory using malloc, checks if
* the memory allocation was successfull and return a void* to the
* beginning of the allocated memory.
* */
void* malloc_or_end(size_t sz) {
void *pointer;
pointer = malloc(sz);
if(pointer == NULL) {
printf("Out of memory, terminating.\n");
exit(-1);
}
return pointer;
}
/**
* Function count: Prints the number of times
* that the selected word is found inside the N first words
* of the file.
* */
int count(int N, char *word, int callID,char **wordList) {
int i = 0;
int count = 0;
for(i = 0; i < N; i++) {
if(strcmp(word,wordList[i]) == 0) {
count++;
}
}
if(callID == 0) { /* if callID == 0 (main called count and we want the output) */
printf("%d",count);
printf("\n");
}
return count;
}
typedef struct wordAndCount {
int count;
char *word;
} obj;
int cmpfunc(const void * a, const void * b) {
obj objA = *(obj *)a;
obj objB = *(obj *)b;
int res = objA.count - objB.count;
if(res > 0) {
return -1;
} else if(res < 0) { /* 2nd count is greater than the first */
return 2;
} else {
int cmpResult = strcmp(objB.word,objA.word);
if(cmpResult > 0) {
} else if(cmpResult < 0) {
/* do nothing */
char *temp = malloc_or_end(MAX_STRING_SIZE * sizeof(char));
strcpy(temp,objA.word);
strcpy(objA.word,objB.word);
strcpy(objB.word,temp);
free(temp);
} else {
/* do nothing */
}
return 0;
}
}
void sortedCount(int N,char **wordList) {
int i,j = 0;
int *occurrences;
obj *objArray;
/* mem allocation */
objArray = malloc_or_end(N * sizeof(obj));
occurrences = malloc_or_end(N * sizeof(int));
/* initialize occurrences for the "each word is unique and occurs only once" scenario */
for(i = 0; i < N; i++) {
objArray[i].word = malloc_or_end(MAX_STRING_SIZE * sizeof(char));
occurrences[i] = 1;
}
determineUniqueWords(occurrences,wordList,N);
/* populate the wordCounts & uniqueWords "arrays" with the appropriate data in order to sort them successfully */
for(i = 0; i < N; i++) {
if(occurrences[i] > 0) {
objArray[i].count = count(N,wordList[i],1,wordList);
strcpy(objArray[i].word,wordList[i]);
}
}
/* sort */
qsort(objArray,N,sizeof(obj),cmpfunc);
for(i = 0; i< N; i++) {
if(objArray[i].count == 0 || (strcmp(objArray[i].word,"") == 0)) {
continue;
}
printf("%d %s\n",objArray[i].count,objArray[i].word);
}
/* mem free */
for(i = 0; i < N; i++) {
free(objArray[i].word);
}
free(objArray);
free(occurrences);
return;
}
/* Stelios Papamichail AM 4020 */
int main(int argc,char *argv[]) { /* argv[1] = op argv[2] = name argv[3] = <word> */
int N = -1;
int i = 0;
int spaceNum,nlNum = -1;
FILE *file;
char **wordList;
file = fopen(argv[2],"r");
if(file == (FILE *) NULL) { /* check if the file opened successfully */
fprintf(stderr,"Cannot open file\n");
}
fscanf(file,"%d",&N); /* get the N number */
wordList = malloc_or_end(N * sizeof(char *)); /* allocate memory for pointers */
for(i = 0; i < N; i++) {
wordList[i] = malloc_or_end(MAX_STRING_SIZE * sizeof(char)); /* allocate memory for strings */
}
populateWordsArray(N,wordList,file);
if(strcmp(argv[1],"-reverse") == 0) {
reverse(N,wordList);
} else if(strcmp(argv[1],"-first") == 0) {
first(N,wordList);
} else if(strcmp(argv[1],"-middle") == 0) {
middle(N,wordList);
} else if(strcmp(argv[1],"-last") == 0) {
last(N,wordList);
} else if((strcmp(argv[1],"-count") == 0) && argv[3] != NULL) {
i = count(N,argv[3],0,wordList);
} else if((strcmp(argv[1],"-sorted") == 0) && (strcmp(argv[3],"-count") == 0)) {
sortedCount(N,wordList);
} else {
/* i only wish i could print something here */
}
/* End of program operations */
for(i = 0; i < N; i++) {
free(wordList[i]);
}
free(wordList);
fclose(file);
return 0;
}
Input.txt:
11 this is a simple text is a a z z z
Output:
3 a
3 z
2 is
1 simple
1 text
1 this
Expected output:
3 z
3 a
2 is
1 simple
1 this
1 text
Your compare function is not supposed to manipulate the objects that are compared. You shall only return a compare result:
int cmpfunc(const void * a, const void * b)
{
obj *objA = (obj *)a;
obj *objB = (obj *)b;
int res = objA->count - objB->count;
// negative value means A is less than B.
if(res == 0)
{
res = strcmp(objA->word, objB->word);
// negative value if A is less than B.
}
return res; // or -res for other sorting direction
}
There is also no need to copy the elements in your function when you can use the pointers to access them directly in the array.