Печать идентичной подсети IP-адреса на отдельных строках - PullRequest
0 голосов
/ 19 апреля 2019

У меня есть программа, которая просит пользователя ввести количество IP-адресов для хранения в следующем массиве структур:

  struct ipaddr{
    int octet1;
    int octet2;
    int octet3;
    int octet4;
  }; typedef struct ipaddr ipaddr_t;

struct ipaddr addr_array[];

Мне нужно создать функцию, которая проверяет все IP-адреса внутримассив структуры и проверьте, принадлежат ли они одной и той же подсети (т. е. первые три xxx.xxx.xxx ip-адреса идентичны, например:

123.123.123.1
123.123.123.2
123.123.123.3

И затем для каждой подсети функция печатает всеIP-адреса, принадлежащие этой подсети в отдельной строке, например:

123.123.123.1 123.123.123.2 123.123.123.3 123.123.123.4
144.144.144.1 144.144.144.2 144.144.144.3 144.144.144.4

И для печати необходимо сохранить порядок IP-адресов, которые были введены пользователем

Пока у меня естьМожно было сравнить только в том случае, если две структуры имеют одну подсеть со следующей функцией:

int is_same_subnet(ipaddr_t ip1, ipaddr_t ip2){
  if(ip1.octet1 == ip2.octet1 &&
     ip1.octet2 == ip2.octet2 &&
     ip1.octet3 == ip2.octet3){
    return 1;
  }
  else return 0;
}

Но мне нужно сделать это для массива структур вроде этого (это не сработало, но это была моя попытка):

void print_same_subnet(const ipaddr_t addr_array[], int addr_array_len){
  int i, k;
  for(i=0; i < addr_array_len; i++){
    for(k=1; k < addr_array_len; k++){
      if(addr_array[i].octet1 == addr_array[k].octet1 &&
         addr_array[i].octet2 == addr_array[k].octet2 &&
         addr_array[i].octet3 == addr_array[k].octet3)
        {
        printf("%i.%i.%i.%i %i.%i.%i.%i \n", addr_array[i].octet1, addr_array[i].octet2, addr_array[i].octet3, addr_array[i].octet4,
                                          addr_array[k].octet1, addr_array[k].octet2, addr_array[k].octet3, addr_array[k].octet4);
      } 
    }
  }
}

Любая помощь для начинающих очень ценится!

Ответы [ 3 ]

0 голосов
/ 19 апреля 2019

Если вы не возражаете против изменения массива, подход состоит в том, чтобы отсортировать адреса таким образом, чтобы они были сгруппированы вместе и, таким образом, их было легче выводить в виде группы:

#include <stdlib.h>
#include <stdio.h>
#include <stdbool.h>

struct ipaddr{
    int octet1;
    int octet2;
    int octet3;
    int octet4;
};
typedef struct ipaddr ipaddr_t;

int compare_ips (const ipaddr_t *ip1, const ipaddr_t *ip2) {
    if (ip1->octet1 != ip2->octet1) return ip1->octet1 - ip2->octet1;
    if (ip1->octet2 != ip2->octet2) return ip1->octet2 - ip2->octet2;
    if (ip1->octet3 != ip2->octet3) return ip1->octet3 - ip2->octet3;
    return ip1->octet4 - ip2->octet4;
}
typedef int (*qsort_comparator)(const void *, const void*);

int is_same_subnet(ipaddr_t ip1, ipaddr_t ip2){
    return (ip1.octet1 == ip2.octet1 &&
            ip1.octet2 == ip2.octet2 &&
            ip1.octet3 == ip2.octet3);
}

void print_same_subnet(ipaddr_t addr_array[], int addr_array_len){
    qsort (addr_array, addr_array_len, sizeof (ipaddr_t), (qsort_comparator) compare_ips);
    bool fresh_match = true;
    for (int i = 0; i < addr_array_len - 1; i++) {
        if (is_same_subnet (addr_array[i], addr_array[i+1])) {
          if (fresh_match) {
            printf("%i.%i.%i.%i ", addr_array[i].octet1, addr_array[i].octet2, addr_array[i].octet3, addr_array[i].octet4);
            fresh_match = false;
          }
          printf("%i.%i.%i.%i ", addr_array[i+1].octet1, addr_array[i+1].octet2, addr_array[i+1].octet3, addr_array[i+1].octet4);
        } else {
            if (!fresh_match) {
                printf ("\n");
            }
            fresh_match = true;
        }
    }
    if (!fresh_match) {
        printf ("\n");
    }
}

int main (void) {
    struct ipaddr addr_array[] = {
            { 10, 32, 39, 49 },
            { 10, 32, 25, 95 },
            { 10, 32, 39, 27 },
            { 10, 32, 39, 88 },
            { 10, 32, 25, 22 },
            { 10, 99, 25, 22 },
    };

    print_same_subnet (addr_array, 6);
}
0 голосов
/ 19 апреля 2019

Простой способ - создать вспомогательный массив того же размера, чтобы отметить, какие адреса уже были обработаны. Код может быть (более или менее):

void print_same_subnet(const ipaddr_t addr_array[], int addr_array_len){
    int i, k;
    int *seen = malloc(addr_array_len * sizeof(int)); // allocate auxilliary array
    for(i=0; i<addr_array_len; i++) seen[i] = 0;      // and set it to 0
    for(i=0; i < addr_array_len; i++){
        if (seen[i]) continue;                        // do not process twice the same row
        printf("%i.%i.%i.%i", addr_array[i].octet1, addr_array[i].octet2,
        addr_array[i].octet3, addr_array[i].octet4);
        for(k=i+1; k < addr_array_len; k++){          // search all addresses sharing same network
            if (seen[k]) continue;                    // ignore already seen addresses
            if (is_same_subnet(addr_array[i], addr_array[k])) {
                seen[k] = 1;                          // note it
                printf(" %i.%i.%i.%i", addr_array[k].octet1,   // and display it on same line
                addr_array[k].octet2, addr_array[k].octet3, addr_array[k].octet4);
            }
        }
        printf("\n");
    }
    free(seen);          // free the auxilliary array
}
0 голосов
/ 19 апреля 2019
void print_same_subnet(const ipaddr_t addr_array_1[], const ipaddr_t addr_array_2[], int addr_array_len)
{
    for(i=0; i < addr_array_len; i++)
    {
        if(is_same_subnet(addr_array_1[i], addr_array_2[i]))
        {
            //Do what you want here
        } 
    }
}
...