Reputation: 3
I am trying to make a c99 program that reports the number of bytes downloaded by devices using WiFi.
It takes in a packet file as input, and each packet is sorted into an array of structs that contain the mac id and size of packet.
Now I am trying to sort out the array of structs in ascending order, and add the bytes of the same mac address and delete the added record.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define PACKETS "sample-packets"
#define MAXMACADD 500
struct packetStruct {
char mac[17];
int size;
} packetStruct[MAXMACADD];
struct output {
char mac[17];
int size;
} output[MAXMACADD];
void sortSize(struct packetStruct* macadd, int n) {
int j, i;
for (i = 1; i < n; i++) {
for (j = 0; j < n - i; j++) {
if (macadd[j].size < macadd[j + 1].size) {
struct packetStruct temp = macadd[j];
macadd[j] = macadd[j + 1];
macadd[j + 1] = temp;
}
}
}
}
void mergeMac2(struct packetStruct* macadd, struct output* output, int n) {
int i, j, k=0;
for (i = 0; i < n; i++) {
if (strcmp(macadd[i].mac, "\0") != 0) {
for (j = 0; j < n; j++) {
if (strcmp(macadd[j].mac, "\0") != 0) {
if (strcmp(macadd[i].mac, macadd[j].mac) == 0){
strcpy(output[k].mac, macadd[i].mac);
output[k].size += macadd[i].size;
macadd[i].size = 0;
}
} else j++;
}
} else i++;
k++;
}
}
int readpacket() {
char *token;
char buf[60];
int size;
FILE *packet = fopen(PACKETS, "r"); //open packet file in read mode
int i = 0;
int j = 0; //loop control variables
int k = 0;
while (fgets(buf, sizeof (buf), packet) != '\0') {
token = strtok(buf, "\t"); //tokenize buf and point to time
token = strtok(NULL, "\t"); //point to sender mac add
token = strtok(NULL, "\t"); //point to dest mac add
strcpy(packetStruct[i].mac, token);
token = strtok(NULL, "\t"); //point to byte size
packetStruct[i].size += atoi(token);
//printf("%i. %s\t%d\n", i, packetStruct[i].mac, packetStruct[i].size);
i++;
}
fclose(packet); //close packet file
sortSize(packetStruct, i);
mergeMac2(packetStruct, output, i);
for (i = 0; i < 20; i++) {
printf("%i. %s\t%d\n", i, packetStruct[i].mac, packetStruct[i].size);
}
for (i=0; i < 20; i++){
printf("%i. %s\t%d\n", i+1, output[i].mac, output[i].size);
}
return 0;
}
void main(int argc, char *argv[]) {
if (argc != 2) {
printf("%s: program needs 1 argument, but there was %d\n", argv[0], argc - 1);
exit(EXIT_FAILURE);
} else {
if (strcmp(argv[1], "packets") != 0) {
printf("%s: program expected command 'packets', but you wrote %s\n", argv[0], argv[1]);
} else {
if (readpacket() != 0) {
exit(EXIT_FAILURE);
}
}
}
}
You can compile in command line using:
$: gcc main.c
run using:
$: ./a.out packets
It is sorting it fine but the merging is the issue. Should i use another struct called output and store the values in there or should i just merge up the current array? time-efficiency is not necessary.
I can provide the sample input file if it would be useful.
Upvotes: 0
Views: 2822
Reputation: 1261
void mergeMac2(struct packetStruct* macadd, struct output* output, int n)
{
int i, j, k = 0;
for (i = 0; i < n; i++) {
/*
* If size is 0, the packet has already been processed.
*/
if (macadd[i].size == 0)
continue;
memcpy(&output[k], &macadd[i], sizeof(struct packetStruct));
for (j = i+1; j < n; j++) {
/*
* If size is 0, the packet has already been processed.
*/
if (macadd[j].size == 0)
continue;
if (strcmp(macadd[i].mac, macadd[j].mac) == 0) {
output[k].size += macadd[j].size;
/*
* Set size to 0 so that these packets won't be
* processed in the next pass.
*/
macadd[j].size = 0;
}
}
k++;
}
}
Upvotes: 0
Reputation: 9894
If I have understood you correctly you want to add all sizes from the same mac address. Then mergeMac2()
should be like that (edit: now it's a version that completely preserves the original macadd
array):
// return number of elements in output
int mergeMac2(struct packetStruct* macadd, struct output* output, int n) {
int i, j, k=0;
for (i = 0; i < n; i++) {
// '"\0" makes no difference to "" here
//if (strcmp(macadd[i].mac, "\0") != 0) {
if (strcmp(macadd[i].mac, "") != 0) {
// search in putput;
for( j=0; j<k && strcmp( macadd[i].mac, output[j].mac ) != 0; j++ ) ;
if( j == k ) {
// not yet created in output
strcpy( output[k].mac, macadd[i].mac );
output[k].size = macadd[i].size;
k++;
} else {
output[j].size += macadd[i].size;
}
}
}
return k;
}
Now you have added all sizes for each mac address to the first struct element that originally contained that address. Your second printf()
loop should now be:
int j, n;
...
n = mergeMac2( packetStruct, output, i );
for( j=0; j<n; j++ ) {
...
}
At least I think you should first merge and then sort but that depends on what you want to achieve, of course.
Upvotes: 1