Simple Example of Multithreading in C Linux

This simple example demonstrates the use of multithreading in the linux environment. This little piece of C code has two threads, a producer thread and a consumer thread. The producer thread generates 600 random numbers, which are passed one at a time to a consumer thread via shared memory. Both threads sum all of the random numbers. The fact that both the producer and consumer have the same sum is proof that the thread are communicating together correctly.


/*
 * File:   CS314_P01_BKT.c
 * Author: BK Turley
 *
 */

#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/shm.h>
#include <sys/sem.h>

#define FIFO_Size 10 //not used anywhere
#define NUM_REPEAT 600  // 6000000 takes wayyyyy too long.

#define SHMKEY     ((key_t) 8080)   /* The shared memory ID                 */
#define SEMKEY_1   ((key_t) 8081L)  /* The semaphore ID for MUTEX           */
#define PERMS      0666             /* Access permission codes             */

/* Prototypes ------------------------------------------------------------- */
void insert_delay();
void insert_delay_long();
int sem_create(key_t sem_key, int init_val); /* Creating a semaphore    */
void sem_rm(int id);                         /* Remove a semaphore      */
int randomint(void);                        // return a random number from 1-200
//note that 0 values indicate empty locations.

/* Global Variables ------------------------------------------------------- */
static struct sembuf op_down[1] = {
    0, -1, 0
};
static struct sembuf op_up[1] = {
    0, 1, 0
};
union {
    int val;
    struct semid_ds *buf;
    ushort *array;
} semctl_arg;

/* The Main --------------------------------------------------------------- */
int main(void) {
    int pid; /* Process ID                          */
    int cpid; /* Child process ID                    */
    long int i; /* Loop counter                        */
    int status; /* The exit code from a child process  */

    int shmid; /* Shared memory ID                    */
    int mutex; /* Semaphore ID for "MUTEX" semaphore  */
    int shared_int[1];
    shared_int[1] = 0;
    int * shm_pointer = &shared_int[0]; /* Pointer to the shared memory        */

    /* Create a shared memory ---------------------------------------------- */
    shmid = shmget(SHMKEY, sizeof (shared_int), PERMS | IPC_CREAT);

    /* Attach the shared memory -------------------------------------------- */
    shm_pointer = (int *) shmat(shmid, (int *) 0, 0);

    /* Create a semaphore -------------------------------------------------- */
    mutex = sem_create(SEMKEY_1, 1);

    /* Create the writer process ------------------------------------------- */
    pid = fork();

    /* If pid is not zero, this must be the parent process --- */
    if (pid != 0) {
        /* The parent process creates the reader process --- */
        pid = fork();

        /* If pid is not zero, this must be the parent process --- */
        if (pid != 0) {
            //printf("\nThe parent process is now waiting for the two processes to be completed ... \n");

            cpid = wait(&status);
            //printf("\nA child process %d with process ID = %d has terminated ... \n", (status / 256), cpid);

            cpid = wait(&status);
            //printf("A child process %d with process ID = %d has terminated ... \n", (status / 256), cpid);

            //printf("\nBoth processes have completed and the parent process is terminating ...\n");

            /* Detaching the shared memory --------------------------------- */
            shmdt(shm_pointer);

            /* Deleting the shared memory ---------------------------------- */
            shmctl(shmid, IPC_RMID, (struct shmid_ds *) 0);

            /* Deleting the MUTEX semaphore -------------------------------- */
            sem_rm(mutex);

            //printf("\nThe parent process is now terminating ... \n\n");
            exit(0);
            // END OF PARENT PROCESS

        }/* If pid is zero, this is the writer process --- */
        else {

            long int prodsum = 0;
            int rand = 0;
            i = 0;

            /* Producer algorithm --- */
            while (i < NUM_REPEAT) {

                /* ENTER THE CRITICAL SECTION --- */
                status = semop(mutex, &op_down[0], 1); /* DOWN Operation --- */
                if (status < 0) {
                    printf("DOWN Operation ERROR (WRITER) .... \n");
                }

                /* CRITICAL SECTION --- */

                if(shm_pointer[1] == 0){
                   shm_pointer[0] = randomint();
                    prodsum = prodsum + shm_pointer[0];
                    shm_pointer[1] = 1;
                    i++;
                }

                /* LEAVE THE CRITICAL SECTION --- */
                status = semop(mutex, &op_up[0], 1); /* UP Operation --- */
                if (status < 0) {
                    printf("UP Operation ERROR (WRITER) .... \n");
                }
            }

            printf("PRODUCER SUM: %d.\n", prodsum);

            /* Terminate the producer process and send a signal to the parent process --- */
            exit(1);
        }
    }/* If pid is zero, this is the consumer process --- */
    else {
        int temp;
        long int conssum = 0;
        i = 0;

        /* consumer algorithm --- */
        while (i < NUM_REPEAT) {

            /* ENTER THE CRITICAL SECTION --- */
            status = semop(mutex, &op_down[0], 1); /* DOWN Operation --- */
            if (status < 0) {
                printf("DOWN Operation ERROR (READER) ... \n");
            }

            /* CRITICAL SECTION --- */

                if(shm_pointer[1] == 1){
                    conssum = conssum + shm_pointer[0];
                    shm_pointer[1] = 0;
                    i++;
                }

            /* LEAVING THE CRITICAL SECTION --- */
            status = semop(mutex, &op_up[0], 1); /* UP Operation --- */
            if (status < 0) {
                printf("UP Operation ERROR (READER) ... \n");
            }
        }
        printf("CONSUMER SUM: %d.\n", conssum);
        exit(2);
    }
}

/* create a semaphore ------------------------------------------------------- */
int sem_create(key_t key, int init_val) {
    register int id, semval;
    int status;

    if (key == IPC_PRIVATE) {
        printf("key == IP_PRIVATE ERROR ... \n");
        return (-1);
    } else if (key == (key_t) - 1) {
        printf("key == -1 ERROR ... \n");
        return (-1);
    }

    id = semget(key, 1, IPC_CREAT | PERMS);
    if (id < 0) {
        printf("sem_get ERROR ... \n");
        return (-1);
    }

    semctl_arg.val = 0;
    semval = semctl(id, 0, GETVAL, semctl_arg);
    if (semval < 0) {
        printf("semctl ERROR ... \n");
    }

    if (semval == 0) {
        semctl_arg.val = init_val;
        status = semctl(id, 0, SETVAL, semctl_arg);
        if (status < 0) {
            printf("Can't SETVAL ... ERROR ... \n");
        }
    }

    return (id);
}

/* insert_delay ------------------------------------------------------------- */
void insert_delay() {
    long int i, j, k;

    for (i = 0; i < 1000000; i++) {
        for (j = 0; j < 5; j++) {
            k = k + 1;
        }
    }
}

/* insert_delay_long -------------------------------------------------------- */
void insert_delay_long() {
    long int i, j, k;

    for (i = 0; i < 1000000; i++) {
        for (j = 0; j < 50; j++) {
            k = k + 1;
        }
    }
}

/* sem_rm ------------------------------------------------------------------- */
void sem_rm(int id) {
    int status;

    semctl_arg.val = 0;
    status = semctl(id, 0, IPC_RMID, semctl_arg);
    if (status < 0) {
        printf("ERROR in sen_rm ... \n");
    }
}

int randomint(void) {
    int lowerlimit = 1;
    int upperlimit = 200;
    srand(time(NULL));
    int random_number = lowerlimit + (rand() % (upperlimit - lowerlimit));
    if (random_number == 0)//make absolutely sure 0 is NEVER returned
        return 1;
    return lowerlimit + (rand() % (upperlimit - lowerlimit));
}

Binary Search Tree implemented. C++

This is my personal implementation of a binary search tree. My tree uses iteration instead of recursion for its insertion, deletion and searches for faster execution because function stack overhead is avoided. Recursion is still used for tree deletion because I didn’t want to implement a stack for the traversal of the tree which is required for deletion.

// SearchableADT test driver
// Copyright (C) 2011 Kyle Turley
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.

// Purpose:
// this test driver is used to emperically test the performance of various
// searchable abstract data structures that adhere to the SearchableADT
// interface.

#include <iostream>
#include <sstream>
#include <fstream>
#include <string>
#include <vector>
#include <algorithm>
#include <ctime>
#include <cstdlib>
#include "BST.h"

using namespace std;

void menu_Loop(), menu_Choices(char ans);
void load_dict(), clr_dict(), find_a_word(), find_from_file(), tree_stats(), end_program();
bool isfound(string findme);

//declare a new SearchableADT to test
SearchableADT<string> *dictionary = new BST<string>;

int main() {

    menu_Loop();

    return 0;
}//end main

void menu_Loop() {
    char ans; //declare ans variable, this will be used OVER AND OVER
    do {
        cout << "--- ADT Tinkering Menu ---" << endl;
        cout << "1: Load a Dictionary File" << endl;
        cout << "2: Clear Dictionary" << endl;
        cout << "3: Check for an Entry" << endl;
        cout << "4: Check for Entries from File" << endl;
        cout << "5: Report Tree Statistics" << endl;
        cout << "6: Option 6 - Exit" << endl; //print us some options

        cin >> ans; //take in an answer
        cin.ignore(80, '\n'); 

        menu_Choices(ans);
    } while (ans != '6'); //keep on running on till they pick exit!
}// end menu_Loop()

void menu_Choices(char ans) {
    switch (ans)//roll thru options
    {
        case '1':
            load_dict();
            break;
        case '2':
            clr_dict();
            break;
        case '3':
            find_a_word();
            break;
        case '4':
            find_from_file();
            break;
        case '5':
            tree_stats();
            break;
        case '6':
            end_program();
            break;
        default://THEY DIDNT READ THE MENU, WHO WOULD HAVE THOUGHT?!?!
            cout << "Please read and follow all directions\n";
            break;
    }
}// end menu_Choices(char ans)

//functions, FILL WITH VALUABLE PROGRAMMING SKILLS

// Asks the user for a filename, then loads each whitespace delineated string into the SearchableADT
void load_dict() {

    string filename = "";
    fstream in;
    clock_t start, finish;
    while (!in.is_open()) {
        cout << "Enter a valid C++ file to Load" << endl;
        cin >> filename;
        in.open(filename.c_str());
    }
    start = clock();
    dictionary->loadFromFile(filename);
    finish = clock();
    in.close();
    cout << "## file added to ADT ##" << endl;
    cout << "Load time: " << ((double) (finish - start) / CLOCKS_PER_SEC) << "sec" << endl;
}

// releases all memory occupied by the SearchableADT
void clr_dict() {
    clock_t start, finish;
    start = clock();
    dictionary->clear();
    finish = clock();
    cout << "## ADT CLEARED ##" << endl;
    cout << "time: " << ((double) (finish - start) / CLOCKS_PER_SEC) << "sec" << endl;
}

// Asks the user for a word
void find_a_word() {
    string findme;
    cout << "Enter a string to search for" << endl;
    cin >> findme;

    clock_t start, finish;
    start = clock();
    // insert timing code here
    if(isfound(findme)){
        cout << "found it" << endl;
    }else
        cout << "not found" << endl;
    finish = clock();
    cout << "time: " << ((double) (finish - start) / CLOCKS_PER_SEC) << "sec" << endl;
}

void find_from_file() {

    string filename = "";
    fstream in;
    clock_t start, finish;
    stringstream buffer;
    string temp;
    int misspelled_count = 0;

    while (!in.is_open()) {
        cout << "Enter a valid Text file to Read" << endl;
        cin >> filename;
        in.open(filename.c_str());
    }

    buffer << in.rdbuf();
    in.close();
    start = clock();
    // attempt to find each word
    while (buffer.good()) {
        buffer >> temp;
        if(!isfound(temp)){
            cout << temp << " isn't in the dictionary" << endl;
            misspelled_count++;
        }
    }
    finish = clock();
    cout << misspelled_count << " misspelled words were found" << endl;
    cout << "Search time: " << ((double) (finish - start) / CLOCKS_PER_SEC) << "sec" << endl;
}

void tree_stats() {
    clock_t start, finish;
    start = clock();
    cout << "Number of Entries: " << dictionary->numEntries() << endl;
    finish = clock();
    cout << "Report time: " << ((double) (finish - start) / CLOCKS_PER_SEC) << "sec" << endl;
}

bool isfound(string findme){
    bool isfound = false;
    string alphabet = "abcdefghijklmnopqrstuvwxyz";

    // make findme lowercase
    for (int i = 0; i < strlen(findme.c_str()); i++) {
        if (findme[i] >= 0x41 && findme[i] <= 0x5A)
            findme[i] = findme[i] + 0x20;
    }

    //if findme contains a ? character, generate a list of 26 possibilities to search for
    if (findme.find_first_of('?') != string::npos) {
        string possibilities[25];
        int qmarkindex = findme.find_first_of('?');

        for (int i = 0; i < 25; i++) {
            possibilities[i] = findme.replace(qmarkindex, 1, 1, alphabet[i]);
            if (dictionary->isThere(possibilities[i])){
                cout << possibilities[i] << endl;
                isfound = true;
            }
        }
    } else // no '?' character was found,
        isfound = dictionary->isThere(findme);
    return isfound;
}

void end_program(){
	dictionary->clear(); // release memory stored by the dictionary
	exit(0);
}
// Abstract Searchable ADT interface
// Copyright (C) 2011 Kyle Turley
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.

#ifndef SEARCHABLEADT_H
#define SEARCHABLEADT_H

#include <string>

using namespace std;

template <typename T>
class SearchableADT{
public:
	// these are all purely virtual functions that must be implemented by all classes that inherit from SearchableADT().
	virtual int loadFromFile(string filename) = 0;
	virtual void clear(void) = 0;
	virtual void insertEntry(T value) = 0;
	virtual void deleteEntry(T value) = 0;
	virtual bool isThere(T value) = 0 ;
	virtual int numEntries(void) = 0;

private :
	//no private methods or data members.

};

#endif
// BST class
// Copyright (C) 2011 Kyle Turley
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.

#ifndef BST_H
#define BST_H
#pragma once

#include "SearchableADT.h"
#include <cstring>

using namespace std;

template <typename T>
class binarynode {
public:
    T data;
    binarynode<T> *left;
    binarynode<T> *right;
};

template <typename T>
class BST : public SearchableADT<T> {
public:
    BST(void);
    ~BST(void);
    int loadFromFile(string filename);
    void clear(void);
    void insertEntry(T value);
    void deleteEntry(T value);
    bool isThere(T value);
    int numEntries(void);

    // additional methods, not part of abstract interface
    void postorder_delete(binarynode<T>* itr);
    int BST<T>::height(binarynode<T>* itr);

private:
    binarynode<T> * root_ptr;
    double numnodes;

};

template <typename T>
BST<T>::BST(void) {
    root_ptr = NULL;
    numnodes = 0;
}

template <typename T>
BST<T>::~BST(void) {
    this->clear();
}

template <typename T>
int BST<T>::loadFromFile(string filename) {

    fstream in;
    vector<T> vect;
    vector<T>::const_iterator iter;
    std::stringstream buffer;
    string temp;

    in.open(filename.c_str());
    buffer << in.rdbuf();

    // read each word into a vector
    while (buffer.good()) {
        buffer >> temp;
        vect.push_back(temp);
    }
    // randomize the vector for more efficient inserts
    // just in case the user tries to input a sorted file.
    // "A good programmer looks both ways before crossing a one way street"
    srand(time(0));
    random_shuffle(vect.begin(), vect.end());

    //now insert each randomized entry into the BST
    for (iter = vect.begin(); iter != vect.end(); ++iter) {
        //cout << *iter << endl;
        this->insertEntry(*iter);
    }

    return 0;
}

template <typename T>
void BST<T>::clear(void) {
    this->postorder_delete(root_ptr);
    root_ptr = NULL;
    //numnodes = 0;
    return;
}

template <typename T>
void BST<T>::insertEntry(T value) {

    // create the new node to be inserted and populate it with data
    binarynode<T> *temp, *prev, *curr;
    temp = new binarynode<T>;
    temp->data = value;
    temp->left = NULL;
    temp->right = NULL;

    // insert the node into its proper place in the tree
    if (root_ptr == NULL) {
        // the tree is empty so make the new node the root
        root_ptr = temp;
    } else {
        // discover the new nodes proper place in a binary search fashion
        curr = root_ptr;
        while (curr != NULL) {
            prev = curr;
            if (temp->data < curr->data)
                curr = curr->left;
            else
                curr = curr->right;
        }
        // the proper place has been found at this point.  insert the new node
        if (temp->data < prev->data)
            prev->left = temp;
        else
            prev->right = temp;
    }
    numnodes++;
    return;
}

template <typename T>
void BST<T>::deleteEntry(T value) {

    binarynode<T> *prev, *curr, *grandparent;
    prev = curr = grandparent = NULL;

    binarynode<T> *deleteme = new binarynode<T>;
    deleteme->data = value;

    // discover where the node should be in a binary search fashion
    curr = root_ptr;
    while (curr != NULL) {
        grandparent = prev;
        prev = curr;
        if (deleteme->data < curr->data)
            curr = curr->left;
        else if (deleteme->data > curr->data)
            curr = curr->right;
        else
            break;
    }
    if (deleteme->data == prev->data) {// found it, now delete it. There are special cases for different children
        if (prev->left == NULL && prev->right == NULL) { //no children
            if (grandparent->left->data == prev->data)
                grandparent->left = NULL;
            else
                grandparent->right = NULL;
            delete prev;
        } else if (prev->left == NULL && prev->right != NULL) { //right child exists
            if (grandparent->left->data == prev->data)
                grandparent->left = prev->right;
            else
                grandparent->right = prev->right;
            delete prev;
        } else if (prev->left != NULL && prev->right == NULL) { //left child exists
            if (grandparent->right->data == prev->data)
                grandparent->right = prev->left;
            else
                grandparent->left = prev->left;
            delete prev;
        }
    }
    numnodes--;
}

template <typename T>
bool BST<T>::isThere(T value) {
    binarynode<T> *prev, *curr;

    curr = root_ptr;

    // find the right spot in an iterative fashion
    // recursion should be avoided whenever possible for safety and performance
    while (curr != NULL) {
        prev = curr;
        if (value < curr->data)
            curr = curr->left;
        else if (value > curr->data)
            curr = curr->right;
        else if (prev->data == value)
            return true; // value was found
    }
    return false; //value wasn't found
}

template <typename T>
int BST<T>::numEntries(void) {
    // do a post-order traversal counting along the way
    // this is kinda hacked, but I want to preserve the given SearchableADT interface

    cout << "Tree Height: " << height(root_ptr) << endl;

    return numnodes;
}

template <typename T>
void BST<T>::postorder_delete(binarynode<T>* itr) {
    if (itr != NULL) {
        postorder_delete(itr->left);
        postorder_delete(itr->right);
        delete itr;
        numnodes--;
    }
    return;
}

template <typename T>
int BST<T>::height(binarynode<T>* itr) {
    if (itr == NULL)
        return -1;
    else
        return 1 + max(height(itr->left), height(itr->right));
}

#endif

A realistic C++ line counter

This program asks the user for a c++ source file. It displays the file’s linecount to the screen. Program exits on invalid input. This sourcefile is 90 lines of code(according to itself).
Each of the following counts as one line of code:

  1. Preprocessor directives
  2. if()
  3. while()
  4. do..while()
  5. switch()
  6. non-repeating semicolons

#include <iostream>
#include <fstream>
#include <string>

using namespace std;

// accepts a valid C++ filename, returns a C++ linecount. Prints a error and exits program on invalid input.
int loc(string filename);

int main()
{
	string filename;
	cout << "Enter a cpp filename to linecount " << endl;
	cin >> filename;
	cout << filename << " has " << loc(filename) << " lines of code." << endl;
	system("pause");
	return 0;
}

int loc(string filename){
/* open file. exit on failure
 * read the file one character at a time
 * accumulate a linecount by counting if, do, while, switch and semicolons.
 * ignore keywords and semi's that are inside strings and comments
 */
    ifstream OpenFile;
    OpenFile.open(filename.c_str());
    char ch;
    int linecount = 0;

    if (!OpenFile) {
    cout << "loc() was unable to open file. Exiting program." << endl;
	system("pause");
	exit(1);
    }

    while(!OpenFile.eof()){

        OpenFile.get(ch);

        //dont count anything inside line or block comments
        if(ch == '/'){
                OpenFile.get(ch);
                if(ch == '/'){
                        while(ch != '\n')
                                OpenFile.get(ch);
                }else if(ch == '*'){
                        OpenFile.get(ch);
                        while(ch != '*' && ch+1 != '/'){
                                OpenFile.get(ch);
                        }
                }

        // handle the \" escape character here, to prevent errors in string parsing
        }else if(ch == '\\'){
            if(OpenFile.peek()=='\"'){
                OpenFile.get(ch);
                OpenFile.get(ch);
            }

        // dont count anything inside of strings, remember to ignore the /" escape character
        }else if(ch=='\"'){
            OpenFile.get(ch);
            while(ch!='\"'){
                if(ch == '\\'){
                    if(OpenFile.peek()=='\"'){
                        OpenFile.get(ch);
                        OpenFile.get(ch);
                    }
                }OpenFile.get(ch);
            }
        }

        // count if()'s
        else if(ch == 'i'){
                if(OpenFile.peek() == 'f'){
                        OpenFile.get(ch);
                        if(OpenFile.peek() == ' ' || OpenFile.peek() == '('  || OpenFile.peek() == '\n' || OpenFile.peek() == '\r' || OpenFile.peek() == '\t' ){
                                linecount++;
                        }
                }
        }

        // count while()'s
        else if(ch == 'w'){
                if(OpenFile.peek() == 'h'){
                        OpenFile.get(ch);
                        if(OpenFile.peek() == 'i'){
                                OpenFile.get(ch);
                                if(OpenFile.peek() == 'l'){
                                OpenFile.get(ch);
                                        if(OpenFile.peek() == 'e'){
                                        OpenFile.get(ch);
                                                if(OpenFile.peek() == ' ' || OpenFile.peek() == '('  || OpenFile.peek() == '\n' || OpenFile.peek() == '\r' || OpenFile.peek() == '\t' ){
                                                linecount++;
                                                }
                                        }
                                }
                        }
                }

        // count do..while();    this routine eliminates double counting because do{..}while(); loops always end with a semi.
                // the whole block is effectivly ignored, and the ending semi is counted like normal
        }else if(ch == 'd'){
                if(OpenFile.peek() == 'o'){
                        OpenFile.get(ch);
                        bool flag = false;
                        while( !flag ){
                                OpenFile.get(ch);
                                if(ch == 'w'){
                                        if(OpenFile.peek() == 'h'){
                                                OpenFile.get(ch);
                                                if(OpenFile.peek() == 'i'){
                                                        OpenFile.get(ch);
                                                        if(OpenFile.peek() == 'l'){
                                                        OpenFile.get(ch);
                                                                if(OpenFile.peek() == 'e'){
                                                                OpenFile.get(ch);
                                                                        if(OpenFile.peek() == ' ' || OpenFile.peek() == '('  || OpenFile.peek() == '\n' || OpenFile.peek() == '\r' || OpenFile.peek() == '\t' ){
                                                                        flag = true;
                                                                        }
                                                                }
                                                        }
                                                }
                                        }
                                }
                        }
                }
        }

        // count switch()'s
        else if(ch == 's'){
                if(OpenFile.peek() == 'w'){
                        OpenFile.get(ch);
                        if(OpenFile.peek() == 'i'){
                                OpenFile.get(ch);
                                if(OpenFile.peek() == 't'){
                                OpenFile.get(ch);
                                        if(OpenFile.peek() == 'c'){
                                        OpenFile.get(ch);
                                                if(OpenFile.peek() == 'h'){
                                                OpenFile.get(ch);
                                                        if(OpenFile.peek() == ' ' || OpenFile.peek() == '('  || OpenFile.peek() == '\n' || OpenFile.peek() == '\r' || OpenFile.peek() == '\t' ){
                                                        linecount++;
                                                        }
                                                }
                                        }
                                }
                        }
                }
        }

        // counts semi's, remember that ;;;;; only counts as one line, not 5.
        else if(ch == ';'){
                while ( OpenFile.peek() == ';' || OpenFile.peek() == ' '  || OpenFile.peek() == '\n' || OpenFile.peek() == '\r' || OpenFile.peek() == '\t' ){
                        OpenFile.get(ch);
                }
                linecount++;
        }

        //and count meta, # character counting is all thats necessasary because
        else if(ch == '#'){
                linecount++;
        }
    }

    OpenFile.close();
    return linecount;
}

Can’t use a string in a switch statement? Here is a simple alternative

Many programmers are surprised to find that switch statements aren’t compatible with strings in C++.

When attempting to compile, you will see an error:

Visual Studio 2010 —–  error C2450: switch expression of type ‘std::string’ is illegal

Netbeans 6.9.1 —– error: switch quantity not an integer

Here is an example of invalid code

#include <iostream>
#include <string>

using namespace std;

int main(){

	string dayofweek = "wednesday";

	switch(dayofweek){
		case "monday":
			cout << "Watch football" << endl;
			break;
		case "tuesday":
			cout << "steal a car"<< endl;
			break;
		case "wednesday":
			cout << "rob a bank" << endl;
			break;
		case "thursday":
			cout << "count the money" << endl;
			break;
		case "friday":
			cout << "hire a good lawyer" << endl;
			break;
	}
	return 0;
}

The problem is that strings are not a basic type in the C++ language. Whenever a C++ programmer uses basic variables types like int, bool, and char, nothing extra needed. But when a C++ programmer wishes to use strings in a program, they must add #include <string> to the top of the code to enable that functionality. Basic switch statements don’t have the capability to understand “add on” features such as strings and other filestreams.

There is still hope. The people who created the string library were kind enough to include a function to compare strings – strcmp() function. The string compare function can be used along with if..else statements to achieve the desired result.

this is the same logic as before without using a switch statement:

#include <iostream>
#include <string>

using namespace std;

int main(){

	string str = "wednesday";

	if ((!strcmp(str.c_str(), "monday"))){
		cout << "Watch football" << endl;
	}else if (!strcmp(str.c_str(), "tuesday")){
        cout << "steal a car"<< endl;
	}else if (!strcmp(str.c_str(), "wednesday")){
        cout << "rob a bank" << endl;
	}else if (!strcmp(str.c_str(), "thursday")){
		cout << "count the money" << endl;
	}else if (!strcmp(str.c_str(), "friday")){
		cout << "hire a good lawyer" << endl;
	}else{ // same as default
		cout << "Enjoy the Weekend" << endl;
	}

	return 0;
}

A Lexical Analyizer for C++ tokens

Lexical analysis is step 1 of compiling code down to machine language. The process breaks source code down into a long list of pieces called tokens. This list of tokens is used by a parser algorithm that extracts meaning from the order and arrangement of the tokens. Here is a small example of lex analysis:

code:

int main(void) {

float myvar = 2.5;

return 0;

}

list of tokens:

  1. int type
  2. main reserved word
  3. (
  4. void keyword
  5. )
  6. {
  7. float keyword
  8. myvar identifier
  9. = operator
  10. 2.5 floating point constant
  11. ; end statement
  12. return keyword
  13. 0 integer constant
  14. ; end statemant
  15. }

As you can see, the list of tokens gets long rather quickly. Absolutely no syntax checking is done during lex. That happens later down the line.

I have written a basic lexical analyzer to break C++ code into tokens.  Its own source code is C++ as well.

// B.K. Turley
// 1/26/2011

// Compile with g++ only, The nesting is limited to 128 in VS2010.
// This limit is exceeded by the massive if..else..if..else statement
// in identify_token()

// Known bugs:
// block comments are wrongly terminated with / instead of */

// Tokens are also stored in a linked list for later processing

#include <iostream>  //  Include <iostream> whenever using C++ I/O (cin and cout)
#include <iomanip>   //  Include <iomanip> along with iostream and you can't go wrong
#include <fstream>   //  Include <fstream> whenever working with external files.
#include <string>    //  Include <string> whenever using variable of type string.
#include <sstream>
#include <list>

using namespace std;

int find_split_point(string word);
	//accepts a string, returns a integer representing the length of the first token in the string

void identify_token(string str);
	//accepts a string, pritnt the type of token (operator, reverved, meta ect.) followed by str.

list<string> tokens;
int main()
    {

    string filename = "";
	fstream in;
	while(!in.is_open()){
	cout << "Enter a valid C++ file file to tokenize  ";
        cin >> filename;
	in.open(filename.c_str());
	}

	std::stringstream buffer;
	buffer << in.rdbuf();

	string lexme(buffer.str());

    //begin lex
    while(lexme != ""){
		int splitpoint = find_split_point(lexme);// if splitpoint is set to anything but zero here, string begins with operator or META

		if(splitpoint==0)//   string doesn't begin with op or meta. so set splitpoint to the index to the first occurence of space, operator, or META
				splitpoint = lexme.find_first_of(" #\"/=+-*%!^&|<>~,?.:;()[]{}\t");

		if(splitpoint==lexme.length()){ // this only executes whenever the very last piece of the string contains no ops or META
						identify_token(lexme);
						lexme = "";
		}
		else{
				if(splitpoint==0) splitpoint++;
				string token = lexme.substr(0,splitpoint);
				identify_token(token);
				lexme = lexme.substr(splitpoint, lexme.length()-splitpoint);
		}
	}

    return 0;
}

int find_split_point(string word){
// tests if first character is an operator(or META) and returns its length.
/*
    examples:
	isfirstcharoperator("hello there") returns zero.
	isfirstcharoperator("++i;") returns 2.
	isfirstcharoperator("!!crazy!") returns 1. (there is no !! operator)
	isfirstcharoperator("#include <string>") returns 8. (#inclued is a meta word)

*/
	string::iterator itr=word.begin();

        if(itr != word.end() && *itr=='#'){
		int i = 0;
		while(*itr != ' '){
		   i++;
		   itr++;
		   }
		return i;
	}
	else if(itr != word.end() && *itr=='"'){
            int i = 2;
            itr++;
            while(*itr != '"'){
                if(*itr=='\\'){
                    i++;
                    itr++;
                }
                 i++;
                    itr++;
		}
            return i;
	}
	else if(itr != word.end() && *itr=='/'){
		itr++;
		if(itr != word.end() && *itr=='/'){
                    int i = 1;
			while(itr != word.end() && *itr != '\n'){
                            i++;
                            itr++;
                        }
                    return i;
                }else if(itr != word.end() && *itr=='=')
                    return 2;
                else if(itr != word.end() && *itr=='*'){
                    int i = 3;
                    itr++;
                    do {
                        i++;
                        itr++;
                        }while(*itr != '/');//bug
                        return i;
                }
        }
	else if(itr != word.end() && *itr=='+'){
		itr++;
		if(itr != word.end() && *itr=='+')
			return 2;
		else if(itr != word.end() && *itr=='=')
			return 2;
		else
			return 1;
	}
	else if(itr != word.end() && *itr=='-'){
		itr++;
		if(itr != word.end() && *itr=='-')
			return 2;
		else if(itr != word.end() && *itr=='=')
			return 2;
		else if(itr != word.end() && *itr=='>')
			return 2;
		else
			return 1;

	}
        else if(itr != word.end() && *itr=='*'){
		itr++;
		if(itr != word.end() && *itr=='=')
			return 2;
		else if(itr != word.end() && *itr=='/')
			return 2;
		else
			return 1;

	}
	else if(itr != word.end() && *itr=='%'){
		itr++;
		if(itr != word.end() && *itr=='=')
			return 2;
		else
			return 1;
	}
	else if(itr != word.end() && *itr=='!'){
		itr++;
		if(itr != word.end() && *itr=='=')
			return 2;
		else
			return 1 ;
	}
        else if(itr != word.end() && *itr=='^'){
		itr++;
		if(itr != word.end() && *itr=='=')
			return 2;
		else{
			return 1;
		}
	}
	else if(itr != word.end() && *itr=='&'){
		itr++;
		if(itr != word.end() && *itr=='=')
			return 2;
		else if(itr != word.end() && *itr=='&')
			return 2;
		else
			return 1;
	}
	else if(itr != word.end() && *itr=='|'){
		itr++;
		if(itr != word.end() && *itr=='|')
			return 2;
		else if(itr != word.end() && *itr=='=')
			return 2;
		else
			return 1;
	}
	else if(itr != word.end() && *itr=='<'){ // bug,
		itr++;
		if(itr != word.end() && *itr=='<'){
			itr++;
			if(itr != word.end() && *itr=='=')
				return 3;
			else
				return 2;
		}
		else if(itr != word.end() && *itr=='=')
			return 2;
		else
			return 1;
	}
	else if(itr != word.end() && *itr=='>'){ // bug,
		itr++;
		if(itr != word.end() && *itr=='>'){
			itr++;
			if(itr != word.end() && *itr=='=')
				return 3;
			else
				return 2;
		}
		else if(itr != word.end() && *itr=='=')
			return 2;
		else
			return 1;
	}
        else if(itr != word.end() && *itr==':'){
		itr++;
		if(itr != word.end() && *itr==':')
                    return 2;
		return 1;
	}
        else if(itr != word.end() && *itr=='='){
		itr++;
		if(itr != word.end() && *itr=='=')
                    return 2;
		return 1;
	}

	else if(
                *itr=='\'' ||
                *itr==',' ||
                *itr=='~' ||
                *itr=='?' ||
                *itr=='.' ||
                *itr==';' ||
                *itr==':' ||
                *itr=='(' ||
                *itr==')' ||
                *itr=='{' ||
                *itr=='}' ||
                *itr=='[' ||
                *itr==']' ||
                *itr==' ' ||
                *itr=='\r'||
                *itr=='\n'
                )
                return 1;

	// not an operator
	return 0;

}

void identify_token(string str){

   // purge whitespace
    if ((!strcmp(str.c_str(), " ")))
            return;
    else if (!strcmp(str.c_str(), "\t"))
        return;
    else if (!strcmp(str.c_str(), "\r"))
        return;
    else if (!strcmp(str.c_str(), "\n"))
        return;

    //check for operators
    else if (!strcmp(str.c_str(), "?"))
            cout << "questionmark\t" << str << endl;
    else if (!strcmp(str.c_str(), "'"))
            cout << "singlequote\t" << str << endl;
    else if (!strcmp(str.c_str(), ";"))
            cout << "semicolon\t" << str << endl;
    else if (!strcmp(str.c_str(), "::"))
            cout << "scoperes\t" << str << endl;
    else if (!strcmp(str.c_str(), ":"))
            cout << "colon   \t" << str << endl;
    else if (!strcmp(str.c_str(), "{"))
            cout << "leftcurley\t" << str << endl;
    else if (!strcmp(str.c_str(), "}"))
            cout << "rightcurly\t" << str << endl;
    else if (!strcmp(str.c_str(), "["))
            cout << "arraysubL\t" << str << endl;
    else if (!strcmp(str.c_str(), "]"))
            cout << "arraysubR\t" << str << endl;
    else if (!strcmp(str.c_str(), ".*"))
            cout << "pointtomember\t" << str << endl;
    else if (!strcmp(str.c_str(), "."))
            cout << "dotoperator\t" << str << endl;
    else if (!strcmp(str.c_str(), "->*"))
            cout << "pointtomtmber\t" << str << endl;
    else if (!strcmp(str.c_str(), "->"))
            cout << "arrow\t" << str << endl;
    else if (!strcmp(str.c_str(), "("))
            cout << "leftparen\t" << str << endl;
    else if (!strcmp(str.c_str(), ")"))
            cout << "rightparen\t" << str << endl;
    else if (!strcmp(str.c_str(), "++"))
            cout << "increment\t" << str << endl;
    else if (!strcmp(str.c_str(), "--"))
            cout << "decrement\t" << str << endl;
    else if (!strcmp(str.c_str(), "typid"))
            cout << "type info\t" << str << endl;
    else if (!strcmp(str.c_str(), "*_cast"))
            cout << "C++ cast\t" << str << endl;
    else if (!strcmp(str.c_str(), "sizeof"))
            cout << "size info\t" << str << endl;
    else if (!strcmp(str.c_str(), "~"))
            cout << "bitwise NOT\t" << str << endl;
    else if (!strcmp(str.c_str(), "!="))
            cout << "not equal\t" << str << endl;
    else if (!strcmp(str.c_str(), "!"))
            cout << "NOT      \t" << str << endl;
    else if (!strcmp(str.c_str(), "-="))
            cout << "sub&assign\t" << str << endl;
    else if (!strcmp(str.c_str(), "-"))
            cout << "minus\t" << str << endl;
    else if (!strcmp(str.c_str(), "+="))
            cout << "add&assign\t" << str << endl;
    else if (!strcmp(str.c_str(), "+"))
            cout << "add/concat\t" << str << endl;
    else if (!strcmp(str.c_str(), "&&"))
            cout << "logicAND\t" << str << endl;
    else if (!strcmp(str.c_str(), "&="))
            cout << "AND&assign\t" << str << endl;
    else if (!strcmp(str.c_str(), "&"))
            cout << "address of\t" << str << endl;
    else if (!strcmp(str.c_str(), "*="))
            cout << "mult&assign\t" << str << endl;
    else if (!strcmp(str.c_str(), "*/"))
            cout << "closecomment\t" << str << endl;
    else if (!strcmp(str.c_str(), "*"))
            cout << "mult/deref\t" << str << endl;
    else if (!strcmp(str.c_str(), "new"))
            cout << "allocate\t" << str << endl;
    else if (!strcmp(str.c_str(), "delete"))
            cout << "deallocate\t" << str << endl;
    else if (!strcmp(str.c_str(), "/*"))
            cout << "opencomment\t" << str << endl;
    else if (!strcmp(str.c_str(), "//"))       // ?
            cout << "linecomment\t" << str << endl;
    else if (!strcmp(str.c_str(), "/"))
            cout << "divide op\t" << str << endl;
    else if (!strcmp(str.c_str(), "%="))
            cout << "mod&assign\t" << str << endl;
    else if (!strcmp(str.c_str(), "%"))
            cout << "modulo\t" << str << endl;
    else if (!strcmp(str.c_str(), "<<="))
            cout << "shftL&assign\t" << str << endl;
    else if (!strcmp(str.c_str(), "<<"))
            cout << "shiftleft\t" << str << endl;
    else if (!strcmp(str.c_str(), "<="))
            cout << "less or eq\t" << str << endl;
    else if (!strcmp(str.c_str(), "<"))
            cout << "less than\t" << str << endl;
    else if (!strcmp(str.c_str(), ">>="))
            cout << "shftR&assign\t" << str << endl;
    else if (!strcmp(str.c_str(), ">>"))
            cout << "shiftright\t" << str << endl;
    else if (!strcmp(str.c_str(), ">="))
            cout << "greateroreq\t" << str << endl;
    else if (!strcmp(str.c_str(), ">"))
            cout << "greater than\t" << str << endl;
    else if (!strcmp(str.c_str(), "=="))
            cout << "equal to\t" << str << endl;
    else if (!strcmp(str.c_str(), "="))
            cout << "assignment\t" << str << endl;
    else if (!strcmp(str.c_str(), "^="))
            cout << "XOR&assign\t" << str << endl;
    else if (!strcmp(str.c_str(), "^"))
            cout << "bitwiseXOR\t" << str << endl;
    else if (!strcmp(str.c_str(), "||"))
            cout << "logic OR\t" << str << endl;
    else if (!strcmp(str.c_str(), "|="))
            cout << "OR&assign\t" << str << endl;
    else if (!strcmp(str.c_str(), "throw"))
            cout << "throwex\t" << str << endl;
    else if (!strcmp(str.c_str(), ","))
            cout << "sequence\t" << str << endl;

    // check for reserved words
    else if (!strcmp(str.c_str(), "and"))
            cout << "Reserved\t" << str << endl;
    else if (!strcmp(str.c_str(), "and_eq"))
            cout << "Reserved\t" << str << endl;
    else if (!strcmp(str.c_str(), "asm"))
            cout << "Reserved\t" << str << endl;
    else if (!strcmp(str.c_str(), "auto"))
            cout << "Reserved\t" << str << endl;
    else if (!strcmp(str.c_str(), "bitand"))
            cout << "Reserved\t" << str << endl;
    else if (!strcmp(str.c_str(), "bitor"))
            cout << "Reserved\t" << str << endl;
    else if (!strcmp(str.c_str(), "bool"))
            cout << "Type    \t" << str << endl;
    else if (!strcmp(str.c_str(), "break"))
            cout << "Reserved\t" << str << endl;
    else if (!strcmp(str.c_str(), "case"))
            cout << "Reserved\t" << str << endl;
    else if (!strcmp(str.c_str(), "catch"))
            cout << "Reserved\t" << str << endl;
    else if (!strcmp(str.c_str(), "char"))
            cout << "Type    \t" << str << endl;
    else if (!strcmp(str.c_str(), "class"))
            cout << "Classtype\t" << str << endl;
    else if (!strcmp(str.c_str(), "compl"))
            cout << "Reserved\t" << str << endl;
    else if (!strcmp(str.c_str(), "const"))
            cout << "Reserved\t" << str << endl;
    else if (!strcmp(str.c_str(), "const_cast"))
            cout << "Reserved\t" << str << endl;
    else if (!strcmp(str.c_str(), "continue"))
            cout << "Reserved\t" << str << endl;
    else if (!strcmp(str.c_str(), "default"))
            cout << "Reserved\t" << str << endl;
    else if (!strcmp(str.c_str(), "delete"))
            cout << "Reserved\t" << str << endl;
    else if (!strcmp(str.c_str(), "do"))
            cout << "Reserved\t" << str << endl;
    else if (!strcmp(str.c_str(), "double"))
            cout << "Type    \t" << str << endl;
    else if (!strcmp(str.c_str(), "dynamic_cast"))
            cout << "Reserved\t" << str << endl;
    else if (!strcmp(str.c_str(), "else"))
            cout << "Reserved\t" << str << endl;
    else if (!strcmp(str.c_str(), "enum"))
            cout << "Grouptype\t" << str << endl;
    else if (!strcmp(str.c_str(), "explicit"))
            cout << "Reserved\t" << str << endl;
    else if (!strcmp(str.c_str(), "export"))
            cout << "Reserved\t" << str << endl;
    else if (!strcmp(str.c_str(), "extern"))
            cout << "Reserved\t" << str << endl;
    else if (!strcmp(str.c_str(), "false"))
            cout << "Reserved\t" << str << endl;
    else if (!strcmp(str.c_str(), "float"))
            cout << "Type    \t" << str << endl;
    else if (!strcmp(str.c_str(), "for"))
            cout << "Reserved\t" << str << endl;
    else if (!strcmp(str.c_str(), "friend"))
            cout << "Reserved\t" << str << endl;
    else if (!strcmp(str.c_str(), "goto"))
            cout << "Reserved\t" << str << endl;
    else if (!strcmp(str.c_str(), "if"))
            cout << "Reserved\t" << str << endl;
    else if (!strcmp(str.c_str(), "inline"))
            cout << "Reserved\t" << str << endl;
    else if (!strcmp(str.c_str(), "int"))
            cout << "Type    \t" << str << endl;
    else if (!strcmp(str.c_str(), "long"))
            cout << "Type    \t" << str << endl;
    else if (!strcmp(str.c_str(), "mutable"))
            cout << "Reserved\t" << str << endl;
    else if (!strcmp(str.c_str(), "namespace"))
            cout << "Reserved\t" << str << endl;
    else if (!strcmp(str.c_str(), "not"))
            cout << "Reserved\t" << str << endl;
    else if (!strcmp(str.c_str(), "not_eq"))
            cout << "Reserved\t" << str << endl;
    else if (!strcmp(str.c_str(), "operator"))
            cout << "Reserved\t" << str << endl;
    else if (!strcmp(str.c_str(), "or"))
            cout << "Reserved\t" << str << endl;
    else if (!strcmp(str.c_str(), "or_eq"))
            cout << "Reserved\t" << str << endl;
    else if (!strcmp(str.c_str(), "private"))
            cout << "Reserved\t" << str << endl;
    else if (!strcmp(str.c_str(), "protected"))
            cout << "Reserved\t" << str << endl;
    else if (!strcmp(str.c_str(), "public"))
            cout << "Reserved\t" << str << endl;
    else if (!strcmp(str.c_str(), "register"))
            cout << "Reserved\t" << str << endl;
    else if (!strcmp(str.c_str(), "reinterpret_cast"))
            cout << "Reserved\t" << str << endl;
    else if (!strcmp(str.c_str(), "return"))
            cout << "Reserved\t" << str << endl;
    else if (!strcmp(str.c_str(), "short"))
            cout << "Type    \t" << str << endl;
    else if (!strcmp(str.c_str(), "signed"))
            cout << "Reserved\t" << str << endl;
    else if (!strcmp(str.c_str(), "sizeof"))
            cout << "Reserved\t" << str << endl;
    else if (!strcmp(str.c_str(), "static"))
            cout << "Reserved\t" << str << endl;
    else if (!strcmp(str.c_str(), "static_cast"))
            cout << "Reserved\t" << str << endl;
    else if (!strcmp(str.c_str(), "struct"))
            cout << "Classtype\t" << str << endl;
    else if (!strcmp(str.c_str(), "switch"))
            cout << "Reserved\t" << str << endl;
    else if (!strcmp(str.c_str(), "template"))
            cout << "Reserved\t" << str << endl;
    else if (!strcmp(str.c_str(), "this"))
            cout << "Reserved\t" << str << endl;
    else if (!strcmp(str.c_str(), "throw"))
            cout << "Reserved\t" << str << endl;
    else if (!strcmp(str.c_str(), "true"))
            cout << "Reserved\t" << str << endl;
    else if (!strcmp(str.c_str(), "try"))
            cout << "Reserved\t" << str << endl;
    else if (!strcmp(str.c_str(), "typedef"))
            cout << "Reserved\t" << str << endl;
    else if (!strcmp(str.c_str(), "typeid"))
            cout << "Reserved\t" << str << endl;
    else if (!strcmp(str.c_str(), "typename"))
            cout << "Reserved\t" << str << endl;
    else if (!strcmp(str.c_str(), "union"))
            cout << "Classtype\t" << str << endl;
    else if (!strcmp(str.c_str(), "unsigned"))
            cout << "Reserved\t" << str << endl;
    else if (!strcmp(str.c_str(), "using"))
            cout << "Reserved\t" << str << endl;
    else if (!strcmp(str.c_str(), "virtual"))
            cout << "Reserved\t" << str << endl;
    else if (!strcmp(str.c_str(), "void"))//
            cout << "Reserved\t" << str << endl;
    else if (!strcmp(str.c_str(), "volitile"))
            cout << "Reserved\t" << str << endl;
    else if (!strcmp(str.c_str(), "wchar_t"))
            cout << "Type    \t" << str << endl;
    else if (!strcmp(str.c_str(), "while"))
            cout << "Reserved\t" << str << endl;
    else if (!strcmp(str.c_str(), "xor"))
            cout << "Reserved\t" << str << endl;
    else if (!strcmp(str.c_str(), "xor_eq"))
            cout << "Reserved\t" << str << endl;

	// check for predefined words
    else if (!strcmp(str.c_str(), "cin"))
	cout << "Predefined\t" << str << endl;
    else if (!strcmp(str.c_str(), "endl"))
	cout << "Predefined\t" << str << endl;
    else if (!strcmp(str.c_str(), "main"))
	cout << "Predefined\t" << str << endl;
    else if (!strcmp(str.c_str(), "cout"))
	cout << "Predefined\t" << str << endl;
    else if (!strcmp(str.c_str(), "NULL"))
	cout << "Predefined\t" << str << endl;
    else if (!strcmp(str.c_str(), "string"))
	cout << "Predefined\t" << str << endl;

    // check for META
    else if (!strcmp(str.c_str(), "#define"))
        cout << "META     \t" << str << endl;
    else if (!strcmp(str.c_str(), "#undef"))
        cout << "META     \t" << str << endl;
    else if (!strcmp(str.c_str(), "#ifdef"))
        cout << "META     \t" << str << endl;
    else if (!strcmp(str.c_str(), "#ifndef"))
        cout << "META     \t" << str << endl;
    else if (!strcmp(str.c_str(), "#else"))
        cout << "META     \t" << str << endl;
    else if (!strcmp(str.c_str(), "#endif"))
        cout << "META     \t" << str << endl;
    else if (!strcmp(str.c_str(), "#if"))
        cout << "META     \t" << str << endl;
    else if (!strcmp(str.c_str(), "#elif"))
        cout << "META     \t" << str << endl;
    else if (!strcmp(str.c_str(), "#error"))
        cout << "META     \t" << str << endl;
    else if (!strcmp(str.c_str(), "#line"))
        cout << "META     \t" << str << endl;
    else if (!strcmp(str.c_str(), "#pragma"))
        cout << "META     \t" << str << endl;
    else if (!strcmp(str.c_str(), "#include"))
        cout << "META     \t" << str << endl;

    //check for numbers and floating points
    else if(str.find_first_not_of("1234567890") == string::npos)
	cout << "CONST_NUM\t" << str << endl;
    else if(str.find_first_not_of(" 1234567890.", 0) == string::npos)
        cout << "CONST_FLOAT\t" << str << endl;

    // check for string
    else if (str[0] == '"' && str[str.length()-1]=='"')
            cout << "CONST_STR\t" << str << endl;

    // check for line comments
    else if (str[0] == '/' && str[1]=='/')
            cout << "LINECOMMENT\t" << str << endl;

    // check for block comments
    else if (str[0] == '/' && str[1] == '*' && str[str.length()-2]=='*' &&str[str.length()-1]=='/'){
            cout << "BLOCKCOMMENT\t" << str; cout << endl;}

    // all checks complete, assuming whatever passes all checkes is a
    // valid identifier(not in real life, identifiers can't begin with numeric characters)
    // we are assuming that the input is a valid c++ file, so this shouldn't be an issue.
    else cout << "IDENTIFIER\t" << str << endl;

}

Doubly Linked List (C++)

This code is an implementation and test driver of a doubly linked list. This list is pointer based and uses dynamic memory.


Sorted Doubly Linked List with Insertion and Deletion

#include <iostream>
#include <cstdlib>
#include <string>
using namespace std;

class Dllist
{
 private:
 typedef struct Node
 {
 string name;
 Node* next;
 Node* prev;
 };
 Node* head;
 Node* last;
 public:
 Dllist()
 {
 head = NULL;
 last = NULL;
 }
 bool empty() const { return head==NULL; }
 friend ostream& operator<<(ostream& ,const Dllist& );
 void Insert(const string& );
 void Remove(const string& );
};

void Dllist::Insert(const string& s)
{
 // Insertion into an Empty List.
 if(empty())
 {
 Node* temp = new Node;
 head = temp;
 last = temp;
 temp->prev = NULL;
 temp->next = NULL;
 temp->name = s;
 }
 else
 {
 Node* curr;
 curr = head;
 while( s>curr->name && curr->next != last->next) curr = curr->next;

 if(curr == head)
 {
 Node* temp = new Node;
 temp->name = s;
 temp->prev = curr;
 temp->next = NULL;
 head->next = temp;
 last = temp;
 //  cout<<" Inserted "<<s<<" After "<<curr->name<<endl;
 }
 else
 {
 if(curr == last && s>last->name)
 {
 last->next = new Node;
 (last->next)->prev = last;
 last = last->next;
 last->next = NULL;
 last->name = s;
 //  cout<<" Added "<<s<<" at the end "<<endl;
 }
 else
 {
 Node* temp = new Node;
 temp->name = s;
 temp->next = curr;
 (curr->prev)->next = temp;
 temp->prev = curr->prev;
 curr->prev = temp;
 //  cout<<" Inserted "<<s<<" Before "<<curr->name<<endl;
 }
 }
 }
}

ostream& operator<<(ostream& ostr, const Dllist& dl )
{
 if(dl.empty()) ostr<<" The list is empty. "<<endl;
 else
 {
 Dllist::Node* curr;
 for(curr = dl.head; curr != dl.last->next; curr=curr->next)
 ostr<<curr->name<<" ";
 ostr<<endl;
 ostr<<endl;
 return ostr;
 }
}

void Dllist::Remove(const string& s)
{
 bool found = false;
 if(empty())
 {
 cout<<" This is an empty list! "<<endl;
 return;
 }
 else
 {
 Node* curr;
 for(curr = head; curr != last->next; curr = curr->next)
 {
 if(curr->name == s)
 {
 found = true;
 break;
 }
 }
 if(found == false)
 {
 cout<<" The list does not contain specified Node"<<endl;
 return;
 }
 else
 {
 // Curr points to the node to be removed.
 if (curr == head && found)
 {
 if(curr->next != NULL)
 {
 head = curr->next;
 delete curr;
 return;
 }
 else
 {
 delete curr;
 head = NULL;
 last = NULL;
 return;
 }
 }
 if (curr == last && found)
 {
 last = curr->prev;
 delete curr;
 return;
 }
 (curr->prev)->next = curr->next;
 (curr->next)->prev = curr->prev;
 delete curr;
 }
 }
}

int main()
{
 Dllist d1;
 int ch;
 string temp;
 while(1)
 {
 cout<<endl;
 cout<<" Doubly Linked List Operations "<<endl;
 cout<<" ------------------------------"<<endl;
 cout<<" 1. Insertion "<<endl;
 cout<<" 2. Deletion "<<endl;
 cout<<" 3. Display "<<endl;
 cout<<" 4. Exit "<<endl;
 cout<<" Enter your choice : ";
 cin>>ch;
 switch(ch)
 {
 case 1: cout<<" Enter Name to be inserted : ";
 cin>>temp;
 d1.Insert(temp);
 break;
 case 2: cout<<" Enter Name to be deleted : ";
 cin>>temp;
 d1.Remove(temp);
 break;
 case 3: cout<<" The List contains : ";
 cout<<d1;
 break;
 case 4: system("pause");
 return 0;
 break;
 }
 }

Open Text File the Right Way. (C++)

This code is a simple example of how to safely open a text file in C++. Notice the very important check that the file was opened correctly. This covers a range of errors,  most commonly file not found.


// Read integers from file and print sum.

#include <iostream>
#include <iomanip>
#include <fstream>
#include <string>

using namespace std;

int main() {
 int sum = 0;
 string word;
 ifstream inFile;

 inFile.open("test.txt");
 if (!inFile) {
 cout << "Unable to open file";
 exit(1); // terminate with error
 }

 while (inFile >> word) {
 cout << word << " ";
 }

 inFile.close();

 return 0;
}

Press any key to Continue…(C++)

this snippet of code is an alternative to system(“pause”) in MS Visual Studio.

/*
* File:   SystemPause.cpp
* Author: B Turley
*
* This function can be used as a substitute for 'system("pause")'
* in Microsoft Visual Studio
*
* Created on November 10, 2009, 1:17 AM
*/

#include &lt;iostream&gt;
#include &lt;limits&gt;
using namespace std;

void pause()
{
cout&lt;&lt;"Press any key to Continue...";
cin.sync();
cin.ignore(numeric_limits&lt;streamsize&gt; ::max(), '\n');
}

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

pause();

return (0);
}

String to Int function (C++)

This little piece of code can convert a string of decimal characters into an integer value.  If you seek to convert a string into a double, see this post.

/*
 * A function to convert a string into an integer
 */

#include &lt;string&gt;

int StringToInt (std::string str)
{
    int total = 0;
    int length = str.length(); // the length of the string
    int x = 1; // this is our multiplier, used to convert each digit into tens, units, etc
    for (int i = 1; i &lt; str.length(); i++)
        x *= 10; // initialise x correctly

    for (int i = 0; i &lt; length; i++)
    { // loop through the string
        // 48 is the base value (ASCII)
        // multiply it by x to get it into tens, units, etc
        total += (static_cast &lt;int&gt; (str[i]) - 48) * x;
        x /= 10; // divide x by 10, to reduce the units by one
    }

    return total; // return the value as an integer
}

/** EXAMPLE USAGE **/
#include &lt;iostream&gt;
int main ()
{
    int t = StringToInt("1234") + 300;
    std::cout &lt; &lt; t; // should be 1534 (1234 + 300 = 1534)

    std::cin.get ();
    return EXIT_SUCCESS;
}

A Pretend Radio Class (C++)

This C++ class is a good demonstration of Object Orientation in code.
Download the  entire code: RadioClass.zip
// definition file for class Radio
#ifndef RADIO_H
#define RADIO_H
#include <iostream>
using namespace std;

const bool FM = true;
const bool AM = false;
const bool ON = true;
const bool OFF = false;
const int MIN_VOLUME = 0;
const int MAX_VOLUME = 11; // it goes to eleven!

class Radio
{
public:
	// constructors:
	Radio();
	Radio(bool b,bool p,double fm,double am,int v);

	// accessors:
	bool getBand();
	bool getPower();
	double getFMStation();
	double getAMStation();
	int getVolume();

	// mutators:
	bool setBand(bool b);
	bool setPower(bool p);
	bool setFMStation(double s);
	bool setAMStation(double s);
	bool setVolume(int v);

	// utility functions:
	void displayRadio();

private:
	bool band; // FM = true, AM = false
	bool power; // on = true, off = false
	double FMstation , AMstation ; // as per norms
	int volume; // 0..11 is the valid range
};
#endif
// Implementation file for class Radio
#include <iostream>
#include "Radio.h"
using namespace std;

// constructors:
Radio::Radio()
{
	band = FM;
	volume = 4;
	power = OFF;
	FMstation = 88.1;
	AMstation = 530;
}

bool Radio::setFMStation(double s)
{
	if((s < 88.1) || (s > 107.9))  // Station's input out of range
		return false;
	if((int(s * 10) % 2) == 0)     // station's .x is even and therefore invalid
		return false;
	FMstation = s;
	return true;
}
bool Radio::setAMStation(double s)
{
	if((s &lt; 530) || (s &gt; 1600))
		return false;
	if((int(s) % 10) != 0) // AMstation not divisible by 10 and therefore invalid
		return false;
	AMstation = s;
	return true;
}

// utility functions:
void Radio::displayRadio()
{
	cout << "Band = " <<; ((band == FM) ? "FM":"AM") << endl;
	cout &lt;&lt; "Power = " &lt;&lt; ((power == ON) ? "ON":"OFF") &lt;&lt; endl;
	cout &lt;&lt; "FM Station = " &lt;&lt; FMstation &lt;&lt; endl;
	cout &lt;&lt; "AM Station = " &lt;&lt; AMstation &lt;&lt; endl;
	cout &lt;&lt; "Volume = " &lt;&lt; volume &lt;&lt; endl &lt;&lt; endl;
}

// mutators:
bool Radio::setBand(bool b)
{
	band = b;
	return true;
}
bool Radio::setPower(bool p)
{
	power = p;
	return true;
}
bool Radio::setVolume(int v)
{
	if((v < MIN_VOLUME) || (v > MAX_VOLUME))
		return false;
	volume = v;
	return true;
}
//custom constructor , placed later on purpose.
Radio::Radio(bool b,bool p,double fm,double am,int v) // build a radio with custom defaults
{
	band = FM;
	setBand(b);
	power = OFF;
	setPower(p);
	FMstation = 88.1;
	setFMStation(fm);
	AMstation = 530;
	setAMStation(am);
	volume = 4;
	setVolume(v);
}
// accessors:
bool Radio::getBand()
{
	return band;
}
bool Radio::getPower()
{
	return power;
}
double Radio::getFMStation()
{
	return FMstation;
}
double Radio::getAMStation()
{
	return AMstation;
}
int Radio::getVolume()
{
	return volume;
}
// Driver file for class Radio
#include <iostream>
#include "Radio.h"
using namespace std;

//Radio object driver, this file sends the commands that "push the radio buttons" via function calls.

void main()
{
	Radio myJamBox;              // Build a radio to be referred to as 'myJamBox'.

	myJamBox.displayRadio();     // display myJamBox's current attributes.
	myJamBox.setAMStation(550);  // adjust's myJamBox's AM station to 530
	myJamBox.setPower(ON);       // flips myJamBox's power swith ON
	myJamBox.displayRadio();     // display myJamBox's current attributes.

	system("pause");

}