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();
efd8ccd2-aef7-4b35-80d2-0324157dfd97|0|.0
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;
}
479d1833-cf90-445b-b14f-cdd701028d43|0|.0
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
496dacda-fc91-4b30-9647-36f06db5e511|0|.0
6. November 2012 09:27
Short example of using string stream in C++ to build a string.
#include <stdio.h>
#include <iostream>
#include <sstream>
int main(int argc, char **argv) {
std::stringstream ss;
ss << "Hello, World" << "\n" << 42 << "\n";
std::string str = ss.str();
std::cout << str;
return 0;
}
9ec1c55f-4162-4be5-876d-1af7ed67914a|0|.0
By: james
Category: C++
Tags: stringstream
3. November 2012 08:56
This is a short guide on how to override malloc / free in C/C++ on linux so that custom tracing / logging can be used on the functions to detect double free's
It is actually very simple to do. All you require is a short program that is compiled into a shared lib. Then this lib is pre loaded before your program loads and instead of binding to the libc functions it will bind to the ones in the lib.
#include <stdio.h>
#include <dlfcn.h>
extern void abort();
void *malloc(int size) {
void * (*ptr)(int);
void * handle = (void*) -1;
ptr = (void *) dlsym(handle, "malloc");
if (ptr == NULL) {
printf("Opps\n");
abort();
}
void *alloc = (*ptr)(size);
printf("Alloc = %p Size: %d\n", alloc, size);
return alloc;
}
void *realloc(void *alloc, int size) {
void * (*ptr)(void *, int);
void * handle = (void*) -1;
ptr = (void *) dlsym(handle, "malloc");
if (ptr == NULL) {
printf("Opps\n");
abort();
}
alloc = (*ptr)(alloc, size);
printf("Realloc = %p Size: %d\n", alloc, size);
return alloc;
}
void free(void *alloc) {
if (alloc == NULL)
return;
printf("free %p\n", alloc);
void * (*ptr)(void *);
void * handle = (void *) -1;
ptr = (void *) dlsym(handle, "free");
if (ptr == NULL)
abort();
(*ptr)(alloc);
}
You can compile the above with the following command
gcc -Wall sample.c -fPIC -shared -o libsample.so -lc -ldl
Then set the LD_LIBRARY_PATH= so that it includes the path to the location that the libsample.so is in.
Then set the LD_PRELOAD=libsample.so which will tell the dynamic lib loader to load that library first.
Then you can simply run your program.
2bab09cf-663d-47f7-b743-43ce1c453cfc|0|.0