Accepting as input, IP addresses.

Pages: 12
I'm trying to accept IP addresses in their dot notation form. However, I'm having trouble trying to store them in anything other then a string variable, and retaining the dot notation. Working with string variables, I cannot figure out how to access and manipulate each individual octet of the IP address (1-3 numbers separated by a decimal, four times. So 4 octets, 3 dots). The number can be 192.168.0.1 or 192.255.255.255 so I cannot know how many digits each octet will have.

How can I extract each octet, and place them in separate variables to determine the appropriate action for subnetting it? Different digit counts in different octets are vital to subnetting this IP.
Last edited on
I'm guessing I'll be using the .size() member function on the ip variable that the user will define, to extract each digit and test for the three decimals - all within a loop to test every character - and save the octets accordingly.

Will this work?

1
2
3
4
5
6
7
8
9
10
	string ip;
	string ipF;
	cout << "enter the IP address: ";cin>>ip;
	cout << endl;
	for (int i = 0; i < ip.size(); i++){
		ip[i]!='.'?ipF+=ip[i]:ipF;
	}
	cout << ipF << endl;
	system("PAUSE");
}


I have identified and removed the decimals but cannot figure out how to place each octet into a separate variable. I need some sort of iteration on the ipF array to create each element as well I think. Can I get some help?
Last edited on
What is wrong here? I'm trying to increment the ipF array with J++ if ip[i] == '.'
When I run this program it crashes after I enter the IP.

I can't offer $15 but I can offer a "Good job, thanks sir!".

1
2
3
4
5
6
7
8
9
10
11
12
int main() {
	string ip;
	string ipF;
	int j = 0;
	cout << "enter the IP address: ";cin>>ip;
	cout << endl;
	for (int i = 0; i < ip.size(); i++){
		ip[i]!='.'?ipF[j]+=ip[i]:j++;
	}
	cout << ipF[0] << " - " << ipF[1] << " - " << ipF[2] << " - " << ipF[3] << endl;
	system("PAUSE");
}
Last edited on
for strings try this function:

1
2
3
4
string s_old, s_new;
s_old = "Whole string";
s_new = s_old.substr(0,1);
cout << s_new;


destination = stringname.substr(x,y) returns a string starting at position x of string "stringname" with a length y, and assigns to destination

as you can see ^ I'm a noob and can't read this garbage ip[i]!='.'?ipF[j]+=ip[i]:j++;
I don't even know what that means but I don't think you can access characters of a string as if they were part of a c char array. use ".substr(int,int)"
Last edited on
ok - I added [3] array identifier to the ipF during initialization and changed ipF to a int - now the program runs, but gives me a 4 large negative numbers (9 digits each) instead of the user input. Here is my code:

1
2
3
4
5
6
7
8
9
10
11
12
int main() {
	string ip;
	int ipF [3];
	int j = 0;
	cout << "enter the IP address: ";cin>>ip;
	cout << endl;
	for (int i = 0; i < ip.size(); i++){
		ip[i]!='.'?ipF[j]+=ip[i]:j++;
	}
	cout << ipF[0] << " - " << ipF[1] << " - " << ipF[2] << " - " << ipF[3] << endl;
	system("PAUSE");
}


Outputs:

 
-858993361 - -858993361 - -858993361 - -858993361
Last edited on
I tried using a stringstream, though this seems a bit long, there are probably neater ways of handling it. Below, I'm assuming there are exactly four integers separated by exactly three dots. Its still necessary to test the integers are in the range 0-255, I've not done that part.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
#include <iostream>
#include <string>
#include <sstream>

    using namespace std;


bool checkIP(std::string s, int & a, int &b, int &c, int&d);

int main()
{

    string ip = "192.168.0.1";


    int a, b, c, d;

    bool ok = checkIP(ip, a, b, c, d);

    if (ok)
    {
        cout << a << endl;
        cout << b << endl;
        cout << c << endl;
        cout << d << endl;
    }


    return 0;
}

bool checkIP(std::string s, int & a, int &b, int &c, int&d)
{
    a = b = c = d = 0;

    if (s.find_first_not_of("1234567890.") != string::npos)
    {
        cout << "invalid character" << endl;
        return false;
    }

    stringstream strm;
    strm.str(s);

    char ch1, ch2, ch3;
    ch1 = ch2 = ch3 = ' ';

    strm  >> a >> ch1 >> b >> ch2 >> c >> ch3 >> d;

    if (strm.eof() && !strm.fail())
    {
        if (ch1 == '.' && ch2 == '.' && ch3 == '.')
        {
            return true;
        }
        else
        {
            cout << "invalid separator" << endl;
            return false;
        }
    }
    else
    {
        cout << "invalid data" << endl;
        return false;
    }
}


I guess you could turn this into a class, where the four numbers are data members, and the conversion to/from a string would be done by functions of the class.
These seem helpful, but I'm so close with the little code I have. Now, all the numbers are saved into an array (problem: all saving inside the first element of the ipF array '[0]') - When I run program and input: 192.168.0.1 it prints out: 192-168-0-1.

Now I just need to get a new element in the ipF array to create, instead of a dash being inputted for each iteration. Is this possible?

1
2
3
4
5
6
7
8
9
10
11
12
int main() {
	string ip;
	string ipF [3];
	int j = 0;
	cout << "enter the IP address: ";cin>>ip;
	cout << endl;
	for (int i = 0; i < ip.size(); i++){
		ip[i]!='.'?ipF[j]+=ip[i]:ipF[j]+='-';
	}
	cout << ipF[0];
	system("PAUSE");
}


I don't understand why this doesn't work:

 
ip[i]!='.'?ipF[j]+=ip[i]:j++;


Specifically
 
:j++;
Last edited on
This code causes my program to crash after I enter the IP address. Why cant I store 12.13.14.15 into ipF[0] = 12, ipF[1] = 13, ipF[2] = 14, and ipF[3] = 15?

Here is the code in If's and Elses:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
int main() {
    string ip;
    string ipF [3];
    int j = 0;
    cout << "Enter the IP address to be subnetted" << endl
        << "----Example: 192.168.0.1----" << endl << "IP Address: "; getline(cin, ip);
    cout << endl;
    for (int i = 0; i < ip.size(); i++){
        if ( ip[i]!='.' ) {
            ipF[j] += ip[i];
        }else{
            j++;
        }
    }
    cout << ipF[0] << endl;
    system("PAUSE");
}
Last edited on
I am starting to doubt the entire logic behind this code. Maybe it is just wrong, perhaps i'll go with chervil's solution if I can't figure this out.
Last edited on
Here's my attempt.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
#include <vector>
#include <string>
#include <iostream>
#include <sstream>

int main()
{
	std::string ip = "192.168.0.1";

	std::vector<int> octets;

	int start = 0,
		end = std::string::npos;	

	while((end = ip.find('.', start)) != std::string::npos)
	{
		ip[end] = ' ';
		start = end + 1;
	}

	std::stringstream ss(ip);

	int temp = 0;

	while(ss >> temp){ octets.push_back(temp); }	

	for(std::vector<int>::iterator it = octets.begin(); it != octets.end(); ++it)
		std::cout << *it << std::endl;
}
Last edited on
This works great, thanks everyone - I was trying to get this working without stringstream but my brain is about to explode so I concede.
Really, this question is already answered, I'm just posting a variation on the previous solution.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
#include <vector>
#include <string>
#include <iostream>
#include <sstream>
#include <cstdlib>

    using std::string;
    using std::vector;
    using std::cout;
    using std::endl;
    using std::atoi;
    using std::stringstream;

int main()
{
    string ip = "192.168.0.1";
    vector<int> octets;
    stringstream ss(ip);
    string temp;

    while (getline(ss,temp,'.'))
        octets.push_back(atoi(temp.c_str()));

    for (unsigned i=0; i< octets.size(); i++)
        cout << octets[i] << endl;
}


The only question in my mind is how certain we are that the input is valid, which is why my earlier suggestion was substantially longer, in order to catch invalid data.
Last edited on
Nice Chervil - I can handle all the other things, this little 12 line code is more what I was looking for.

So this code turns octets into a object of vector<int> and sets the variable 'ip' up as a stringstream named ss. Then the ss stream produces characters into temp until it reaches '.' delimiter at which time it uses the octets object to push the new c_str converted string, which is converted into an atoi count value, into a new element of octets (octets[0], [1], etc..) then the for loop checkeds the size of octets against i and prints each element.

Does this sum it up correctly? The only thing I'm not sure about is atoi and .c_str()
Last edited on
use two arrays one for storing digits and other for storing dots. i know this is silly answer but work on this idea you will get success
int digits[4];
char dot = '.';
cout<<"please enter ip address digits by digits";
cin>>digits[0]>>digits[1]>>digits[2]>>digits[3];
cout<<"Your IP address is "<<digits[0]<<dot<<digits[1]<<dot<<digits[2]<<dot<<digits[3];

system ("PAUSE");
So far this is what I have, stringstream apparently was the best way.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
vector<int> getOctets(string ip) {
		vector<int> octets;						// Define vector<int> as octets
		stringstream ss(ip);					// use stringstream named ss and populate with ip
		string temp;
		while (getline(ss,temp,'.'))					// Every time getline recieves new stream element from ss, save to temp
			octets.push_back(atoi(temp.c_str()));		//... until reaches '.' delimiter, then push_back octet with new element.
		return octets;
}

int main() {
	cout  << "----Subnetting Calculator----" << endl << endl;
	string ip;
	int count = 0;
	bool rGetOctet = true;
	while (rGetOctet == true) {
		cout << "Enter IP Address to be subnetted" << endl;
		cout << "Example: 192.168.0.1" << endl;
		cout << "IP Address: "; (getline(cin, ip));
		vector<int> octets = getOctets(ip);					// return octets array to main function
		for (int i = 0; i < octets.size(); i++)				// measure array size, print each array (4)
			cout << octets[i] << endl; count++;
		if (octets.size() == 4)
			rGetOctet = false;
		else
			rGetOctet = true;
	}
	system("PAUSE");
}


Having trouble with the loop that will rerun the IP addresses input if the octets don't match certain conditions. using rGetOctet as a repeater. Any ideas? I couldn't figure out how to run an if else in the getOctet() function that would test for this, and return octets if its good, or return octetes +1???? if its bad. Don't know what to return if it's bad, and how to test for that in main. tyring to make the function abstract/generic (right word?)
Last edited on
Let me describe this code the way I see it:
1
2
3
4
5
6
7
8
9
    vector<int> octets;
    stringstream ss(ip);
    string temp;

    while (getline(ss,temp,'.'))
        octets.push_back(atoi(temp.c_str()));

    for (unsigned i=0; i< octets.size(); i++)
        cout << octets[i] << endl;


Line 1. Define an empty vector called octets. This is like an array which can dynamically resize as and when required. It will hold values of type int.

Line 2. Define a stringstream called ss. Load into it the existing string ip.

Line 3. Define an empty string called temp.

That was just the preparation. Now things get more interesting.

Line 5. getline(ss,temp,'.') read a line of text from the stream ss into the string temp. The end of each line is delimited by the '.' character or the end of the stream.

The while loop will repeat until all the lines have been read from the stream.

Line 6.
temp.c_str() convert the std::string into a null-terminated c-string
atoi() convert the contents of the c-string into an integer.
octets.push_back() add the value to the vector.


Lines 8 and 9 simply output each entry in the vector.
Where's the like button? I'll just report you.... lol i joke.
Last edited on
Having trouble with the loop that will rerun the IP addresses input if the octets don't match certain conditions.


That all sounds a bit vague, but I think I understand partly.


What you might do, instead of this:
1
2
3
4
5
6
vector<int> getOctets(string ip) 
{
    vector<int> octets;
    // etc. ....
    return octets;
}


maybe something like this, pass the vector by reference:
1
2
3
4
5
int getOctets(string ip, vector<int> &octets ) 
{
    // etc. ....
    return 0;
}


The return type int could be zero for success, and some other value for various other conditions - if that's what you mean.

Or just test the data in main() instead.
n/a
Last edited on
Pages: 12