Reputation: 47
In C language, How would I Go about printing my code in ascending order? I have asked some questions on stack earlier today, and I am still a little confused. My code currently reads a file and uses a priority queue to print the frequencies of each character in the file, however I need it to print out the characters in ascending order, while my project just prints them in the order of the ASCII table.
Here is my code:
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <fcntl.h>
#include <sys/types.h>
#include <sys/stat.h>
struct pair //struct to store frequency and value
{
int frequency;
char value;
};
struct Qnode
{
struct pair nodeValue;
struct Qnode *next;
struct Qnode *left, *right;
};
void popQueue(struct Qnode **front)
{
struct Qnode *pop = *front;
*front = (*front) -> next;
free(pop);
}
void pushQueue(struct Qnode **front, struct Qnode *newQnode)
{
struct Qnode *n1 = *front;
struct Qnode *n2 = newQnode;
if (!(*front))
{
(*front) = newQnode;
}
else{
if((*front)->nodeValue.frequency < newQnode->nodeValue.frequency)
{
n2->next = *front;
*front = n2;
}
else
{
while(n1->next != NULL && (n1->nodeValue).frequency < (newQnode->nodeValue).frequency)
{
n1 = n1->next;
}
n2->next = n1->next;
n1->next = n2;
}
}
//newQnode->next = front;
// front = newQnode;
}
/*
struct Qnode *newNode(struct pair Pairs)
{
struct Qnode *temp = (struct Qnode*)malloc(sizeof(struct Qnode));
temp->left = temp->right = NULL;
temp->nodeValue = Pairs;
temp->frequency = frequency;
}
*/
struct Qnode *createQnode(struct pair Pairs)
{
struct Qnode *p = malloc(sizeof(struct Qnode));
p->next=NULL;
p->nodeValue = Pairs;
return p;
}
void printQueue(struct Qnode **front)
{
struct Qnode *nodePtr = *front;
while (nodePtr != NULL)
{
printf("%c: %d\n", (nodePtr->nodeValue).value,(nodePtr->nodeValue).frequency);
nodePtr = nodePtr->next;
}
}
int main(int argc, char *argv[]) //command line takes in the file of text
{
struct pair table[128]; //set to 128 because these are the main characters
int fd; // file descriptor for opening file
char buffer[1]; // buffer for reading through files bytes
fd = open(argv[1], O_RDONLY); // open a file in read mode
for(int j = 0; j < 128; j++)//for loop to initialize the array of pair (struct)
{
table[j].value = j; // table with index j sets the struct char value to equal the index
table[j].frequency = 0; // then the table will initialize the frequency to be 0
}
while((read(fd, buffer, 1)) > 0) // read each character and count frequency
{
int k = buffer[0]; //index k is equal to buffer[0] with integer mask becasue each letter has a ASCII number.
table[k].frequency++; //using the struct pair table with index k to count the frequency of each character in text file
}
struct Qnode *pq = NULL; //initialize priority queue Qnode struct
for (int i = 32; i < 128; i++) // for loop to print the values of the ASCII tabe
{
struct Qnode *new = createQnode(table[i]); //create new node frome struct pair
pushQueue(&pq, new); //insert node into priority queue
}
printQueue(&pq); // print queue to screen
popQueue(&pq); // remove pop each element from queue
close(fd); // close the file
return 0; //end of code
}
Here is my output:
./frequencyNew freqCount.txt
m: 13
: 0
~: 0
}: 0
|: 0
{: 0
z: 0
y: 0
x: 0
w: 0
v: 0
u: 0
t: 0
s: 0
r: 0
q: 0
p: 0
o: 0
n: 10
l: 12
k: 11
0: 10
j: 10
i: 9
h: 8
g: 7
f: 6
e: 5
d: 4
c: 3
b: 2
a: 1
`: 0
_: 0
^: 0
]: 0
\: 0
[: 0
Z: 0
Y: 0
X: 0
W: 0
V: 0
U: 0
T: 0
S: 0
R: 0
Q: 0
P: 0
O: 0
N: 0
M: 0
L: 0
K: 0
J: 0
I: 0
H: 0
G: 0
F: 0
E: 0
D: 0
C: 0
B: 0
A: 0
@: 0
?: 0
>: 0
=: 0
<: 0
;: 0
:: 0
9: 1
8: 2
7: 3
6: 4
5: 5
4: 6
3: 7
2: 8
1: 9
: 0
/: 0
.: 0
-: 0
,: 0
+: 0
*: 0
): 0
(: 0
': 0
&: 0
%: 0
$: 0
#: 0
": 0
!: 0
Upvotes: 0
Views: 291
Reputation: 424
Please change the two lines in the pushQueue
function
chanage
if((*front)->nodeValue.frequency < newQnode->nodeValue.frequency)
to
if((*front)->nodeValue.frequency > newQnode->nodeValue.frequency)
change
while(n1->next != NULL && (n1->nodeValue).frequency < (newQnode->nodeValue).frequency)
to
while(n1->next != NULL && (n1->next->nodeValue).frequency < (newQnode->nodeValue).frequency)
Upvotes: 0
Reputation: 117238
I suggest that you simplify it:
qsort
to sort the table.Example:
#include <ctype.h>
#include <stdio.h>
#include <stdlib.h>
#include <limits.h>
// A struct to store a letter and its count
typedef struct {
unsigned char letter;
unsigned long count;
} letter_count_t;
// A function to compare two `letter_count_t`s to use with qsort:
int letter_count_t_comp(const void *vlhs, const void *vrhs) {
const letter_count_t* lhs = vlhs;
const letter_count_t* rhs = vrhs;
if(lhs->count < rhs->count) return -1;
if(lhs->count > rhs->count) return 1;
return 0;
}
int main(int argc, char* argv[]) {
if(argc != 2) return 1;
// make a table of letter counts
letter_count_t lc[1 << CHAR_BIT]; // very often 256
// Assign a letter and count to each `letter_count_t` in the table:
for(unsigned ch = 0; ch < (1 << CHAR_BIT); ++ch) {
lc[ch].letter = ch;
lc[ch].count = 0;
}
FILE *fp = fopen(argv[1], "r");
if(fp) {
int ch;
// Read the file and increase the count for each letter
while((ch = fgetc(fp)) != EOF) {
++lc[(unsigned char)ch].count;
}
fclose(fp);
// Sort the table:
qsort(lc, 1 << CHAR_BIT, sizeof *lc, letter_count_t_comp);
// Display the result
for(ch = 0; ch < (1 << CHAR_BIT); ++ch) {
if(lc[ch].count) { // Skip letters that didn't occur in the file
printf("%c %lu\n", isgraph(lc[ch].letter) ? lc[ch].letter : ' ',
lc[ch].count);
}
}
}
}
Upvotes: 2