2009-10-01 16 views
6

char türünde bir IP adresim var char char = "192.123.34.134" Son değeri artırmak istiyorum (134). Bunu nasıl yapmalıyım? Sanırım, onu bir tam sayıya dönüştürmeliyim ve sonra geri dönüyorum, ama ne yazık ki nasıl bilmiyorum? :(Ben C++ kullanıyorum.Dizgi olarak temsil edilen IP adresini nasıl artırırım?

bana yardım edin!

Teşekkür, kampi

+4

Haklısınız, char * ip demek? –

cevap

23

Sen inet_addr kullanarak bir tam sayıya dizisinden IP adresi dönüştürebilir, o zaman, bunu manipüle sonra, inet_ntoa ile bir dizeye geri dönüştürmek.

Bunların kullanımıyla ilgili daha fazla bilgi için bu işlevler için bkz the documentation.

// NOTE: only works for IPv4. Check out inet_pton/inet_ntop for IPv6 support. 
char* increment_address(const char* address_string) 
{ 
    // convert the input IP address to an integer 
    in_addr_t address = inet_addr(address_string); 

    // add one to the value (making sure to get the correct byte orders) 
    address = ntohl(address); 
    address += 1; 
    address = htonl(address); 

    // pack the address into the struct inet_ntoa expects 
    struct in_addr address_struct; 
    address_struct.s_addr = address; 

    // convert back to a string 
    return inet_ntoa(address_struct); 
} 

* Nix sistemlerde <arpa/inet.h> veya Windows üzerinde <winsock2.h> ekle:

Burada ne istediğinizi yapacak küçük fonksiyon.

+0

Benimki daha hızlı bir yürütme olacağını biliyorum, ama bu cevap kesinlikle daha doğru. – Erich

+0

Sadece * kullanımdan kaldırılmış * inet_ntoa yerine inet_ntop demek istediğimi farz edeyim, değil mi? ** Doğru? ** – Powerlord

+0

@ R. Bemrose IPv6 bu soruyu gereksiz yere karmaşıklaştırıyor; Orijinal soru, adresin sadece IPv4'ü ifade eden noktalı dörtlü formatta olacağını belirtmiştir. IPv6 adresleri için çalışacak bir şeyle htonl/ntohl çağrılarını değiştirmek için herhangi bir öneriniz varsa, kodu memnuniyetle okuyacağım. –

2

ben bu biçimde bir dize kabul eden bir yöntem yazardı.
4 tamsayılar için dönüştürün. Artışı. (Önemli Kontrol aralık)
Sonra bir dizeye geri dönüştürmek.

sen somthing daha uzun vadeli ve IP adresini temsil eden güçlü bir sınıf istiyorum. Sonra sınıf korumak bir şekilde appropraite manipüle ve gerektiğinde dizeye dönüştürmek.

#include <iostream> 
#include <istream> 
#include <sstream> 
#include <string> 
#include <stdexcept> 



class MyIp 
{ 
    struct Dot 
    {}; 
    struct Byte 
    { 
     Byte(unsigned char& val) 
      :m_val(val) 
     {} 
     unsigned char& m_val; 
    }; 
    friend std::istream& operator>>(std::istream& str,MyIp::Dot const& d); 
    friend std::istream& operator>>(std::istream& str,MyIp::Byte const& b); 
    friend std::ostream& operator<<(std::ostream& str,MyIp const& ip); 
    public: 
     MyIp(std::string const& ip) 
     { 
      std::stringstream str(ip); 
      str >> Byte(ad[0]) >> Dot() >> Byte(ad[1]) >> Dot() >> Byte(ad[2]) >> Dot() >> Byte(ad[3]); 
      std::string leftover; 
      if (str >> leftover) 
      { throw std::runtime_error("InvalidIP: Long"); 
      } 
     } 
     void inc(int index) 
     { 
      if ((index >= 0) && (index <=3)) 
      { 
       ++ad[index]; 
       if (ad[index] == 0) 
       { 
        inc(index-1); 
       } 
      } 
     } 
    private: 
     unsigned char ad[4]; 
}; 
std::istream& operator>>(std::istream& str,MyIp::Dot const& d) 
{ 
    char x = str.get(); 
    if (x != '.') 
    { throw std::runtime_error("Invalid IP: Dot"); 
    } 
    return str; 
} 
std::istream& operator>>(std::istream& str,MyIp::Byte const& b) 
{ 
    unsigned int val; 
    str >> val; 
    if (!str || val > 255) 
    { throw std::runtime_error("Invalid IP: Val"); 
    } 
    b.m_val = static_cast<unsigned char>(val); 
    return str; 
} 
std::ostream& operator<<(std::ostream& str,MyIp const& ip) 
{ 
    return str << static_cast<unsigned int>(ip.ad[0]) 
       << "." << static_cast<unsigned int>(ip.ad[1]) 
       << "." << static_cast<unsigned int>(ip.ad[2]) 
       << "." << static_cast<unsigned int>(ip.ad[3]); 
} 

int main() 
{ 
    try 
    { 
     std::string ip("127.0.0.1"); 

     MyIp addr(ip); 

     std::cout << addr << "\n"; 
     addr.inc(3); 
     std::cout << addr << "\n"; 
    } 
    catch(std::exception const& e) 
    { 
     std::cout << "What: " << e.what() << "\n"; 
    } 
} 
+0

Bu çok eğlenceli. +1. – glomad

+0

İnsanlar üzerinde öldürmek gibi :-) –

-2

Bu site benim sekmelerimi yedi, böylece tekrar deneyeceğim. Bunun gibi bir şey yapmak için bir kütüphane olduğundan eminim, ama bu, fikrini elde etmek için yeteri kadar çalışmalı (sözdizimimin dağınık olmadığı varsayımıyla).

Sözde Kod:

char[] ipAddress= "192.123.34.134"; 

if (ipAddress[ipAddress.Length-1] == '9') 
{ 
    if(ipAddress[ipAddress.Length-2]=='9') 
    { 
     ipAddress[ipAddress.Length-1]='0'; 
     ipAddress[ipAddress.Length-2]='0'; 
     ipAddress[ipAddress.Length-3]=(char)ipAddress[ipAddress.Length-3]+1; 
    } 
    else 
    { 
     ipAddress[ipAddress.Length-2]=(char)ipAddress[ipAddress.Length-2]+1; 
     ipAddress[ipAddress.Length-1]='0'; 
    } 
} 
else 
{ 
    ipAddress[ipAddress.Length-1]=(char)ipAddress[ipAddress.Length-1]+1; 
} 
+0

Peki ya 192.123.34.255'? –

+0

Bu noktada, aralık kontrolünün zaten ele alınmış olduğunu düşündüm. Benim için 192.123.34.255'i 192.123.35.0'a çevirmenin mantıklı olduğunu düşünmüyorum, ki bu da diğer çözümlerin bir tamsayıdan geçeceğini düşünüyorum. – Erich

+0

Eh, şimdi bahsettiğinize göre x.x.x.99 veya x.x.x.9 da çalışmıyor. Bunları düzeltebilirdim, ama gerçekte, soket kütüphanesi işlevlerini kullanan yukarıdaki cevaplar daha doğrudur. – Erich

4

Hızlı/Kirli!

void increment(std::string& ip) 
{ 
    std::string::size_type dot = ip.find_last_of('.'); 
    std::stringstream stream(ip.substr(dot+1)); 
    int part = 0; 

    stream >> part; 

    part++; 

    stream.str(""); stream.clear(); 

    stream << part; 

    ip.replace(dot+1, std::string::npos, stream.str()); 
} 
+0

Kod yazarken yazıyordum :) C++ becerilerim paslı ama sizinkilerin üstünde duruyor. İyi gösteri. – Deverill

0

Ayrıca, son "." Konumunu da kullanabilirsiniz. ve bir int dönüştürmek, sınırlarını kontrol etmek ve daha sonra bir dizeye dönüştürmek ve temel parçaya eklemek için oradan sonuna kadar götür.

0

Bu muhtemelen pek aklı başında değil ama düşünmek eğlenceliydi.

IP adres alanı 32 bit olduğundan, IP adreslerini işaretsiz 32 bit tam sayılara dönüştürmek için bir işlev yazabilirsiniz. Ardından 1 veya daha fazlasını ekleyebilir veya çıkartabilir ve bir IP adresine dönüştürebilirsiniz. Menzil kontrolü konusunda endişelenmene gerek yok. 192.123.34.134 için pseduo-kodunda

yapacağın:

int i = (192 << 24) + (123 << 16) + (34 << 8) + 134 

Daha genel a.b.c. içind:

int i = (a << 24) + (b << 16) + (c << 8) + d 

Şimdi (i++, i+=10000) istediğiniz gibi i kadar değiştirip geri dönüştürmek:

String ip = (i >> 24) + "." + 
      ((i >> 16) mod 256) + "." + 
      ((i >> 8) mod 256) + "." + 
      (i mod 256); 

Mazeret sözdizimi - Kendimi kurtarmak için C++ yazamadım.

MK

+3

Tam olarak, inet_addr_t, Neil'in cevabındaki gibi, bu yüzden kendi kendine yuvarlanmaya gerek yok. Yani, aklı başında olsun ya da olmasın, C programcılarının yıllardır yaptıkları şey ... –

+0

Sanırım bir Java dünyasında çok uzun zamandır biraz düşünürdüm sanırım bit-twiddling biraz fazla hardcore, pointer için teşekkürler ! (Pun orijinal olarak tasarlanmamıştır ancak fark edildiğinde tutulmuştur.) – monorailkitty

3
int a,b,c,d; 
sscanf(str, "%d.%d.%d.%d", &a,&b,&c,&d); 
sprintf(str, "%d.%d.%d.%d\0", a,b,c,d+1); 
İlgili konular