在c中合并和排序struct数组

时间:2013-09-12 14:50:57

标签: c arrays linux sorting struct

我正在尝试制作一个c99程序,报告设备使用WiFi下载的字节数。

它接收一个数据包文件作为输入,每个数据包被分类为一个包含mac id和数据包大小的结构数组。

现在我试图按升序排序结构数组,并添加相同mac地址的字节并删除添加的记录。

#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);
      }
    }
  }
}

您可以使用以下命令行编译:

$: gcc main.c

使用:

运行
$: ./a.out packets

它正在排序很好,但合并是问题。我应该使用另一个名为output的结构并将值存储在那里,还是应该合并当前数组?时间效率是没有必要的。

如果它有用,我可以提供示例输入文件。

2 个答案:

答案 0 :(得分:1)

如果我理解正确,您想要从同一个mac地址添加所有尺寸。然后mergeMac2()应该是那样的(编辑:现在它是一个完全保留原始macadd数组的版本):

  // 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;
  }

现在,您已将每个mac地址的所有大小添加到最初包含该地址的第一个struct元素。您的第二个printf()循环现在应该是:

int j, n;
...
n = mergeMac2( packetStruct, output, i );
for( j=0; j<n; j++ ) {
    ...
} 

至少我认为你应该首先合并然后排序,但这取决于你想要实现的目标。

答案 1 :(得分:0)

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++;
    }
}