Member 12899279 Ответов: 4

Как выполнить итерацию до определенной подстроки в строке?


у меня есть выходные данные команды ipconfig, хранящиеся в строковой переменной
теперь все знают, что у него много информации, но мне нужен только ipv4-адрес во всей этой информации
как я могу извлечь этот конкретный ipv4 адрес из всех этих других данных ipconfig
я не могу использовать ничего другого, кроме строковой переменной для хранения результата ipconfig
я упоминаю ниже, что я пытаюсь найти и получить информацию после того, как эта конкретная строка будет сопоставлена


Windows IP Configuration


Ethernet adapter Ethernet:

   Media State . . . . . . . . . . . : Media disconnected
   Connection-specific DNS Suffix  . :

Ethernet adapter Ethernet 4:

   Media State . . . . . . . . . . . : Media disconnected
   Connection-specific DNS Suffix  . :

Unknown adapter Local Area Connection:

   Media State . . . . . . . . . . . : Media disconnected
   Connection-specific DNS Suffix  . :

Wireless LAN adapter Local Area Connection* 9:

   Media State . . . . . . . . . . . : Media disconnected
   Connection-specific DNS Suffix  . :

Wireless LAN adapter Local Area Connection* 14:

   Media State . . . . . . . . . . . : Media disconnected
   Connection-specific DNS Suffix  . :

Ethernet adapter Ethernet 3:

   Media State . . . . . . . . . . . : Media disconnected
   Connection-specific DNS Suffix  . :

Unknown adapter VPN - VPN Client:

   Media State . . . . . . . . . . . : Media disconnected
   Connection-specific DNS Suffix  . :

Wireless LAN adapter Wi-Fi:

   Connection-specific DNS Suffix  . :
   Link-local IPv6 Address . . . . . : fe80::190f:cbb9:3f5d:46fd%7
   IPv4 Address. . . . . . . . . . . : 192.168.1.55
   Subnet Mask . . . . . . . . . . . : 255.255.255.0
   Default Gateway . . . . . . . . . : 192.168.1.1

Ethernet adapter vEthernet (Default Switch) 3:

   Connection-specific DNS Suffix  . :
   Link-local IPv6 Address . . . . . : fe80::1589:a303:4153:48fa%48
   IPv4 Address. . . . . . . . . . . : 192.168.204.145
   Subnet Mask . . . . . . . . . . . : 255.255.255.240
   Default Gateway . . . . . . . . . :


Что я уже пробовал:

char* search2 = "IPv4 Address. . . . . . . . . . . :";

4 Ответов

Рейтинг:
28

CPallini

Как быстро и грязно ™ подход, опирающийся на ipconfig согласованный формат вывода, вы можете написать

#include <iostream>
#include <sstream>
using namespace std;

int main()
{
  const string Pattern = "   IPv4 Address. . . . . . . . . . . : ";
  const size_t Len = Pattern.length();

  string line;

  while ( getline(cin, line) )
  {
    if ( line.find(Pattern) != string::npos)
    {
      string ip4 = line.substr(Len);
      cout << ip4 << "\n";
    }
  }
}


Вышеприведенная программа, работающая с размещенными данными в качестве входных данных, выводит
192.168.1.55
192.168.204.145



[обновление]
(согласно запросу OP...)
Функция, принимающая строку в качестве аргумента и возвращающая первый IPV4 в виде строки.
std::string get_first_ipv4(const std::string & ipconfig_info)
{
  const string Pattern = "   IPv4 Address. . . . . . . . . . . : ";
  const size_t Len = Pattern.length();

  istringstream iss( ipconfig_info );
  string line;

  while ( getline(iss, line) )
  {
    if ( line.find(Pattern) != string::npos)
    {
      return line.substr(Len);
    }
  }
  return string{};
}

[/обновление]


Member 12899279

он ничего не возвращает потому что вы использовали cin в то время как все данные которые я опубликовал выше полученные из ipconfig находятся внутри строковой переменной с именем output ну имя не имеет значения

CPallini

Вы можете либо
* перенаправление стандартного ввода команды ipconfig, как в мою программу.
или
* используйте istringstream вместо cin (просто создайте объект istringstream, используя вашу строку в качестве аргумента).

CPallini

Я покажу тебе ... istringstream техника в моем обновленном решении.

Maciej Los

5ed!

CPallini

Спасибо тебе, Мацей!

Member 12899279

спасибо это сработало на самом деле я не знал как использовать istringstream и использовать его для поиска подстроки в строковой переменной так что большое спасибо

CPallini

Добро пожаловать. Я догадался, что вы не знаете об istringstream, поэтому я специально обновил решение.

Member 12899279

да, я не знал о istringstream еще раз спасибо (Y)

Рейтинг:
2

Rick York

Лично я думаю, что разбор выходных данных ipconfig-это слишком много взлома, когда есть API, которые можно использовать. На этом сайте есть несколько статей о таких вещах. Вот один из них, на который вам стоит взглянуть : "Новый ipconfig" и IP Helper API[^]


Рейтинг:
2

k5054

Думая об этом, регулярное выражение слишком тяжело для этого. Вот альтернативное решение, которое работает с c-строками, возвращаемыми из _popen()

#include <iostream>
#include <cstdio>
#include <cstring>
#include <string>
#include <vector>


int main()
{
    FILE *pipe = _popen("ipconfig", "r");
    
    if(pipe == NULL) {
        perror("popen");
        return 1;
    }

    char buffer[256];
    const char *MatchIPv4  = "IPv4 Address";

    std::vector<std::string> ipaddrs;  // store all the addresses

    while(fgets(buffer, sizeof buffer, pipe) != NULL) {

        char *ptr;   // temporary var for doing work

        // find the right input line
        if( (ptr = strstr(buffer, MatchIPv4)) != NULL) {

            // IP addr starts after the :
            ptr = strchr(ptr, ':');

            // first char of IP address is a digit, so find first digit
            size_t begin = strcspn(ptr, "0123456789");
            
            // IP address is first char not in set [0-9.]
            size_t length = strspn(ptr+begin, "0123456789.");

            // create a C++ string:
            ipaddrs.push_back(std::string(ptr+begin, length));
        }
    } 

    _pclose(pipe);

    for(auto  ipaddr : ipaddrs ) {
        std::cout << ipaddr << std::endl;
    }
        

    return 0;
}


Это не делает никаких предположений за пределами
1) интересующие строки содержат "IPv4-адрес".
2) есть только один":", который предшествует IP-адресу

Существует еще более простое решение, если вы готовы сделать предположение, что выходной формат вывода из ipconfig не изменится - или, по крайней мере, не изменится, пока ваша программа вам полезна.

if( strstr(buffer, MachIPv4) != NULL) {
     char *ptr = buffer + 39;       // start of IP address
     char *end = strchr(ptr, '\n'); // find terminating \n from fgets
     *end = '\0';                   // turn it into a nul byte
     ipaddrs.push_back(std::string(ptr));
}


Member 12899279

я не могу использовать popen так как он открывает cmd который я не хочу показывать даже на долю секунды

k5054

Да, это потому, что не следует использовать _popen() в контексте рабочего стола windows. См. примечание в нижней части этого документа _popen, _wpopen | Майкрософт документы[^] Перейдите по ссылке в конце заметки о создании дочерних процессов в программе windows. А еще лучше последуйте совету Рика Йорка и используйте API IP helper.

Member 12899279

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

Рейтинг:
0

OriginalGriff

Мы не можем сказать вам точно, как это сделать, потому что у нас нет никакого доступа к фактической строке, и это будет иметь фундаментальное значение для того, что вам нужно сделать. Без фактических данных невозможно разработать какой - либо код, который будет на 100% захватывать именно то, что вам нужно, и ничего больше-даже с ним вам, вероятно, понадобится большое количество образцов для работы формы, чтобы быть уверенным, что вы правильно изолируете только правильную информацию каждый раз.

Итак, начните с ваших данных и найдите нужный бит. Посмотрите, есть ли что - нибудь вокруг него- желательно раньше и после этого он говорит: "получите этот бит", и это не повторяется нигде, что вы не получаете то, что хотите.

Затем подумайте о том, чтобы посмотреть на регулярное выражение (именно то, как вы его используете, зависит от вашей системы разработки / среды, в которой будет выполняться код) и посмотреть, можете ли вы использовать его для изоляции только IP-адреса. Базовое совпадение IP-адресов в регулярном выражении будет выглядеть следующим образом:

\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}
Но вам, возможно, придется расширить его в зависимости от остальных ваших данных, так как это будет соответствовать любой последовательности до трех цифр, разделенных точками.

В качестве помощника получите копию Экспрессо[^] - это бесплатно, и он проверяет и генерирует регулярные выражения.


Member 12899279

я прикрепил строковый Вывод, Теперь вы можете помочь мне понять, как получить только ipv4address?

OriginalGriff

Нет, потому что мы не знаем, какой из IP - адресов там вам нужен-и я могу видеть два там, даже не присматриваясь. И это при условии, что некоторые из ваших других не появятся в сети позже.

Начните с размышления о том, что именно вы пытаетесь сделать - и почему uyouj ar eusing Command outputs для этого, когда, вероятно, есть API-способы получить именно то, что вы хотели в любом случае. Затем посмотрите на свои данные и начните думать о том, что я сказал выше.

Member 12899279

я назвал адрес IPv4 че первое под адаптер беспроводной локальной сети беспроводной доступ в интернет

Member 12899279

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

Member 12899279

или любой ipv4 адрес который появляется первым не имеет значения если он предназначен для проводной или беспроводной связи
я хочу получить ipv4-адрес, который появляется первым

OriginalGriff

И что же? Что вы пытались сделать?

Maciej Los

5ed!