Showing posts with label cplusplus. Show all posts
Showing posts with label cplusplus. Show all posts

Tuesday, August 11, 2015

const pointer to const data in c++

A pointer is a variable and it has got a value as other variable types. A pointer can be declared as a constant.

It is allowed to dereference a constant pointer and assign a new value to the pointed address under suitable conditions.

1-) const pointer to data :

In the following function "constPtrToData()" ptr is initially pointing to the address of the val1 which is holding the value of 10. Later constant pointer ptr is dereferenced and the value at the pointed address changed.

Therefore, the value of val1 and val2 variables becomes the same at the end of the "constPtrToData()" function call.

However, it is not allowed to directly change the address where the constant pointer points to.

If the constant pointer is assigned to the address of the second variable then a compile time error arises.

If you try to assign a new address to the const ptr then the following compile-time error is generated :

error: assignment of read-only variable 'ptr'

This means that you can not change the address assigned to the const pointer.

Terminal output of the "constPtrToData()" function shows that the initial address const ptr holds does not change, but the value stored at this address changes.


#include <iostream>
using namespace std;

void constPtrToData()
{
    //not allowed to change where the ptr points to
    int val1 = 10, val2 = 20;
    int *const ptr = &val1;

    cout << "\n";
    cout << "ptr value = " << *ptr << " address = "<< ptr << "\n";

    *ptr = val2;
    cout << "\n";
    cout << "ptr value = " << *ptr << " address = "<< ptr << "\n";
    cout << "\n";
    cout << "val1 value = " << val1 << " val2 value = " << val2 << "\n";

    // can not assign to constant ptr a new address
    // ptr = &val2;  // error: assignment of read-only variable 'ptr'
}

int main()
{
    constPtrToData();
    cout << "\n";

    return 0;
}



2-) pointer to const data

A pointer can point to constant data. At this time, the address that the pointer points to can be changed but the value can not.

Following compile-time error generated when you try to dereference a pointer which points to const data.

error: assignment of read-only location '* ptr2' 

Main aim of using pointer to const data is to protect the data being pointed to instead of the address of the pointer itself.

In the following "ptrToConstantData()" function, ptr2 is declared as a normal pointer which points to constant data.

For this case, it is allowed to change the address which pointer points to.


#include <iostream>
using namespace std;


void ptrToConstantData()
{
    //protect the value of the variable pointed to
    double val3 = 32, val4 = 45;
    const double *ptr2 = &val3;
    cout << "\n";
    cout << "ptr2 value = " << *ptr2 << " address = " << ptr2 << "\n";

    // can not change the value at the address ptr2 points to
    // *ptr2 = val4;   error: assignment of read-only location '* ptr2'

    // allowed to change the address of the ptr2 points to
    ptr2 = &val4;
    cout << "\n";
    cout << "ptr2 value = " << *ptr2 << " address = " << ptr2 << "\n";
    cout << "\n";
    cout << "val3 value = " << val3 << " val4 value = " << val4 << "\n";
}

int main()
{
    ptrToConstantData();
    cout << "\n";

    return 0;
}


Output of the function call is :



3-) const pointer to const data

Declaring a constant pointer which is pointing to constant data means that you are aiming to protect both the pointer and the data at the pointed address from being modified.

In this case, if you try to change the address of the pointer or dereference the pointer following error messages generated respectively :

error: assignment of read-only variable 'ptr3'

error: assignment of read-only location '*(const int*)ptr3'

Following "constPtrToConstData()" declares ptr3 as a const pointer to const int .


#include <iostream>

using namespace std;


void constPtrToConstData()
{
    //protect both pointer and the data from being modified
    int val1 = 10, val2 = 20;
    const int *const ptr3 = &val1;

    cout << *ptr3 << "\n";

    // ptr3 = &val2;  // error: assignment of read-only variable 'ptr3'
    // *ptr3 = val2;  // error: assignment of read-only location '*(const int*)ptr3'
}

int main()
{    
    constPtrToConstData();
    cout << "\n";

    return 0;
}

When the "constPtrToConstData()" function executed it just prints "10" as expected to the terminal.

Wednesday, July 29, 2015

void* universal pointer

void* also known as universal pointer or generic pointer can be used to hold the address of any type assigned to it.

void* universal pointer can also be used as a function argument.

Below example transferValues function declares two void* arguments.

Instead of writing two different functions for int and double types only one transferValues function with void* arguments can be used.

void* seems to be usable but there are type-safety related problems with void pointer.

With a suitable casting operation existing void* universal pointer can be converted to an appropriate type.

Because a void pointer can not be dereferenced directly, static_cast can be used to cast from void* to another type.

Following error message is generated by the compiler if a void* is dereferenced before casting to an appropriate type.

'void*' is not a pointer-to-object type
           

Example void pointer project compiled with : g++ (Ubuntu 4.9.2-10ubuntu13) 4.9.2


#include <iostream>
using namespace std;

enum ParamType
{
    intType,
    doubleType
};

void transferValues( void* from, void* to, int size, ParamType pType)
{

    if( pType == intType )
    {
         for (int i= 0; i<size; i++)
         {
             static_cast<int*>(to)[i] = static_cast<int*>(from)[i];
         }
    }
    else if( pType == doubleType )
    {
         for (int i= 0; i<size; i++)
         {
             static_cast<double*>(to)[i] = static_cast<double*>(from)[i];
         }
    }
}

int main()
{

    int val = 5;
    void* vPtr = &val;
    // below line generates compile error
    // cout << *vPtr;
    int* newVal = static_cast<int*>(vPtr);
    cout << *newVal << endl;

    double dVal = 5.2;
    vPtr = &dVal;
    double* newDVal = static_cast<double*>(vPtr);
    cout << *newDVal << endl;

    char cVal = 'c';
    vPtr = &cVal;
    char* newCVal = static_cast<char*>(vPtr);
    cout << *newCVal;

    cout << endl << endl;

    int a[5] = { 1, 2, 1, 1, 1 };
    int b[5];

    cout << "Elements of array a = ";
    for( int i = 0; i<5; i++ )
        cout << a[i] << " ";

    cout << endl << "Elements of array b before casting = ";
    for( int i = 0; i<5; i++ )
        cout << b[i] << " ";

    transferValues( a, b, 5, intType );
    cout << endl << "Elements of array b after casting = ";
    for( int i = 0; i<5; i++ )
        cout <<  b[i] << " ";

    double c[5] = { 2.3, 3.3, 4.3, 5.3, 6.3 };
    double d[5];

    cout << endl << endl << "Elements of array c = ";
    for( int i = 0; i<5; i++ )
        cout << c[i] << " ";

    cout << endl <<"Elements of array d before casting = ";
    for( int i = 0; i<5; i++ )
        cout << d[i] << " ";

    transferValues( c, d, 5, doubleType );
    cout << endl << "Elements of array d after casting = ";
    for( int i = 0; i<5; i++ )
        cout << d[i] << " ";

    cout << endl << endl;

    return 0;
}

After running the program following terminal output displayed.


Saturday, July 25, 2015

toLower and toUpper Character Functions in C++ without using string.h and ctype.h

string.h and ctype.h libraries have got functions defined for converting characters from upper case to lower case and vice versa.

Sample functions below achieves in a c program following requirements :

1- convert a given character from lower case to upper case character
2- convert a given character from upper case to lower case character
3- convert a given whole string from lower case to upper case string
4- convert a given whole string from upper case to lower case string

with the following constraints :

1- All letters are English alphabet letters
2- There is no space in the input
3- Only character input is assumed


Main rule to remember when converting case for letters is :

Upper case character = Lower case character - ('a'-'A');
Lower case character = Upper case character + ('a'-'A');

Here the difference ('a'-'A') corresponds to 32.


#include <stdio.h>

char charToLower(const char& cUpper)
{
    if(cUpper>='A' && cUpper<='Z')
        return cUpper+('a'-'A');
    else
        return cUpper;
}

char charToUpper(const char& cLower)
{
    if(cLower>='a' && cLower<='z')
        return cLower-('a'-'A');
    else
        return cLower;
}

char* strToLower( char strUpper[] )
{
    int i = 0;
    while(strUpper[i] != '\0')
        i++;

    char* strLower = new char[i];
    i=0;
    while( strUpper[i] != '\0' )
    {
        if(strUpper[i]>='A' && strUpper[i]<='Z')
            strLower[i] = strUpper[i]+('a'-'A');
        i++;
    }
    return strLower;
}

char* strToUpper( char strLower[] )
{
    int i=0;
    while(strLower[i] != '\0')
        i++;

    char* strUpper = new char[i];
    i=0;
    while( strLower[i] != '\0' )
    {
        if( strLower[i]>='a' && strLower[i]<='z')
            strUpper[i] = strLower[i]-('a'-'A');
        i++;
    }
    return strUpper;
}

int main()
{
    char upperCaseChar = 'C';
    char lowerCaseChar = charToLower(upperCaseChar);
    printf("Upper Case Character : %c \n", upperCaseChar);
    printf("Lower Case Character : %c \n\n", lowerCaseChar);

    char lowerTestChar = 'f';
    char upperTestChar = charToUpper(lowerTestChar);
    printf("Lower Case Character : %c \n", lowerTestChar);
    printf("Upper Case Character : %c \n\n", upperTestChar);

    char upperCaseString[] = "TRKSH";
    char* lowerCaseString = strToLower(upperCaseString);
    printf("Upper Case String : %s \n", upperCaseString);
    printf("Lower Case String : %s \n\n", lowerCaseString);
    delete[] lowerCaseString;

    char lowerCaseTestString[] = "trksh";
    char* upperCaseTestString = strToUpper(lowerCaseTestString);
    printf("Lower Case String : %s \n", lowerCaseTestString);
    printf("Upper Case String : %s \n\n", upperCaseTestString);
    delete[] upperCaseTestString;

    return 0;
}

After running the program following terminal output displayed.


Friday, July 24, 2015

Palindrome String Check in C++ without using string.h

Palindrome check for a given string is very popular starting exercise for new programmers. It has got many implementations in Java and C++. Most of the implementations use existing String class in Java or string.h header in C++.

Following string palindrome check function in c++ without using string.h works with the constraints :

- strings that do not contain any space
- strings just contain English alphabet characters
- strings with more than 3 characters


#include <stdio.h>

int isPalindrome( const char* arr )
{
    int stringLength = 0;
    int index = 0;
    while(arr[index]!='\0')
    {
        ++stringLength;
        ++index;
    }

    if( stringLength >= 0 && stringLength <=2 )
        return 0;

    for(int i = 0; i<stringLength/2; i++)
    {
        if(arr[i] != arr[stringLength-1-i])
            return 0;
    }

    return 1;
}

int main()
{
    const char* stringToCheck1 = "aba";
    int res = isPalindrome(stringToCheck1);
    if(res)
        printf("%s is palindrome\n", stringToCheck1);
    else
        printf("%s is not palindrome\n",stringToCheck1);

    const char* stringToCheck2 = "abba";
    res = isPalindrome(stringToCheck2);
    if(res)
        printf("%s is palindrome\n",stringToCheck2);
    else
        printf("%s is not palindrome\n",stringToCheck2);

    const char* stringToCheck3 = "abccccba";
    res = isPalindrome(stringToCheck3);
    if(res)
        printf("%s is palindrome\n",stringToCheck3);
    else
        printf("%s is not palindrome\n",stringToCheck3);

    const char* stringToCheck4 = "abcc111211ccba";
    res = isPalindrome(stringToCheck4);
    if(res)
        printf("%s is palindrome\n",stringToCheck4);
    else
        printf("%s is not palindrome\n",stringToCheck4);

    const char* stringToCheck5 = "";
    res = isPalindrome(stringToCheck5);
    if(res)
        printf("%s is palindrome\n",stringToCheck5);
    else
        printf("%s is not palindrome\n",stringToCheck5);

    return 0;
}

After executing above main function following terminal output is produced.


Thursday, July 23, 2015

Iterative and Recursive Factorial Functions in C++

Factorial function is defined as a function which multiplies a given number by every number below it until 1.

For example 5!= 5*4*3*2*1=120.

In C++, factorial function can be implemented in an iterative or recursive way.

For big numbers, return value of factorial functions are declared as unsigned long long.


#include <iostream>
using namespace std;

unsigned long long iterativeFactorial( const unsigned int& value )
{
    unsigned long long result=1;
    unsigned long long i=1;
    while(i<=value)
    {
        result *= i++;
    }

    return result;
}

unsigned long long recursiveFactorial( const unsigned int& value )
{
    if( value == 1 || value == 0 )
        return 1;
    return value*recursiveFactorial(value-1);
}

int main()
{
    const unsigned long value = 20;
    unsigned long long iterativeFactorialResult = iterativeFactorial( value );
    cout << "Iterative Factorial Result : "<< iterativeFactorialResult << endl;

    unsigned long long recursiveFactorialResult = recursiveFactorial( value );
    cout << "Recursive Factorial Result : "<< recursiveFactorialResult << endl;

    return 0;
}

Both factorial functions in C++ source code were tested with the same value = 20 and the following result is achieved.


Wednesday, July 22, 2015

Call Function From PostgreSQL with Qt SQL

Qt SQL enables programmers to call written functions from PostgreSQL database. Example project contains following table and functions from PostgreSQL server.

Configuration required to run this application:

1-) PostgreSQL 9.4.4
2-) Qt Version 5.4.0
3-) Qt Creator 3.2.2

PostgreSQL has got its own database programming language named with PL/pgSQL and following functions implemented in PL/pgSQL.

-- Table: person

-- DROP TABLE person;

CREATE TABLE person
(
  id integer NOT NULL,
  name text NOT NULL,
  age integer NOT NULL,
  address character(50),
  CONSTRAINT person_pkey PRIMARY KEY (id)
)
WITH (
  OIDS=FALSE
);
ALTER TABLE person
  OWNER TO test;


person table is filled with the following sample records/rows in order to see the execution result.

INSERT INTO person(
            id, name, age, address)
    VALUES (1, 'paul', 12, 'adana');

INSERT INTO person(
            id, name, age, address)
    VALUES (2, 'tufan', 15, 'ankara');

INSERT INTO person(
            id, name, age, address)
    VALUES (3, 'colin', 18, 'antep');

First PostgreSQL PL/pgSQL function returns the max age from the person table.
CREATE OR REPLACE FUNCTION maxAge()
RETURNS integer AS $$
declare
 max_age integer;
BEGIN
   SELECT max(age) into max_age FROM person;
   RETURN max_age;
END;
$$ LANGUAGE plpgsql;

maxAge() plpgsql function called with a select statement from pgAdmin III Query Tool.
SELECT maxage();

Output of the call of the maxage() function from PostgreSQL database is "18".

Second PostgreSQL PL/pgSQL function returns the age of the person whose name is sent as a parameter from the person table.
CREATE OR REPLACE FUNCTION getAgeOfPersonByName( nameOfPerson text )
RETURNS integer AS $$
declare
 person_age integer;
BEGIN
   SELECT age into person_age FROM person where name=nameOfPerson;
   RETURN person_age;
END;
$$ LANGUAGE plpgsql;

getAgeOfPersonByName( nameOfPerson text ) plpgsql function called with a select statement from pgAdmin III Query Tool.

SELECT getAgeOfPersonByName('paul');
Output of the call of the getAgeOfPersonByName('paul') function from PostgreSQL database is "12".

After creating the required tables and functions in PostgreSQL, now it is time to write our Qt application that calls these PL/pgSQL functions from PostgreSQL with Qt SQL.

Following sample project created by qt creator and contains following files :

1- QtSQLCallFunctionFromPostgreSQL.pro
2- main.cpp


QtSQLCallFunctionFromPostgreSQL.pro file contains project configuration :

TEMPLATE  = app
CONFIG   += console
CONFIG   -= app_bundle
QT       += core sql
QT       -= gui
TARGET = QtSQLCallFunctionFromPostgreSQL
SOURCES += main.cpp
Sample project only contains main.cpp file as source file. maxAge and getAgeOfPersonByName PL/pgSQL functions from PostgreSQL are called and return values are displayed in the terminal.

#include <QCoreApplication>
#include <QtSql>
#include <QDebug>

int main()
{
    const char* driverName = "QPSQL";
    QSqlDatabase db( QSqlDatabase::addDatabase(driverName) );
    db.setConnectOptions();
    db.setHostName("localhost");
    db.setDatabaseName("testdb");
    db.setUserName("test");
    db.setPassword("test");

    db.open();

    QString functionNameToCall = "maxAge";
    QSqlQuery* query = new QSqlQuery(db);
    query->prepare(QString("SELECT %1()").arg(functionNameToCall));
    query->exec();

    QString maxAgeOfPersonTable;
    while (query->next())
    {
        maxAgeOfPersonTable = query->value(0).toString();
    }

    qDebug() << maxAgeOfPersonTable;

    functionNameToCall = "getageofpersonbyname";
    QString name = "paul";
    query->prepare(QString("SELECT %1(?)").arg(functionNameToCall));
    query->addBindValue(name);
    query->exec();

    QString personAge;
    while (query->next())
    {
        personAge = query->value(0).toString();
    }

    qDebug() << personAge;

    delete query;
    db.close();

    return 0;
}


getageofpersonbyname PL/pgSQL function takes a parameter and the parameter is binded by addBindValue function of QSqlQuery. When the Qt application runs in the terminal the following output is displayed.


Sunday, July 19, 2015

Connect to PostgreSQL From Qt Application with Qt Sql

Qt comes with Qt Sql APIs in order to perform database related operations. Qt SQL's APIs consist of mainly three parts.
- Driver Layer
- SQL API Layer
- User Interface Layer

In order to connect to a database from Qt application, related database driver needs to be configured.
After setting connection to a specific database from Qt application, SQL API helps to achieve common database operations such as open-close connection, query tables, etc.

Configuration required to run this application:

1-) PostgreSQL 9.4.4
2-) Qt Version 5.4.0
3-) Qt Creator 3.2.2


Create sql script for Person table: You can use pgAdmin tools in order to create tables on postgreSQL database.

-- Table: person

-- DROP TABLE person;

CREATE TABLE person
(
  id integer NOT NULL,
  name text NOT NULL,
  age integer NOT NULL,
  address character(50),
  CONSTRAINT person_pkey PRIMARY KEY (id)
)
WITH (
  OIDS=FALSE
);
ALTER TABLE person
  OWNER TO test;


Following sample project created by qt creator and contains following files :

1- QSqlConnection.pro
2- QSQLDbHelper.h
3- QSQLDbHelper.cpp
4- main.cpp



QSqlConnection.pro file contains project configuration :

TEMPLATE  = app
CONFIG   += console
CONFIG   -= app_bundle
QT       += core sql
QT       -= gui
SOURCES  += main.cpp \
    QSQLDbHelper.cpp

HEADERS += \
    QSQLDbHelper.h


In this example qt sql project QSQLDbHelper.h class header file contains database related functions.


#ifndef QSQLDBHELPER_H
#define QSQLDBHELPER_H

#include <QtSql>
#include <QString>
#include <QDebug>

class QSQLDbHelper
{
public:
    QSQLDbHelper(const char* driver);
    ~QSQLDbHelper();
    QSqlDatabase* connect( const QString& server,
                           const QString& databaseName,
                           const QString& userName,
                           const QString& password );
    void disConnect();

    int selectRowCountResult(QSqlQuery* query);
    bool executeInsert(QSqlQuery* query);
    bool executeUpdate(QSqlQuery* query);
    bool executeDelete(QSqlQuery* query);

private:
    QSqlDatabase* db;
};

#endif // QSQLDBHELPER_H


QSQLDbHelper.cpp file contains implementation details for the following functions :

1- Class constructor/desctructor
2- Db connect
3- Db disconnect
4- selectRowCount
5- insert operation
6- update operation
7- delete operation


#include "QSQLDbHelper.h"

QSQLDbHelper::QSQLDbHelper(const char* driver)
{
    db = new QSqlDatabase( QSqlDatabase::addDatabase(driver) );
}

QSQLDbHelper::~QSQLDbHelper()
{
    qDebug() << "Called Destructor!";
    delete db;
}

QSqlDatabase* QSQLDbHelper::connect( const QString& server,
                                     const QString& databaseName,
                                     const QString& userName,
                                     const QString& password )
{
    db->setConnectOptions();
    db->setHostName(server);
    db->setDatabaseName(databaseName);
    db->setUserName(userName);
    db->setPassword(password);

    if(db->open()) {
        return db;
    }
    else {
        return NULL;
    }
}

int QSQLDbHelper::selectRowCountResult(QSqlQuery* query)
{
    bool queryRes = query->exec();
    if (query->lastError().type() != QSqlError::NoError || !queryRes)
    {
        qDebug() << query->lastError().text();
        return -1;
    }

    int recordCount = 0;
    while (query->next())
    {
        qDebug() << "Field 1 : " << query->value(0).toString() 
                 << "Field 2 : " << query->value(1).toString();
        ++recordCount;
    }

    return recordCount;
}

bool QSQLDbHelper::executeInsert(QSqlQuery* query)
{
    db->transaction();
    bool queryRes = query->exec();
    if (query->lastError().type() != QSqlError::NoError || !queryRes)
    {
        qDebug() << query->lastError().text();
        db->rollback();
        return false;
    }
    db->commit();
    return true;
}

bool QSQLDbHelper::executeUpdate(QSqlQuery* query)
{
    db->transaction();
    bool queryRes = query->exec();
    if (query->lastError().type() != QSqlError::NoError || !queryRes)
    {
        qDebug() << query->lastError().text();
        db->rollback();
        return false;
    }
    db->commit();
    return true;
}

bool QSQLDbHelper::executeDelete(QSqlQuery* query)
{
    db->transaction();
    bool queryRes = query->exec();
    if (query->lastError().type() != QSqlError::NoError || !queryRes)
    {
        qDebug() << query->lastError().text();
        db->rollback();
        return false;
    }
    db->commit();
    return true;
}

void QSQLDbHelper::disConnect()
{
    qDebug() << "Disconnected From Database!";
    db->close();
}


In order to make database related operations from a qt application it is required to include "QtSql" header file into the related source file.

QSqlDatabase class represents a database in your application. A transaction is started and concluded by using rollback() and commit() functions of QSqlDatabase.

QSqlQuery class executes passed sql queries on postgresql database.

Main method in the main.cpp file calls implemented connect, disconnect and CRUD operation methods from QSQLDbHelper class.


#include <iostream>

#include <QDebug>
#include "QSQLDbHelper.h"

int main()
{
    qDebug() << "Compiled with Qt Version = " << QT_VERSION_STR;

    const char* driverName = "QPSQL";
    QSQLDbHelper* qSQLDbHelper = new QSQLDbHelper(driverName);
    QSqlDatabase* db = qSQLDbHelper->connect("localhost", "testdb", "test", "test");

    if(db->open()) {

        QSqlQuery* query = new QSqlQuery(*db);
        query->setForwardOnly(true);

        // Select empty person table
        QString name = "Paul";
        if( !query->prepare(QString("SELECT id, name from person where name = ? ")) )
        {
            qDebug() <<"Error = " << db->lastError().text();
            return -1;
        }
        else
            query->addBindValue(name);

        int queryResultRowCount = qSQLDbHelper->selectRowCountResult(query);
        qDebug() << "Initial Row Count = " << queryResultRowCount << "\n";

        // insert into empty person table
        QString id = "1";
        QString age = "34";
        QString address = "istanbul";
        if( !query->prepare(
        QString("INSERT INTO person( id, name, age, address) VALUES ( ?, ?, ?, ?)") ))
        {
            qDebug() <<"Error = " << db->lastError().text();
            return -1;
        }
        else
        {
            query->addBindValue(id);
            query->addBindValue(name);
            query->addBindValue(age);
            query->addBindValue(address);
        }

        bool result = qSQLDbHelper->executeInsert(query);
        if( result )
            qDebug() << "Successful insert";
        else
            qDebug() << "Insert failed";

        // Select person table with 1 matching record
        if( !query->prepare(
        QString("SELECT id, name from person where name = ? ")))
        {
            qDebug() <<"Error = " << db->lastError().text();
            return -1;
        }
        else
            query->addBindValue(name);

        queryResultRowCount = qSQLDbHelper->selectRowCountResult(query);
        qDebug() << "After Insert Row Count = " << queryResultRowCount << "\n";


        // Update person table
        name = "Paul2";
        if( !query->prepare(QString("UPDATE person set name=? where id =? ")) )
        {
            qDebug() <<"Error = " << db->lastError().text();
            return -1;
        }
        else
        {
            query->addBindValue(name);
            query->addBindValue(id);
        }

        result = qSQLDbHelper->executeUpdate(query);
        if( result )
            qDebug() << "Successful update";
        else
            qDebug() << "Update failed";

        // Select person table with 0 no matching record
        if( !query->prepare(
        QString("SELECT id, name from person where name = ?")) )
        {
            qDebug() <<"Error = " << query->lastError().text();
            return -1;
        }
        else
        {
            query->addBindValue(name);
        }
        queryResultRowCount = qSQLDbHelper->selectRowCountResult(query);
        qDebug() << "After Update Row Count = " << queryResultRowCount << "\n";


        // Delete from person table whose name is Paul2
        // name = "Paul2";
        if( !query->prepare(QString("Delete from person where name =? ")) )
        {
            qDebug() << "Error = " << db->lastError().text();
            return -1;
        }
        else
        {
            query->addBindValue(name);
        }

        result = qSQLDbHelper->executeDelete(query);
        if( result )
            qDebug() << "Successful delete";
        else
            qDebug() << "Delete failed";

        // Select person table with 0 no matching record
        if( !query->prepare(
        QString("SELECT id, name from person where name = ? ")) )
        {
            qDebug() << "Error = " << db->lastError().text();
            return -1;
        }
        else
        {
            query->addBindValue(name);
        }
        queryResultRowCount = qSQLDbHelper->selectRowCountResult(query);
        qDebug() << "After Delete Row Count = " << queryResultRowCount << "\n";

        delete query;
    }
    else {
        qDebug() << "Something went Wrong:" << db->lastError().text();
    }

    qSQLDbHelper->disConnect();
    delete qSQLDbHelper;

    return 0;
}


In main function database connection is established and related database related operations are being tested. Parametric, dynamic sql queries created by using addBindValue method of QSqlQuery.

Output of the execution of this program shows database operation results from Qt application in terminal.


Tuesday, June 16, 2015

Thread Safe Singleton XMLReader with QMutex and boost property tree

Singleton design pattern is used widely when only one instance of an object needs to be created in the application domain. In order to achieve secure creation of singleton instance in multithreaded environments, locking mechanism must be taken into consideration to provide thread safety.

XML configuration settings file access can be handled by creating a thread-safe singleton XMLParser class. Boost library has got a Property Tree library, boost::property_tree , which populates a tree data structure that is representing the existing XML file content.

boost::property_tree makes it easy to load an existing XML file into application. In order to provide thread safety for singleton XMLParser , QT application development framework supplied QMutex class can be used.

Following sample project created by qt creator and contains following files :

1-SingletonXMLParser.pro
2-XmlParser.h
3-XmlParser.cpp
4-main.cpp



SingletonXMLParser.pro file contains project configuration :

QT       += core
TARGET    = SingletonXMLParser
CONFIG   += console
CONFIG   -= app_bundle
TEMPLATE  = app
SOURCES  += main.cpp \
            XmlParser.cpp
HEADERS  += XmlParser.h

In this example project, XMLParser.h header file contains the Settings struct which is going to hold data loaded from XML file. Also the name of the XML file is declared in the header file with a #define directive.

Requirements to make XMLParser class a Thread-Safe Singleton is handled by

1- Making constructor private
2- Adding a static XMLParser variable
3- Static Instance creator method
4- QMutex variable for locking


Example ConfSettings.xml file contains following data and placed under an accessible folder :


#ifndef XMLPARSER_H
#define XMLPARSER_H

#define CONF_SETTINGS_FILE "ConfSettings.xml"

#include <boost/property_tree/ptree.hpp>
#include <boost/property_tree/xml_parser.hpp>

#include <QMutex>

struct Settings
{
    std::string ipAddress;
    std::string userName;
};

class XMLParser
{
public:
    static XMLParser& instance();
    ~XMLParser();
    Settings getSettings();

private:
    XMLParser();
    Settings configSettings;
    static std::auto_ptr<XMLParser> mInstance;
    static QMutex mMutex;
};

#endif // XMLPARSER_H


XMLParser.cpp file contains implementation details for

1- private constructor
2- static instance creator method
3- static variables


#include "XmlParser.h"

std::auto_ptr<XMLParser> XMLParser::mInstance;
QMutex XMLParser::mMutex(QMutex::Recursive);

XMLParser::XMLParser()
{
    boost::property_tree::ptree config;
    read_xml(CONF_SETTINGS_FILE, config);

    configSettings.ipAddress = config.get<std::string>("ftp.ipAddress");
    configSettings.userName = config.get<std::string>("ftp.userName");
}

XMLParser::~XMLParser()
{
}

XMLParser& XMLParser::instance()
{
    mMutex.lock();
    if (mInstance.get() == 0)
    {
        try
        {
            mInstance.reset(new XMLParser);
        }
        catch (std::bad_alloc&)
        {
            throw;
        }
    }
    mMutex.unlock();
    return *mInstance;
}

Settings XMLParser::getSettings()
{
    return configSettings;
}


In the constructor of the XMLParser class CONF_SETTINGS_FILE is loaded into boost::property_tree::ptree type config variable. Then by applying the get method of boost::property_tree::ptree required elements from the XML document are retrieved into the application.

Static instance() method of XMLParser provides thread safety by calling lock() and unlock() methods of QMutex instance.

Main method in the main.cpp file calls the static instance() method of thread-safe singleton XMLParser class and then loads the config settings into to Settings struct.

#include "XmlParser.h"

int main()
{
    Settings confSettings = XMLParser::instance().getSettings();

    std::cout << confSettings.ipAddress << std::endl;
    std::cout << confSettings.userName << std::endl;

    return 0;
}

Output of the execution of this program shows ipAddress and userName element values from ConfSettings.xml file on the terminal.


Saturday, March 28, 2015

Serialize C++ Object with QString Instance Variables

boost::serialization library can be used to serialize and deserialize the state of QString variables in a C++ program.
By default boost::serialization library can not serialize a directly given QString variable, so you need an extra Serializer implementation for your serialization and deserialization requirements.

When you try to serialize a QString variable directly by using boost::serialization library, compiler gives errors about missing serialize method as follows :

error: 'class QString' has no member named 'serialize'

In order to use boost::serialization library in your applications, it is required to have libboost-all-dev library on your OS which contains libboost-serialization-dev. Following terminal command installs required boost libraries on linux OS :

$ sudo apt-get install libboost-all-dev

After installing boost serialization library, you can start including related header files into your application.

Following sample project created by qt creator and contains following files :

1-BoostSerializeQString.pro
2-QStringSerializer.h
3-User.h
4-main.cpp



BoostSerializeQString.pro file contains project configuration.

QT       += core
TARGET    = BoostSerializeQString
CONFIG   += console
CONFIG   -= app_bundle
TEMPLATE  = app
LIBS     += -lboost_serialization

SOURCES  += main.cpp

HEADERS  += QStringSerializer.h \
            User.h

boost_serialization library is included into this Qt Project by adding "LIBS += -lboost_serialization" line.
In this example User class contains two QString instance variables to serialize and deserialize. When saving and loading User class it is required to save and load QString variable state properly. Also, User class has an intrusive serialize function. For User class case, the serialize function is implemented as a member of the class.

#ifndef USER_H
#define USER_H

class User
{
public:

    User() {}

    User(const QString &name, const QString &surname)
    {
        this->name = name;
        this->surname = surname;
    }

    QString getName() { return name; }
    QString getSurname() { return surname; }

private:
    QString name;
    QString surname;

    friend class boost::serialization::access;
    template<class Archive>
    void serialize(Archive & ar, const unsigned int version)
    {
        // serialize deserialize QString instance variables
        ar & BOOST_SERIALIZATION_NVP(name);
        ar & BOOST_SERIALIZATION_NVP(surname);
    }

};

#endif // USER_H


QStringSerializer.h file contains save and load functions which are going to be invoked during serialization and deserialization process of QString instance variables.

By declaring non-intrusive serialization mechanism we were able to implement serialization for QString without changing its original class definition.

boost::serialization is able to work on std::string type correctly, so it is required to retrieve std::string value of QString for serialization. And also for the reverse operation it is required to construct QString from loaded std::string value.

QString has got both toStdString and fromStdString functions to achieve these requirements.

Inside serialize and deserialize functions different statements are executed so it is required to implement save and load functions separately.

Depending on the type of the archieve used for saving or loading current QString variable, save or load function is invoked.

#ifndef QSTRINGSERIALIZER_H
#define QSTRINGSERIALIZER_H

namespace boost {
    namespace serialization {

        template<class Archive>
        void save( Archive & ar, const QString& qStringParam, const unsigned int )
        {
            // save class member variables
            std::string stdString = qStringParam.toStdString();
            ar & BOOST_SERIALIZATION_NVP(stdString);
        }

        template<class Archive>
        void load( Archive & ar, QString& qStringParam, const unsigned int )
        {
            // load class member variables
            std::string stdString;
            ar & BOOST_SERIALIZATION_NVP(stdString);
            qStringParam = qStringParam.fromStdString(stdString);
        }

        template<class Archive>
        void serialize(Archive & ar, QString & t, const unsigned int file_version)
        {
            split_free(ar, t, file_version);
        }

    } // namespace serialization
} // namespace boost
#endif // QSTRINGSERIALIZER_H


main method in main.cpp file contains two code blocks which are respectively used for serialization and deserialization of User object with QString instance variables or states. After reconstructing User object, QString instance variables name and surname are initialized with the original values as serialized.

#include <boost/archive/xml_iarchive.hpp>
#include <boost/archive/xml_oarchive.hpp>
#include <boost/serialization/string.hpp>
#include <boost/serialization/nvp.hpp>

#include <QString>
#include <fstream>
#include <iostream>

#include "User.h"
#include "QStringSerializer.h"

using namespace std;

int main()
{
        {
            // Initialize User object to serialize with data
            User user("userName","userSurname");
            std::ofstream ofs("stateInfoFile.xml");
            boost::archive::xml_oarchive oa(ofs);
            // write class instance to archive
            oa & BOOST_SERIALIZATION_NVP(user);
        }

        {
            User user;
            std::ifstream ifs("stateInfoFile.xml");
            boost::archive::xml_iarchive ia(ifs);
            // read class instance back from archive
            ia & BOOST_SERIALIZATION_NVP(user);

            std::cout << "Name : " << user.getName().toStdString() << std::endl;
            std::cout << "Surname : " << user.getSurname().toStdString() << std::endl;
        }
}


User object state is saved into stateInfoFile.xml file and loaded back from the same xml file again for object reconstruction. stateInfoFile.xml file is an xml file and its content is as follows :


Thursday, September 25, 2014

Using Enumeration in C++

Enumeration in C++ is a user defined type that contains a set of constant values. An enumeration consists of an identifier and a list of types. Every type in an enumeration corresponds to a constant value. Default value for the first type is integer 0 and the next one gets the integer value 1. But an enumeration type can have a value other than default integer 0. Therefore an enum type can be casted to integer.


Following sample project created by qt creator and contains following files:
1- UsingEnumeration.pro
2- device.h
3- device.cpp
4- main.cpp



UsingEnumeration.pro file contains project configuration.

TEMPLATE = app
CONFIG += console
CONFIG -= app_bundle
CONFIG -= qt
SOURCES += main.cpp \
    device.cpp
HEADERS += \
    device.h

device.h header file contains definition for Device class and Status enumeration.

#ifndef DEVICE_H
#define DEVICE_H

namespace UsingEnumsSample
{

enum Status {
    IDLE = 0,
    ACTIVE = 1,
    DEAD = 2
};

class Device
{
public:

    Device();
    void setStatus(Status pStatus);
    Status getStatus();

private:
    Status status;
};

}

#endif // DEVICE_H


device.cpp file contains implementation for Device class. setDevice method accepts an enumerator and assigns the passed value to Device class private enumeration member.

#include "device.h"

namespace UsingEnumsSample
{

Device::Device()
{
}

void Device::setStatus(Status pStatus)
{
    status = pStatus;
}

Status Device::getStatus()
{
    return status;
}

}

main.cpp method creates a Device instance and calls its setStatus and getStatus methods to set the Status value to the private Status enumeration member.

#include <iostream>
#include "device.h"

using namespace std;
using namespace UsingEnumsSample;

int main()
{
    Device device;
    device.setStatus(ACTIVE);
    cout << device.getStatus() << endl;
    device.setStatus(IDLE);
    cout << device.getStatus() << endl;
    return 0;
}

When the main method is executed, values of the Status member is displayed on the terminal which are consequently 1 and 0 as the program runs.

Wednesday, August 13, 2014

boost::array of std::string items in Qt Creator

boost::array is a template class which enables it to be able to be declared for different type of items. There exists an array as a member inside boost:array template class declaration so boost:array also acts a C-array wrapper with fixed number of items inside it.

Following sample project created by qt creator and contains following files:
1- BoostArrayOfStrings.pro
2- main.cpp



BoostArrayOfStrings.pro file contains project configuration.

TEMPLATE = app
CONFIG += console

SOURCES += main.cpp

INCLUDEPATH += /home/tufan/boost_1_55_0

Boost header files and libraries are located under the directory : /home/tufan/boost_1_55_0

main.cpp file contains main method.

#include <boost/array.hpp>
#include <string.h>

using namespace std;

int main()
{
    typedef boost::array<string,3> boostArray;
    boostArray stringArray;

    stringArray[0] = "FirstStringMember";
    stringArray.at(1) = "SecondStringMember";
    stringArray.at(2) = "ThirdStringMember";

    // some common container operations
    cout << "size:     " << stringArray.size() << endl;
    cout << "empty:    " << boolalpha << stringArray.empty() << endl;
    cout << "front:    " << stringArray.front() << endl;
    cout << "back:     " << stringArray.back() << endl;
    cout << "elements:    " << endl;

    for(boostArray::iterator iter(stringArray.begin()); iter != stringArray.end(); ++iter)
    {
        cout << *iter << endl;
    }

    return 0;
}
boost array contains 3 string items. Members of the array are initialized by using array subscript operator and at() function.

size:     3
empty:    false
front:    FirstStringMember
back:     ThirdStringMember
elements:  
FirstStringMember
SecondStringMember
ThirdStringMember

Tuesday, August 12, 2014

boost::array of Integers in Qt Creator

boost::array provides C-style array declaration and usage with constant number of items inside it. When only static-constant sized arrays are required, then boost::array comes with a better memory management solution than std::vector.

After including boost libraries into a Qt Creator C++ project, it becomes easy to use boost::array type of members in your programs.

boost/array.hpp file contains boost::array type.

As the boost::array documentation indicates boost::array is the STL compliant container wrapper for arrays of constant size.



Following sample project created by qt creator and contains following files:

1- BoostArrayOfIntegers.pro
2- main.cpp


BoostArrayOfIntegers.pro file contains project configuration.
TEMPLATE = app
CONFIG += console

SOURCES += main.cpp

INCLUDEPATH += /home/tufan/boost_1_55_0

I have installed the boost library to the directory         :  /home/tufan/boost_1_55_0
and boost/array.hpp file is located at                           :  /home/tufan/boost_1_55_0/boost/array.hpp

so qt creator does not complain about path related errors.


There is also another installed boost library which contains an older version of boost libraries  at directory : /usr/include/boost


In BoostArrayOfIntegers.pro file I have stated that I will use the boost library from specific location and qt creator selected the library from : /home/tufan/boost_1_55_0


main.cpp file contains main method.

#include <boost/array.hpp>

using namespace std;

int main()
{
    typedef boost::array<int, 4> intArrayType;
    intArrayType myArray = {{1,2,3,4}};
    std::cout << "boost intArray content :" << "\n";
    for( intArrayType::const_iterator iterator = myArray.begin(),
         iteratorEnd = myArray.end();
         iterator != iteratorEnd; ++iterator )
    {
        cout << *iterator << endl;
    }

    return 0;
}
boost::array is initialized with 4 integer members in curly braces. I used an iterator to traverse the integer members of the boost::array.

When the project is executed the following terminal output is generated :

boost intArray content :
1
2
3
4

Friday, August 1, 2014

Build Boost 1.55.0 C++ Libraries on Ubuntu

  Boost libraries are used by C++ programmers to increase the productivity of software product development process. Instead of reinventing the wheel, by using Boost libraries initial-development time costs are decreased remarkably.
  Boost libraries include many benefits for C++ programmers, such as shared_ptr, arrays, serialization, I/O etc. , which most of the time causes troubles. So it becomes crucial to invest time to learn Boost libraries for a C++ programmer to use these benefits and advantages.
  Most Linux distributions come with pre-installed Boost libraries. However, they do not always contain the latest version of Boost libraries.
  In order to build and start using on Ubuntu OS following steps can be followed :

1- download boost_1_55_0.zip file from
 
    http://sourceforge.net/projects/boost/files/boost/1.55.0/

2- unzip your downloaded boost_1_55_0.zip file

    $ unzip boost_1_55_0.zip

3- get required dependencies which are going to help you during build process
 
    $ sudo apt-get update
    $ sudo apt-get install build-essential g++ python-dev autotools-dev libicu-dev build-essential libbz2-dev

4- change your location into your unzipped boost_1_55_0 folder from terminal
 
    $ cd boost_1_55_0/

5- start bootstrapping

    $ ./bootstrap.sh --prefix=/usr/local

6- start building boost libraries

    $ sudo ./b2

7- after waiting for a time-period all the Boost libraries are built successfully.

    "The Boost C++ Libraries were successfully built!"

8- now Boost header files and libraries are ready for being used in your C++ applications.

Sunday, May 11, 2014

Throw and Catch Custom Exception Object in C++

Exceptions are run-time errors that occur during program execution. C++ Standard Library comes with a base class "exception" which is mainly dealing with exceptions. In some circumstances it is required to create-design your own custom exception classes in C++ as in other object oriented programming languages.
what() function of exception class of C++ Standard Library used to provide detailed information about the problem to the client program code in the case of an exception.

Following sample project created by qt creator and contains following files:
1- CustomException.pro
2- DequeWrapper.h
3- DequeWrapper.cpp
4- EmptyContainerException.h
5- EmptyContainerException.cpp
6- main.cpp

CustomException.pro file contains project configuration.

TARGET = CustomException
TEMPLATE = app
SOURCES += main.cpp \
           DequeWrapper.cpp \
           EmptyContainerException.cpp

HEADERS += \
           DequeWrapper.h \
           EmptyContainerException.h

main.cpp file contains main method and the usage of the EmptyContainerException exception instance.
#include "DequeWrapper.h"
#include <iostream>

using namespace std;
using namespace CustomContainers;

int main()
{
    try
    {
        DequeWrapper mDequeWrapper;
        mDequeWrapper.popBack();
    }
    catch(const EmptyContainerException& ex)
    {
        cerr << ex.what() << endl;
    }

    return 0;
}

DequeWrapper.h is the header file for the deque wrapper class declaration.
#ifndef DEQUEWRAPPER_H
#define DEQUEWRAPPER_H

#include <deque>
#include "EmptyContainerException.h"

namespace CustomContainers
{

class DequeWrapper
{
public:
    bool empty() const;
    int popBack();

protected:
    std::deque mDeque;
};

}
#endif // DEQUEWRAPPER_H

DequeWrapper.cpp is the implementation file for the deque wrapper header file.

#include "DequeWrapper.h"

namespace CustomContainers
{

bool DequeWrapper::empty() const
{
    return mDeque.empty();
}

int DequeWrapper::popBack()
{

    if(mDeque.empty())
        throw EmptyContainerException();

    int mItem(mDeque.back());
    mDeque.pop_back();
    return mItem;
}

}
EmptyContainerException.h file is the header file for the custom exception class declaration.
#ifndef EMPTYCONTAINEREXCEPTION_H
#define EMPTYCONTAINEREXCEPTION_H

#include <exception>

namespace CustomContainers
{

class EmptyContainerException : public std::exception
{
    public:
        virtual const char* what() const throw();
};

}

#endif // EMPTYCONTAINEREXCEPTION_H

EmptyContainerException.cpp file is the implementation file for the custom exception class header file.

#include "EmptyContainerException.h"

namespace CustomContainers
{

const char* EmptyContainerException::what() const throw()
{
    return "container is empty!";
}

}

std::exception what() method is reimplemented in the derived class EmptyContainerException to provide the description of the exception. When you run the above sample program main method following console output "container is empty" exception message is generated :


Wednesday, March 5, 2014

Binary Search Sorted Int Array Recursively

There exists a recursive solution for the binary search algorithm. At each step lower and higher bounds for the search interval are updated and the search key is scanned in this new updated interval.
For recursive binary search implementation; search interval is updated depending on the midPoint value.

midPoint = lowerBound+(higherBound-lowerBound)/2

For the starting step; lowerBound is 0 and higherBound is the last array index.

Following sample project created by qt creator and contains following files:
1- SearchIntArrayRecursively.pro
2- main.cpp


SearchIntArrayRecursively.pro file contains project configuration.

TEMPLATE = app
CONFIG += console
CONFIG -= app_bundle
CONFIG -= qt
SOURCES += main.cpp

main.cpp file contains main method and recursive binarySearch function implementations.

#include <stdio.h>

int getIndexOfItemRecursively(int pSearchedItem, int* pArray, int mLowerBound, int mHigherBound)
{
    if( mLowerBound > mHigherBound )
        return -1;
    int midIndex = mLowerBound+(mHigherBound-mLowerBound)/2;

    if( pSearchedItem < pArray[midIndex] )
        return getIndexOfItemRecursively(pSearchedItem, pArray, mLowerBound, midIndex-1);
    else if(pSearchedItem>pArray[midIndex])
        return getIndexOfItemRecursively(pSearchedItem, pArray, midIndex+1, mHigherBound );
    else
        return midIndex;
}

int findIndexOfItem( int pSearchedItem, int* pArray, int pTotalItemCount )
{
    return getIndexOfItemRecursively(pSearchedItem, pArray, 0, pTotalItemCount-1);
}

int main(int argc, char* argv[])
{
    int mArray[] = {1, 2, 4, 12, 34, 45, 56, 67, 78, 89, 90};
    int mLengthOfArray = sizeof(mArray)/sizeof(int);
    printf("There are %d items in the array\n", mLengthOfArray);
    printf("Items :\n");
    for(int i = 0; i<mLengthOfArray; i++)
    {
        if( i!=mLengthOfArray-1 )
            printf("%d,", mArray[i]);
        else
            printf("%d\n", mArray[i]);
    }
    printf("Indexes :\n");
    for(int i = 0; i<mLengthOfArray; i++)
    {
        if( i!=mLengthOfArray-1 )
            printf("%d,", i);
        else
            printf("%d\n\n", i);
    }
    int mSearchItem = 12;
    int mIndex = findIndexOfItem( mSearchItem, mArray, mLengthOfArray );
    if( mIndex!=-1 )
        printf("Item %d is at index %d\n", mSearchItem, mIndex);
    else
        printf("Item %d not found in the array\n",mSearchItem);

    mSearchItem = 89;
    mIndex = findIndexOfItem( mSearchItem, mArray, mLengthOfArray );
    if( mIndex!=-1 )
        printf("Item %d is at index %d\n", mSearchItem, mIndex);
    else
        printf("Item %d not found in the array\n",mSearchItem);

    mSearchItem = 91;
    mIndex = findIndexOfItem( mSearchItem, mArray, mLengthOfArray );
    if( mIndex!=-1 )
        printf("Item %d is at index %d\n", mSearchItem, mIndex);
    else
        printf("Item %d not found in the array\n",mSearchItem);

    return 0;
}

We can analyze the steps for the first search item 12.



Search for 12 :

  • Find midPoint. For this case midPoint is at index 5. If the searchItem (12) is less than the item at index midPoint (45) then update higherBound value with midpoint-1.
  • Search in the new range with new higherBound value. higherBound is now midPoint-1. And lowerBound is 0.
New Sub Array Shrinks To 5 Items:

  • Find midPoint. For this case midPoint is at index 2. If the searchItem is higher than the item at index midPoint then update lowerBound value with midpoint+1.
  • Search in the new range with new lowerBound value. lowerBound is now midpoint+1 and higherBound does not change for this case.
New Sub Array Shrinks To 2 Items :
  • Find midPoint. For this case midPoint is at index 3.
  • SearchedItem is not less than the item at midPoint.
  • SearchedItem is not higher than the item at midPoint.
  • Then item is at midPoint. Return index of midPoint.

When you run the above recursive binary search sample following console output is generated :


Tuesday, February 25, 2014

Binary Search Sorted Int Array Iteratively

Binary Search is one of the most widely known search algorithms. One of the main restrictions to use binary search for existing sets is that your list or container must be sorted before searching inside it.
Instead of searching a list or container by using linear-search algorithm, item-by-item, binary search is considered more efficient in terms of time and space.

Following sample project created by qt creator and contains following files:
1- SearchIntArray.pro
2- main.cpp

SearchIntArray.pro file contains project configuration.
CONFIG += console
TEMPLATE = app
SOURCES += main.cpp
main.cpp file contains main method and indexOfItem function implementations.
#include <stdio.h>

int indexOfItem(int pSearchedtem,int* pArray,int pTotalItemCount)
{
    int mLowerBound = 0;
    int mHigherBound = pTotalItemCount-1;

    while( mLowerBound<= mHigherBound )
    {
        int midIndex = mLowerBound+(mHigherBound-mLowerBound)/2;
        if( pSearchedtem < pArray[midIndex] )
            mHigherBound = midIndex-1;
        else if(pSearchedtem>pArray[midIndex])
            mLowerBound = midIndex+1;
        else
            return midIndex;
    }

    return -1;
}

int main(int argc, char* argv[])
{
    int mArray[] = {1, 2, 4, 12, 34, 45, 56, 67, 78, 89, 90};
    int mLengthOfArray = sizeof(mArray)/sizeof(int);
    printf("There are %d items in the array\n", mLengthOfArray);
    printf("Items :\n");
    for(int i = 0; i<mLengthOfArray; i++)
    {
        if( i!=mLengthOfArray-1 )
            printf("%d,", mArray[i]);
        else
            printf("%d\n", mArray[i]);
    }
    printf("Indexes :\n");
    for(int i = 0; i<mLengthOfArray; i++)
    {
        if( i!=mLengthOfArray-1 )
            printf("%d,", i);
        else
            printf("%d\n\n", i);
    }
    int mSearchItem = 12;
    int mIndex = indexOfItem(mSearchItem,mArray,mLengthOfArray);
    if( mIndex!=-1 )
        printf("Item %d is at index %d\n", mSearchItem, mIndex);
    else
        printf("Item %d not found in the array\n",mSearchItem);

    mSearchItem = 89;
    mIndex = indexOfItem(mSearchItem,mArray,mLengthOfArray);
    if( mIndex!=-1 )
        printf("Item %d is at index %d\n", mSearchItem, mIndex);
    else
        printf("Item %d not found in the array\n",mSearchItem);

    mSearchItem = 91;
    mIndex = indexOfItem(mSearchItem,mArray,mLengthOfArray);
    if( mIndex!=-1 )
        printf("Item %d is at index %d\n", mSearchItem, mIndex);
    else
        printf("Item %d not found in the array\n",mSearchItem);

    return 0;
}

indexOfItem function implements binary search algorithm in C programming language iteratively. indexOfItem function takes the item to search for inside the array as one of its incoming parameters and function returns the index of the found item or -1 if not was found.

Binary Search algorithm, as described at http://algs4.cs.princeton.edu/home/ ,
         
             - lowerBound = 0
             - higherBound = itemCount-1
             - loop until lowerBound is less than or equal to the upper bound
                       - divides the sorted container into 2 parts at the center, find middle index
                       - compares the searchKey with the the item which is at the middle index
                               - if the searchKey is greater than the item which is at the middle index
                                                     - then update the lower bound for search with (middle index+1)
                               - else if the searchKey is lower than the item which is at the middle index
                                                     - then update the upper bound for search with (middle index-1)
                               - else
                                       - then the searchKey is the item which is at the middle index
            - end loop
            return indexNotFound

main function contains 3 test-cases for binary search algorithm. First 2 searchKeys (12 and 89) are found in the test array whereas the last searchKey (91) is not found in the list.

Console output contains all the printf function results as follows :


Wednesday, February 12, 2014

Virtual Functions and Inheritance

Inheritance helps to reduce the amount of code written or repeated by using a base-derived relation in object-oriented-world. Common functions are collected in a base class and the derived class extends or directly uses the existing base class functions. In some situations base class also can be pointing to different derived classes depending on the run-time behavior.

When base class is used to point to derived class, base class pointer calls overridden base-class methods, if there are any base class virtual method re-implementations in the derived class. Virtual functions in C++ help to transfer a specific behavior in the base class to derived class by declaring the function virtual in the base class. Derived is free to re-implement base class virtual functions.

If the derived class does not provide any implementation for the base class virtual functions then the base class virtual functions are called. This is not always the expected behavior because base class virtual functions are declared to be overridden in the derived class.

Following sample project created by qt creator and contains following files:
1- VirtualFunctions.pro
2- main.cpp
3- abstractservice.h
4- abstractservice.cpp
5- activityservice.h
6- activityservice.cpp
7- userservice.h
8- userservice.cpp



VirtualFunctions.pro file contains project configuration.

TARGET = VirtualFunctions
CONFIG   += console
TEMPLATE = app
SOURCES += main.cpp \
    abstractservice.cpp \
    userservice.cpp \
    activityservice.cpp

HEADERS += \
    abstractservice.h \
    userservice.h \
    activityservice.h

abstractservice.h is the base class that contains virtual functions.

#ifndef ABSTRACTSERVICE_H
#define ABSTRACTSERVICE_H

#include <stdio.h>

class AbstractService
{
public:
    AbstractService();
    virtual ~AbstractService();
    // calls both base and derived dest
    // prevents memory leaks

    virtual void insertRecord();
    virtual void selectRecord();
    virtual void deleteRecord();
    virtual void updateRecord();

};

#endif // ABSTRACTSERVICE_H

In the base class abstractservice.h destructor is also defined virtual otherwise derived class destructor is not called at object deletion.

abstractservice.cpp is the base class implementation file that contains implementations for virtual functions, constructor and destructor.

#include "abstractservice.h"

AbstractService::AbstractService()
{
    printf("AbstractService::AbstractService called\n");
}

AbstractService::~AbstractService()
{
    printf("AbstractService::~AbstractService called\n");
}

void AbstractService::insertRecord()
{
    printf("AbstractService::insertRecord called\n");
}

void AbstractService::selectRecord()
{
    printf("AbstractService::selectRecord called\n");
}

void AbstractService::deleteRecord()
{
    printf("AbstractService::deleteRecord called\n");
}

void AbstractService::updateRecord()
{
    printf("AbstractService::updateRecord called\n");
}

userservice.h is the first derived class that contains its own implementations for the virtual functions that are declared in the base class abstractservice.
#ifndef USERSERVICE_H
#define USERSERVICE_H

#include "abstractservice.h"

class UserService : public AbstractService
{
public:
    UserService();
    ~UserService();

    void insertRecord();
    void selectRecord();
    void deleteRecord();
    void updateRecord();
};

#endif // USERSERVICE_H

userservice.cpp contains implementation details for the base class virtual functions.
#include "userservice.h"

UserService::UserService()
{
    printf("UserService::UserService called\n");
}

UserService::~UserService()
{
    printf("UserService::~UserService called\n");
}

void UserService::insertRecord()
{
    printf("UserService::insertRecord called\n");
}

void UserService::selectRecord()
{
    printf("UserService::selectRecord called\n");
}

void UserService::deleteRecord()
{
    printf("UserService::deleteRecord called\n");
}

void UserService::updateRecord()
{
    printf("UserService::updateRecord called\n");
}

activityservice.h is the second derived class that re-declares base class virtual functions in its header.
#ifndef ACTIVITYSERVICE_H
#define ACTIVITYSERVICE_H

#include "abstractservice.h"

class ActivityService : public AbstractService
{
public:
    ActivityService();
    ~ActivityService();

    void insertRecord();
    void selectRecord();
    void deleteRecord();
    void updateRecord();
};

#endif // ACTIVITYSERVICE_H

activityservice.cpp file contains implementation details for the base class virtual functions.
#include "activityservice.h"

ActivityService::ActivityService()
{
    printf("ActivityService::ActivityService called\n");
}

ActivityService::~ActivityService()
{
    printf("ActivityService::~ActivityService called\n");
}

void ActivityService::insertRecord()
{
    printf("ActivityService::insertRecord called\n");
}

void ActivityService::selectRecord()
{
    printf("ActivityService::selectRecord called\n");
}

void ActivityService::deleteRecord()
{
    printf("ActivityService::deleteRecord called\n");
}

void ActivityService::updateRecord()
{
    printf("ActivityService::updateRecord called\n");
}

Both of the derived classes provide their own implementations for the virtual functions declared in the base class abstractservice.

main.cpp file contains a main function that is creating different base class pointers which are pointing to derived class objects.
#include "userservice.h"
#include "activityservice.h"

int main(int argc, char *argv[])
{
   UserService *userServicePtr = new UserService;
   userServicePtr->insertRecord();
   userServicePtr->selectRecord();
   userServicePtr->updateRecord();
   userServicePtr->deleteRecord();
   delete userServicePtr;
   printf("\n");

   AbstractService *abstractServiceObjPtr = new AbstractService;
   abstractServiceObjPtr->insertRecord();
   abstractServiceObjPtr->selectRecord();
   abstractServiceObjPtr->updateRecord();
   abstractServiceObjPtr->deleteRecord();
   delete abstractServiceObjPtr;
   printf("\n");

   // base class pointer to derived class object
   char option = 'a';
   AbstractService *serviceObjPtr;
   if( option == 'u' )
   {
       serviceObjPtr = new UserService;
       serviceObjPtr->insertRecord();
       serviceObjPtr->selectRecord();
       serviceObjPtr->updateRecord();
       serviceObjPtr->deleteRecord();
       delete serviceObjPtr;
       printf("\n");
   }
   else if( option == 'a' )
   {
       serviceObjPtr = new ActivityService;
       serviceObjPtr->insertRecord();
       serviceObjPtr->selectRecord();
       serviceObjPtr->updateRecord();
       serviceObjPtr->deleteRecord();
       delete serviceObjPtr;
       printf("\n");
   }

   return 0;
}

At runtime base class pointer serviceObjPtr points to either UserService instance or ActivityService instance.

Console output also shows the order for object creation and destruction.


Monday, February 10, 2014

Swap Values With Function Template

Swap values function is commonly used in applications that make operations on arithmetic values such as int,double and float. Instead of implementing overloaded functions for different data types to handle swap operation, function templates can be preferred.

Following sample project created by qt creator and contains following files:
1- UsingTemplatesInCPP.pro
2- main.cpp


UsingTemplatesInCPP.pro file contains project configuration.

TEMPLATE = app
TARGET    = UsingTemplatesInCPP
CONFIG   += console
TEMPLATE  = app
SOURCES  += main.cpp

main.cpp file contains main method and swapValues template function implementations.

#include <stdio.h>

template<typename T>
void swapValues(T &param1, T &param2)
{
    T temp = param1;
    param1 = param2;
    param2 = temp;
}

int main(int argc, char *argv[])
{

 int iP1 = 1, iP2 = 2;
 printf("Initial Integer Values : p1 = %d  p2 = %d \n", iP1, iP2);
 swapValues(iP1,iP2);
 printf("Swapped Integer Values : p1 = %d  p2 = %d \n\n", iP1, iP2);

 double dP1 = 1.34, dP2 = 2.45;
 printf("Initial Double Values : p1 = %f  p2 = %f \n", dP1, dP2);
 swapValues(dP1,dP2);
 printf("Swapped Double Values : p1 = %f  p2 = %f \n\n", dP1, dP2);

 float fP1 = 1.67, fP2 = 2.89;
 printf("Initial Float Values : p1 = %f  p2 = %f \n", fP1, fP2);
 swapValues(fP1,fP2);
 printf("Swapped Float Values : p1 = %f  p2 = %f \n", fP1, fP2);

 return 0;
}

When swapValues template function is called with integer parameters the compiler binds integer values for the generic type parameter T and instantiates an instance of the function template with integer parameters.
The same process is followed when double and float instances are instantiated.
Console output contains all the printf function results as follows :