【问题标题】:C++ IP adresses as strings compare?C++ IP地址作为字符串比较?
【发布时间】:2021-08-30 07:52:50
【问题描述】:

我的任务是比较给定数量的 IP 地址。首先,我必须向用户询问数量,然后用户必须输入那么多IP。之后,我必须对它们进行比较——如果我发现有不止一次出现,我必须把它写出来。

我的问题是我不知道如何在没有我的双 for() 循环多次写出它们的情况下将它们写出来。您能帮帮我吗,我应该纠正什么?

#include<iostream>
#include<string>

int main(){
    
    int n;
    std::cin >> n;
    
    std::string ips[n];
    
    for(int i = 0; i < n; i++){
        std::cin >> ips[i];
    }
    
    std::cout << "\n\n";

    
    for(int i = 0; i < n-1; i++){
        for(int j = i+1; j < n; j++){
            if(ips[i] == ips[j]){
                std::cout << ips[j] << '\n';
            }
        }
    }
    
    
    return 0;
}

【问题讨论】:

  • std::string ips[n]; 在标准 C++ 中是非法的,因为 n 的值必须在编译时而不是运行时已知。在这种情况下首选std::vector&lt;std::string&gt; ips(n)
  • 你知道std::sort怎么用吗?你知道std::mapstd::set怎么用吗?
  • 还要注意192.168.0.1192.168.000.001等组合是同一个IP地址。您可能需要首先对表示进行规范化,或者至少与分配给您任务的人核实。
  • @SamVarshavchik 我没有。我是 C++ 的初学者,所以我正在尝试用非常基本的技术来解决问题
  • 使用内置函数和数据结构远比重新发明轮子更基本。调用函数std::sort 比编写自己的排序算法要简单得多。如前所述,地址192.168.0.1192.168.0.001 在技术上是相同的。您是否必须将这些作为副本,或者它们是您案件的不同地址?即使192.168.0.2不是用户输入的,也可以将192.168.0.002打印为192.168.0.2吗?

标签: c++ arrays string compare


【解决方案1】:

既然您提到您是初学者,我假设 IP 地址的使用仅用于说明目的,您使用的资源不希望您关心处理 IP 卫生问题,例如清理前导零,等等

如果确实如此,您正在寻找的是一种在用户输入字符串列表中检查重复项的方法,以及一种仅打印重复项而忽略每个重复次数的方法。

所以首先,而不是这个

std::string ips[n];

让我们简单地使用向量

int n;
std::cout << "Enter number of IP addresses" << '\n';
std::cin >> n;

std::vector<std::string> ip_addresses;

  for (int i = 0; i < n; i++)
  {
    std::string ip;
    std::cin >> ip;
    ip_addresses.push_back(ip);
  }

这里 ip_addresses 保存用户提供的任何内容(请记住,此方法不授予用户输入的实际 IP 地址,我将验证留给您。)

接下来您需要弄清楚这些重复项是什么。

有几种方法可以做到这一点,您可以使用 STL 算法库函数,如 std::adjacent_find,但现在这可能太高级了,您可以对向量进行排序并检查相邻的重复项,这可能更简单

std::sort(ip_addresses.begin(), ip_addresses.end());

这将对ip_addresses的向量进行排序

还有这段代码

  const std::string  empty{ "" };
  const std::string* prev = &empty;
  const std::string* intermidiate;

  for (const std::string& s : ip_addresses)
  {
    if (*prev == s && *prev != *intermidiate)
    {
      std::cout << "Found duplicate entries for: " << s << '\n';
      intermidiate = &s;
    }

    prev = &s;
  }

确保物品;如果它与前一个重复,则不会多次打印,因为我们将该状态保存在 intermidiate var 中。

这就是最终产品的样子

#include <iostream>
#include <string>
#include <vector>

int main()
{
  int n;
  std::cout << "Enter number of IP addresses" << '\n';
  std::cin >> n;

  std::vector<std::string> ip_addresses;

  for (int i = 0; i < n; i++)
  {
    std::string ip;
    std::cin >> ip;
    ip_addresses.push_back(ip);
  }

  std::sort(ip_addresses.begin(), ip_addresses.end());

  const std::string  empty{ "" };
  const std::string* prev = &empty;
  const std::string* intermidiate;

  for (const std::string& s : ip_addresses)
  {
    if (*prev == s && *prev != *intermidiate)
    {
      std::cout << "Found duplicate entries for: " << s << '\n';
      intermidiate = &s;
    }

    prev = &s;
  }

  return 0;
}

这是一个测试用例

Enter number of IP addresses
6
192.168.0.1
192.118.28.2
192.168.0.1
192.180.0.2
192.180.0.2
23.45.199.2
Found duplicate entries for: 192.168.0.1
Found duplicate entries for: 192.180.0.2

【讨论】:

  • 您可以诚实地优化这个,只需使用unordered_set 并检查emplace 的返回值
  • 我如何标记@Mgetz? unordered set 不会存储重复的密钥。整洁的解决方案。
【解决方案2】:

上面的其他人指出您不能执行以下操作:

std::string ips[n];

相反,做这样的事情会更接近你想要的:

std::vector<std::string> ips;
int n;

std::cin >> n;

for(int i = 0; i < n; ++i)
{
    std::string str;

    std::cin >> str;
    ips.push_back(str);
}

std::sort(ips.begin(), ips.end());

auto iter = ips.begin();

while (iter != ips.end())
{
   iter = std::adjacent_find(iter, ips.end());

   if(iter != ips.end())
   {
       std::cout << *iter << '\n';
       iter += 2; // To skip this place and the next
   }
}

标准库中的sort 算法和adjacent find 算法将为您完成繁重的工作。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2015-05-17
    • 2021-01-10
    • 2018-01-29
    • 2014-04-03
    • 2014-09-17
    • 1970-01-01
    • 2022-07-25
    • 2010-11-04
    相关资源
    最近更新 更多