C++ - std::vector add, insert, remove, process, erase, swap, sort, clear

2. April 2013 08:00

 

Here is some examples of how to use std::vector with string for most of the common operations that can be performed on std::vector.

 

The following example assume the following has been declared

 

 

std::vector<std::string> vec;

 

 

Adding Items

vec.push_back("Item 1");
vec.push_back("Item 2");
vec.push_back("Item 3");
vec.push_back("Item 4");
vec.push_back("Item 5");

 

Adding Items to front

vec.insert(vec.begin(), "Front 2");
vec.insert(vec.begin(), "Front 1");

 

Remove Last Item

 

vec.pop_back();

 

 

Remove Last Item

 

vec.erase(vec.end());

 

 

Remove First Item

 

vec.erase(vec.begin());

 

 

Process All Items

for(std::vector<std::string>::iterator it = vec.begin(); it != vec.end(); it++)
{
  printf("%s\n", it->c_str());
}

 

Process All Items

for(size_t i = 0; i < vec.size(); i++)
{
  printf("%s\n", vec[i].c_str());
}

 

Reverse The Order - Note you can also just run the above backwards instead.

for(size_t i = 0; i < vec.size() / 2; i++)
{
  std::string tmp = vec[i];
  vec[i] = vec[vec.size() - i - 1];
  vec[vec.size() - i - 1] = tmp;
}

 

Sorting

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

 

Find and Remove an item

for(std::vector<std::string>::iterator it = vec.begin(); it != vec.end(); it++)
{
  if (*it == "Item 2")
  {
    vec.erase(it);
    break;	//it is now invalud must break!
  }
}

 

Clear All Items

vec.clear();
E-mail Kick it! DZone it! del.icio.us Permalink


C++ - Why you need a copy constructor

29. March 2013 10:29

 

In C++ you may come across an issues where you need to use a copy constructor. This is because when a class is assigned from one variable to another it has to copy the values across. If we are dealing with pointers that are inside the class then the pointer will be copied. So this can create and issue if the pointer is deallocated in the destructor. Since now there is two copied of the same pointer which is going to be deallocated twice. This will result in a common issue such as a double free.

 

In this short program you can see the effect here that will cause a double free. In this case I am using "malloc" to keep the example short. The following program will crash when the main function returns as it will call free from the destructor twice on the same pointer value.

 

 

class MyClass {
    public:
        char *buf;
		size_t buf_len;

        MyClass(size_t len) {
            printf("Alloc\n");
			buf_len = len;
            buf = (char *) malloc(len * sizeof(buf));
        }

        ~MyClass() {
            printf("Free\n");
            free(buf);
        }
};


int main(int argc, char **argv) {
    MyClass x = MyClass(4096);
    MyClass y = x;

    return 0;
}

 

 

To get another the issue above in C++ we must use a copy constructor which will allow us to override the default functionality when the class is copied in order to allocate and copy the contents of the buffer and a new pointer which will completly seperate the source class from the new class that is being assigned.

 

 

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

class MyClass {
    public:
        char *buf;
		size_t buf_len;

        MyClass(size_t len) {
            printf("Alloc\n");
			buf_len = len;
            buf = (char *) malloc(len * sizeof(buf));
        }

        ~MyClass() {
            printf("Free\n");
            free(buf);
        }
        
        MyClass(const MyClass &source)
        {
        	buf_len = source.buf_len;
        	buf = (char *) malloc(buf_len * sizeof(buf));
        	memcpy(buf, source.buf, buf_len);
        }
};


int main(int argc, char **argv) {
    MyClass x = MyClass(4096);
    MyClass y = x;

    return 0;
}

 

E-mail Kick it! DZone it! del.icio.us Permalink


C++ - Boost Optional

27. March 2013 17:21

 

Using boost::optional can be an advantage in certain situation. In C++ it effectivly works by being able to turn any datatype into a nullable value. It works much the same way as returning a null pointer to an object but without using a pointer. Instead this will work by being able to return an object which may or may not valid.

 

It is typically used to return a value from a function where the function may fail in certain situations. If you attempt to use the optional value which has not been set it will fail and the program will abort. This of course is also useful for debugging in order to catch issues sooner rather than later by accessing various variable that may not have valid values.

 

It can of course also be used to pass optional paramaters to functions where you may not want to use operator overloading.

 

Here is an example of it converting an string to an int which will obviously fail on one of the strings.

#include <stdio.h>
#include <string>

#include <boost/optional.hpp>

boost::optional<int> func(const std::string &str)
{
        boost::optional<int> value;
        int tmp = 0;

        if (sscanf(str.c_str(), "%d", &tmp) == 1)
                value.reset(tmp);

        return value;
}

int main(int argc, char **argv)
{
        boost::optional<int> v1 = func("31245");
        boost::optional<int> v2 = func("hello");

        if (v1)
                printf("%d\n", v1.get());
        else
                printf("v1 not valid\n");

        if (v2)
                printf("%d\n", v2.get());
        else
                printf("v2 not valid\n");

        return 0;
}
The output of the above is
31245
v2 not valid
E-mail Kick it! DZone it! del.icio.us Permalink


C++ - Check an IP Address is in a IP/Mask range

9. August 2012 08:00

 

This is a short guide on how to check if an ip address is inside a certain ip / mask combination. An example would be to ensure that an ip address like "192.168.0.10" is inside "192.168.0.0/255.255.255.0"

 

One of the problems that you will face is that the standard functions for converting ip addresses to an unsigned int typically will also convert the address to network byte order which will not make. You could use the ntohl function to convert it back or a simple parsing functions like below to convert it to an unsigned long using sscanf.

 

uint32_t IPToUInt(const std::string ip) {
    int a, b, c, d;
    uint32_t addr = 0;

    if (sscanf(ip.c_str(), "%d.%d.%d.%d", &a, &b, &c, &d) != 4)
        return 0;

    addr = a << 24;
    addr |= b << 16;
    addr |= c << 8;
    addr |= d;
    return addr;
}

 

The rest is the very stright forward since an ip address is really just a 32bit number if you convert the ip address the subnet and the mask a stright check can be performed like this.

 

bool IsIPInRange(const std::string ip, const std::string network, const std::string mask) {
    uint32_t ip_addr = IPToUInt(ip);
    uint32_t network_addr = IPToUInt(network);
    uint32_t mask_addr = IPToUInt(mask);

    uint32_t net_lower = (network_addr & mask_addr);
    uint32_t net_upper = (net_lower | (~mask_addr));

    if (ip_addr >= net_lower &&
        ip_addr <= net_upper)
        return true;
    return false;
}

And just to make sure that it works here is some test code.

 

void test(const std::string ip, const std::string network, const std::string mask, bool expected) {
    if (IsIPInRange(ip, network, mask) != expected) {
        printf("Failed! %s %s %s %s\n", ip.c_str(), network.c_str(), mask.c_str(), expected ? "True" : "False");
    } else {
        printf("Success! %s %s %s %s\n", ip.c_str(), network.c_str(), mask.c_str(), expected ? "True" : "False");
    }
}


int main(int argc, char **argv) {
    std::string ip(argv[1]);

    test("192.168.1.1", "192.168.1.0", "255.255.255.0", true);
    test("192.168.1.1", "192.168.1.2", "255.255.255.255", false);
    test("192.168.1.3", "192.168.1.2", "255.255.255.255", false);

    test("220.1.1.22", "192.168.1.0", "255.255.255.0", false);
    test("220.1.1.22", "220.1.1.22", "255.255.255.255", true);
    test("220.1.1.22", "220.1.1.23", "255.255.255.255", false);
    test("220.1.1.22", "220.1.1.21", "255.255.255.255", false);

    test("0.0.0.1", "0.0.0.0", "0.0.0.0", true);
    test("192.168.1.2", "10.0.0.1", "255.255.255.255", false);

    return 0;
}

 

E-mail Kick it! DZone it! del.icio.us Permalink


boost python and custom exception

6. July 2012 08:00

 

One of the problems faced with creating boost python wrappers is that sooner or later you can run into the situation where you need to support extra exception messages which are being thrown from C++ code but are not understood by python or the python wrapper. So this is a guide to support these extra exceptions.

 

You will know that you have come across this issue when you see the following being produced in python. In this case the Example function in C++ throws a MyException class which provides an error message which in its current state just isn't really useful to try to trace the problem.

 

 

>>> import MyClass_py
>>> obj = MyClass_py.MyClass()
>>> obj.Example()
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
RuntimeError: unidentifiable C++ exception
>>>

 

 

In previous posts about creating python wrappers and supporting operator overloading. I have been using much the same example code. In this case it has been changed to add the extra exception. So the C++ code now looks like this.

 

 

class MyException {
	public:
		MyException(const std::string str) {
			m_str = str;
		}
		
		~MyException() {
		
		}
		
		std::string GetMessage() const {
			return m_str;
		}
		
	private:
		std::string m_str;
};

class MyClass {
	public:
		MyClass() { }
		~MyClass() { }
		
		std::string Example() {
			throw(MyException("Hello World"));
		}
		
};

 

 

To get the exception method supported we need to add an exception converter to our python module using a boost python macro register_exception_translator and an extra C/C++ function in our wrapper. Note that the C++ function should not be in the BOOST_PYTHON_MODULE section but the register_exception_translator is. This is how it should look to handle the exception.

Also take note that because the MyExceptionTranslator requires the argument to be a const the functions that you call must also be marked as const or it will not compile. In this case the function for "MyException::GetMessage" must be declared as "std::string MyException::GetMessage() const" to say that it does not modify the contents of the MyException this is because it is meant to be constant.

 

static void MyExceptionTranslator(const MyException &err) {
        PyErr_SetString(PyExc_UserWarning, err.GetMessage().c_str());
}


BOOST_PYTHON_MODULE(MyClass_py)
{
	register_exception_translator<MyException>(&MyExceptionTranslator);

	class_<MyClass>( "MyClass", init<>() )
	
		.def("Example", static_cast< std::string (MyClass::*)() > (&MyClass::Example) )
		
	;
	
}

 

When compiled and run from python we now get the following instead of the useless error message above

 

 

>>> import MyClass_py
>>> obj = MyClass_py.MyClass()
>>> obj.Example()
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
UserWarning: Hello World

 

I have included a full working example.

 

#include <string>

#include <boost/python.hpp>
#include <boost/python/module.hpp>
#include <boost/python/def.hpp>
#include <boost/python/class.hpp>
#include <boost/python/init.hpp>
#include <boost/python/operators.hpp>
#include <boost/python/call_method.hpp>
#include <boost/python/suite/indexing/map_indexing_suite.hpp>
#include <boost/python/suite/indexing/vector_indexing_suite.hpp>
#include <boost/python/module.hpp>
#include <boost/python/def.hpp>
#include <boost/python/implicit.hpp>
#include <boost/python/return_by_value.hpp>
#include <boost/python/return_value_policy.hpp>
#include <boost/python/overloads.hpp>
#include <boost/ref.hpp>
#include <boost/utility.hpp>

using namespace boost::python;


class MyException {
	public:
		MyException(const std::string str) {
			m_str = str;
		}
		
		~MyException() {
		
		}
		
		std::string GetMessage() const {
			return m_str;
		}
		
	private:
		std::string m_str;
};

class MyClass {
	public:
		MyClass() { }
		~MyClass() { }
		
		std::string Example() {
			throw(MyException("Hello World"));
		}
		
};

static void MyExceptionTranslator(const MyException &err) {
        PyErr_SetString(PyExc_UserWarning, err.GetMessage().c_str());
}


BOOST_PYTHON_MODULE(MyClass_py)
{
	register_exception_translator<MyException>(&MyExceptionTranslator);

	class_<MyClass>( "MyClass", init<>() )
	
		.def("Example", static_cast< std::string (MyClass::*)() > (&MyClass::Example) )
		
	;
	
}

The above example can be compiled with

 

g++ -shared -Wall MyClass_py.cpp -o MyClass_py.so -I/usr/include/python2.6/ -lboost_python -lpython2.6

 

E-mail Kick it! DZone it! del.icio.us Permalink