Click here to Skip to main content
12,813,787 members (34,431 online)
Click here to Skip to main content
Add your own
alternative version


33 bookmarked
Posted 18 Jan 2012

C++ Fuzzy Logic API + Simple DSL

, 18 Jan 2012 CPOL
Rate this:
Please Sign up or sign in to vote.
Fuzzy Logic API and Fuzzy Logic DSL implemented with C++.

Fuzzy Logic?

In this article, I will introduce you to my Fuzzy Logic implementation, called FuzzyLogic API. I believe this implementation is simple, effective, and quite fast. Do you know what Fuzzy Logic is? Here I won't talk about Fuzzy Logic theory too much, because there are many existing cool articles about Fuzzy Logic (see links below).

Fuzzy Logic implementation

In this section, I will describe my FuzzyLogic API implementation. I have tried to make a clean and simple implementation that would be easy to understand for everyone. At first I will try to describe some simple classes which we will later use in more complicated and important classes in the FuzzyLogic API.



CLinguisticVariable is the class used for representing the linguistic variables. There are three class variables. variableName is used for defining the linguistic variable name and should be unique, because we're using a hash map for storing CLinguisticVariable, so we can find specific linguistic variables in time O(1). The next variable, b_output declares if a linguistic variable is output or not. Please note, there can be only one output variable in the FuzzyLogic API. The last variable, h_linguisticValuesHashMap is used for storing linguistic values. One linguistic variable can have one or more linguistic values. There are several class methods. AddLinguisticValue adds LinguisticValue to the selected CLinguisticVariable. In the next image, you can see four linguistic variables: Distance, Approaching, Speed, and Signal.


The next method adds the linguistic value to a hash_map.

//Method add Linguistic value to hash map
void AddLinguisticValue(LinguisticValue* p_linguisticValue)
        p_linguisticValue->ToString(), p_linguisticValue));

where LinguisticValue_Pairs is a typedef declared in:

//Typedef for linguistic values hash map.
typedef pair <string, LinguisticValue*> LinguisticValue_Pairs;

The method ResetLinguisticValues just resets all linguistic values to -1. A more interesting method is FindLinguisticValueByName. The input parameter of the method is the linguistic value name and the return value is a pointer to the object of the LinguisticValue. Because we are using a hash map, the time complexity is O(1).

LinguisticValue* FindLinguisticValueByName(string name)
    //Define iterator
    hash_map <string, LinguisticValue*> :: const_iterator iterator;
    //Fint linguistic value by name
    iterator = h_linguisticValuesHashMap.find(name);
    if(iterator == h_linguisticValuesHashMap.end())
        //SASO, this should never happends!!!!!
        return NULL;
    //Return LinguisticValue
    return (LinguisticValue*)iterator->second;

CalculateLinguisticValueByName is just a bridge between CFuzzyReasoner and LinguisticValue for calculating the linguistic value. A little bit more complicated is UpdateLinguisticValueByName. At first we have to find LinguisticValue by name. If there is a value stored already, we will perform the fuzzy operation OR, else we will just store newVal. Let's see the code:

//Update Linguistic value by name
void UpdateLinguisticValueByName(string name, double newVal)
    //Find LinguisticValue
    LinguisticValue* value = FindLinguisticValueByName(name);

    //If there is value, we should perform operator OR
    if(value->GetLinguisticValue() != -1)
        value->SetLinguisticValue(CFuzzyCalculator::OR(value->GetLinguisticValue(), newVal));
        value->SetLinguisticValue(newVal); //There is no value, just set newVal




The class LinguisticValue is used for storing linguistic values. Variables A, B, C, and D are "borders" of the trapezium (trapezoid). For example, the linguistic variable Distance has three linguistic values (Low, Average, and Height) and for the linguistic value "Low", the variables A, B, C, and D would be A = 0, B = 0, C = 1, D = 2. Every LinguisticValue has a unique name (like in CLinguisticVariable). The variable linguisticValue is used for storing a numeric value. The default value is -1. This value means, how much input value belongs to this LinguisticValue trapezium. For the linguistic value Average (linguistic variable Speed, input: 0 (km/h)), this value would be equal to 0.5 (see image above). There is only one method (except the constructor, getters, and setters) called CalculateLinguisticValue. We have to take care of the correctness of the inputs, so if inputs are out of range, we should normalize them. Then we need to calculate the trapezoidal function. The result of the trapezoidal function is the linguistic value for a specific variable.

double CalculateLinguisticValue(double input)
    //Normalize variables
    if(input < A)
        input = A;
    else if(input > D)
        input = D;
    //Calculating Trapezoid function
    if ((input <= A)
        || (input > D ))
        return 0;
    else if ((A < input) && (input < B))
        return (input - A) / (B - A);
    else if ((B <= input) && (input <= C))
        return 1;
        return (D - input) / (D - C);



Probably the simplest class in the project. There are only two static methods. The method AND implements the operator AND, which is equal to returning the minimal value.

//Operator AND
static double AND(double a, double b)
    if(a < b)
        return a;
    return b;

and method OR implements operator OR, returning the maximal value.

//Operator OR
static double OR(double a, double b)
    if(a > b)
        return a;
    return b;




Fuzzy Logic consists of linguistic variables and fuzzy rules. This class is used for storing a fuzzy rule. A fuzzy rule consists of objects of the class CFuzzyToken. The only functionality of the class is adding CFuzzyRuleToken to a rule. For example, CFuzzyRule could be:


Every fuzzy rule should have an output variable!



Like I said before, CFuzzyRuleToken is just one part of a CFuzzyRule. Let's describe all variables. operation describes what kind of operation is between the previous and current CFuzzyRuleToken. Supported operators are OR, AND, and EMPTY. EMPTY means there isn't any operator ("VOID"). The EMPTY token is just used in the first and last tokens in the rule. Also tokens can be negated (variable b_negation). Every CFuzzyToken has a pointer to CLinguisticVariable and the name of the linguistic value. Let's see the CFuzzyRule example a little bit closer.


What are tokens? There are three token examples:

operation = EMPTY
b_Negate = true
p_linguisticVariable= SPEED
linguisticValueName = "SLOW"

Token_2 operation = AND
b_Negate = false
p_linguisticVariable= DISTANCE 
linguisticValueName = "CLOSE"

operation =EMPTY
b_Negate = false
p_linguisticVariable= SIGNAL 
linguisticValueName = BRAKE"

Please note, TOKEN_3 is the output token! Every CFuzzyRule must have a token with an output variable!!!

The method CalculateTokenOutputValue is used for getting an input value from the hash map h_fuzzyInputHashMap and calling a method for calculating the linguistic value. The input variable h_fuzzyInputHashMap is a hash_map filled with objects (class CFuzzyInput). In CFuzzyInput is stored input values for specific linguistic variables. CFuzzyInput will be explained later.

//Calculate token value
double CalculateTokenOutputValue(hash_map <string, CFuzzyInput*> h_fuzzyInputHashMap)
    hash_map <string,> :: const_iterator iterator;
    //Find linguistic variable
    iterator = h_fuzzyInputHashMap.find(p_linguisticVariable->ToString());
    CFuzzyInput* temp = (CFuzzyInput*)iterator->second;
    double input = temp->GetInputValue();
    //Calculate linguistic value
    return p_linguisticVariable->CalculateLinguisticValueByName(linguisticValueName, input);



CFuzzyInput has only two variables, variableName for the linguistic variable name and inputValue (type double) for the value. For example, CFuzzyInput could be variableName = "SPEED" and inputValue = "43" (km/h).



CFuzzyReasoner is the heart of the FuzzyLogic system. It's used for calculating fuzzy rule output values and the final defuzzyfication. The CFuzzyReasoner variable v_fuzzyRulesVector is used for storing fuzzy rules (CFuzzyRule). Let's see the most important method in FuzzyLogic, FuzzyRuleReasoner. The method takes as inputs a fuzzy rule and a hash map filled with fuzzy inputs. Every fuzzy rule token is checked if it is an output variable or not. If not, output variables are calculated linguistic values of the current token variable. Then we check if the token is negated or not. If the linguistic variable is not first in the fuzzy rule and it's not an output variable then we should have an operator different than EMPTY. Only the first variable in the fuzzy rule must have the operator EMPTY (for the output value, operator isn't important). For the output value we just set a new value (resetVal) and return a pointer to the output token.

//Start fuzzy rule reasoner
CFuzzyRuleToken* FuzzyRuleReasoner(CFuzzyRule* fuzzyRule, 
                 hash_map <string, CFuzzyInput*> h_fuzzyInputs)
    double resultVal = 0;
    for(unsigned int i = 0; i < fuzzyRule->GetFuzzyRuleTokens().size(); i++)
        //Get fuzzy rule token
        CFuzzyRuleToken* token = fuzzyRule->GetFuzzyRuleTokens()[i];
            //Update output object
            //Return result token
            return token;
            double tokenVal = token->CalculateTokenOutputValue(h_fuzzyInputs);
                tokenVal = 1 - tokenVal;    //Negate value
            if(i == 0)
                resultVal = tokenVal;        //Set value
            else if(token->IsOrOperator())
                resultVal = CFuzzyCalculator::OR(resultVal, tokenVal); //OR operator
            else if(token->IsAndOperator())
                resultVal = CFuzzyCalculator::AND(resultVal, tokenVal); //AND operator
    //This won't happends saso
    return NULL;

The following method just calls reasoning for every fuzzy rule in the FuzzyLogic API.

//Start reasoner for fuzzy rulles
CFuzzyRuleToken* CalculateFuzzyRules(hash_map <string, CFuzzyInput*> h_fuzzyInputs)
    //Reset all values
    CFuzzyRuleToken* outputObject;
    //Calculate all fuzzy rules
    for(unsigned int i = 0; i < v_fuzzyRulesVector.size(); i++)
        //Glede na izhodno vrednost izhodne spremeljivke naredi update izhodnega objekta
        outputObject = FuzzyRuleReasoner((CFuzzyRule*)v_fuzzyRulesVector[i], h_fuzzyInputs);
    //Return output object
    return outputObject;

The last step in Fuzzy Logic reasoning is Defuzzyfication. It's implemented in the next two methods.

double Defuzzy(CFuzzyRuleToken *outputToken)
    //For every output value
    CLinguisticVariable* lVar = outputToken->GetLinguisticVariable();
    vector<LinguisticValue*> valuesList = lVar->GetLinguisticValuesList();

    double upEqualation = 0;
    double downEqualation = 0;
    //Calculating defuzzy value
    for(unsigned int i = 0; i < valuesList.size(); i++)
        LinguisticValue* val =;
        upEqualation += val->GetLinguisticValue()
            * CalculateTrapezoidBalance(val->GetA(), val->GetB(), val->GetC(), val->GetD()); 
        downEqualation += val->GetLinguisticValue();
    //Return output value of system
    if(downEqualation == 0)
        return 0;
    return upEqualation / downEqualation;

//Calculating surface of trapezoid 
double CalculateTrapezoidBalance(double A, double B, double C, double D)
    return ((1 / (B - A)) * (2 * pow(B,3) - 3 * A * pow(B,2) + pow(A,3)) + 
        3 * (pow(C,2) - pow(B,2)) + (1 / (D-C)) * (2 * pow(C,3) - 3 * D * pow(C,2) + pow(D,3)))
    / (3 * (B - A) + 6 * (C - B) + 3 * (D - C));

How to use it?

Probably you are wondering how to use this FuzzyLogic API. It's not so complicated. For making your life easier, I have made three simple examples. The first one is for a Fuzzy Cruise Control, the second for a basketball player, and the last one for a ski jumper. All examples are in the class called CExperiments. Let's see the simple basketball player example. We create three linguistic variables, then we add linguistic values to the linguistic variables. With the linguistic variables, we create two rules and add the rules to FuzzyLogic.

void BuildBasketballPlayersRules()
    //Method for building necessary rules for Basketball players
    CLinguisticVariable *height = new CLinguisticVariable(false,"Height");
    CLinguisticVariable *age = new CLinguisticVariable(false,"Age");
    CLinguisticVariable *basketball_player = 
              new CLinguisticVariable(true,"Basketball_player");

    //Add linguistic values to variable
    height->AddLinguisticValue(new LinguisticValue("Low_height",150,150,170,180));
    height->AddLinguisticValue(new LinguisticValue("Average_height",170,180,185,190));
    height->AddLinguisticValue(new LinguisticValue("Tall",185,195,210,210));

    age->AddLinguisticValue(new LinguisticValue("Young",10,10,25,30));
    age->AddLinguisticValue(new LinguisticValue("Average_young",25,35,40,45));
    age->AddLinguisticValue(new LinguisticValue("Old",50,60,80,80));
    age->AddLinguisticValue(new LinguisticValue("Average_old",40,45,50,55));
    basketball_player->AddLinguisticValue(new LinguisticValue("Suitable",0.5,0.6,1,1));
    basketball_player->AddLinguisticValue(new LinguisticValue("Unsuitable ",0,0,0.4,0.5));

    //IF age = Young AND height = Tall THEN basketball_player = "Suitable"
    CFuzzyRule* rule1 = new CFuzzyRule();
    rule1->AddTokenToRule(new CFuzzyRuleToken(false,EMPTY, age,"Young"));
    rule1->AddTokenToRule(new CFuzzyRuleToken(false,AND, height,"Tall"));
    rule1->AddTokenToRule(new CFuzzyRuleToken(false,EMPTY, basketball_player,"Suitable"));

    //IF age = "Old" THEN basketball_player = "Unsuitable"
    CFuzzyRule* rule2 = new CFuzzyRule();
    rule2->AddTokenToRule(new CFuzzyRuleToken(false,EMPTY, age,"Old"));
    rule2->AddTokenToRule(new CFuzzyRuleToken(false,EMPTY, 
                             basketball_player,"Unsuitable "));

    //Add rules

    //Add linguistic variables, if you want to obtain
    //more informations about fuzzy calculations

How to execute the example

With the next sample you should understand how to use the class CExperiment.

int _tmain(int argc, _TCHAR* argv[])
    //Create instance of CExperiments.
    CExperiments* experiment = new CExperiments();
    //Create rules

    //Hash_map for storing inputs
    hash_map <string, CFuzzyInput*> h_fuzzyInputs;
    //Put some values to inputs
    CFuzzyInput* inputRazdalja = new CFuzzyInput("Distance", 1.8);
    CFuzzyInput* inputPriblizevanje = new CFuzzyInput("Approaching", 15);
    CFuzzyInput* inputHitrost = new CFuzzyInput("Speed", -8);
    //Insert inputs to the hash_map
    h_fuzzyInputs.insert(CFuzzyInput_Pairs(inputRazdalja->GetVariableName(), inputRazdalja));
    h_fuzzyInputs.insert(CFuzzyInput_Pairs(inputPriblizevanje->GetVariableName(), inputPriblizevanje));
    h_fuzzyInputs.insert(CFuzzyInput_Pairs(inputHitrost->GetVariableName(), inputHitrost));

    //Calculate fuzzy Logic output signal
    double outputSignal = experiment->CalculateFuzzyRules(h_fuzzyInputs);
    //Get some additional informations from fuzzy logic 
    double t = experiment->GetC_ByName("Distance","Average");
    double v1 = experiment->GetLinguisticVariableValue("Signal","Brake");
    double v2 = experiment->GetLinguisticVariableValue("Signal","Maintain");
    double v3 = experiment->GetLinguisticVariableValue("Signal","Accelerate");

    double v4 = experiment->GetLinguisticVariableValue("Distance","Low");
    double v5 = experiment->GetLinguisticVariableValue("Distance","Average");
    double v6 = experiment->GetLinguisticVariableValue("Distance","High");

    double v7 = experiment->GetLinguisticVariableValue("Approaching","Slow");
    double v8 = experiment->GetLinguisticVariableValue("Approaching","Average");
    double v9 = experiment->GetLinguisticVariableValue("Approaching","Fast");

    double v10 = experiment->GetLinguisticVariableValue("Speed","Slow");
    double v11 = experiment->GetLinguisticVariableValue("Speed","Acceptable");
    double v12 = experiment->GetLinguisticVariableValue("Speed","Fast");

    delete experiment;

    return 0;

Too complicated?

For even easier defining of rules and attributes, I made a simple DSL (domain specific language).


The only class of the project CFuzzyLogicDSL is CFuzzyLanguageParser. This class is used for parsing fuzzy rules and attributes. The input value is the path to the file with fuzzy rules / attributes, and output values are updated rules and attributes in CExperiment (you have to put a CExperiment* pointer to the CFuzzyLanguageParser constructor). Let's see the input file format. Please, please be very accurate with spacing. If you forget spaces, the parser won't work (I have tried to keep a simple implementation). You can define the attributes in this format:

Linguistic_Variable_Name Input/Output ValueName_0 (A,B,C,D) ValueName_N (A,B,C,D)

and rules:

IF Linguistic_Variable_Name = Linguistic_Value_Name AND ... 
  AND Linguistic_Variable_Name NOT Linguistic_Value_Name THEN 
  Linguistic_Variable_Name = Linguistic_Value_Name

Also there is the possibility to write comments, using:

% This is comment

The next step is code explanation. The "main" method is Parse. Simple reading line by line, splitting tokens by space, then checking if is a commend, empty line, rule, or attribute.

void Parse(char* filePath)
    ifstream ifs(filePath);
    string line;
    while( getline( ifs, line ) )
        vector<string> tokens = SplitBy(line,' ');
        //Skip lines without text
        if(tokens.size() > 0)
            //Skip comments
    //Close stream

Here are the methods for checking if a line is a comment or rule:

//Check is line is comment
bool IsComment(string token)
    //Return true if is comment
    if( == '%')
        return true;
    return false;

bool IsRule(string token)
    //Return true if is rule
    if(token == "IF")
        return true;
    return false;

How do we parse rules and attributes? Check the next two simple methods. ParseFuzzyRule just goes over all tokens (we don't need to process the first token, its should be "IF") and check if it is an operator token (AND / OR) and set the appropriate operation. Then we check if there is negation or we are on the "set" (token "="). If this condition is true, we just have to set the previous and next token, create a new CFuzzyRuleToken, and add it to the rule.

void ParseFuzzyRule(vector<string> ruleTokens)
    //Rule example
    //IF distance = low AND approaching NOT slow THEN signal=breake
    //SKIP IF token
    bool negated = false;
    string leftSide;
    string rightSide;
    Operation operation = EMPTY; 
    CFuzzyRule* rule = new CFuzzyRule();

    for(unsigned int i = 1; i < ruleTokens.size(); i++)
        //Check for operator
        //OPERATORS =, Operator(AND, OR), NOT, THEN
        if((ruleTokens[i] == "AND") || (ruleTokens[i] == "OR"))
            if(ruleTokens[i] == "AND")
                operation = AND;
                operation = OR;
        else if((ruleTokens[i] == "=") || (ruleTokens[i] == "NOT"))
            leftSide = ruleTokens[i - 1];
                //Next token is right side
            if(ruleTokens[i] == "NOT")
                negated = true;
            rightSide = ruleTokens[++i];
            //ADD TOKEN TO RULE
            CLinguisticVariable* linVar = 
            assert(linVar != NULL);
              new CFuzzyRuleToken(negated,operation,linVar,rightSide));
            operation = EMPTY;
            negated = false;

Now, parsing the attributes. The first token is always the linguistic variable name, the second token should be information of the attribute. There can be N linguistic values. We have to go over all tokens and parsing is Input or Output. With that information, we can create CLinguisticVariable. Then we can start to parse the linguistic values. We have to go over all the remaining tokens. The next token has to be the linguistic value name, followed by the linguistic values (method ParseLinguisticValues). When all linguistic values are parsed, we can add LinguisticVariable to the list (in CExperiment).

void ParseFuzzyAtribute(vector<string> attTokens)
    //Distance Input Low (0,0,1,2) Average (1,2,3,4) High (3,4,5,5)
    //Linguistic variable name
    //Input or output 
    //Linguistic value name
    //Values A,B,C,D
    string linguisticVariableName =;
    bool output = true;
    if( == "Input")
        output = false;
    //Creating new linguistic variable
    CLinguisticVariable *linguisticVariable = 
       new CLinguisticVariable(output,linguisticVariableName);

    //Adding linguistic values to variable
    for(unsigned int i = 2; i < attTokens.size(); i++)
        string linguisticValueName =;
        vector<double> linguisticValues = ParseLinguisticValues(;
        //Check for error!
        assert(linguisticValues.size() == 4);
        LinguisticValue* linValue = new LinguisticValue(linguisticValueName,

vector<double> ParseLinguisticValues(string token)
    vector<double> linguisticValues;
    //Remove first and last char
    token = token.erase(0,1);
    token = token.erase(token.size() - 1, 1);
    vector<string> values = SplitBy(token, ',');

    //Values size should be 4!
    for(unsigned int i = 0; i < values.size(); i++)
    return linguisticValues;

Input file example

Distance Input Low (0,0,1,2) Average (1,2,3,4) High (3,4,5,5)
Approaching Input Slow (0,0,10,20) Average (10,20,30,40) Fast (30,40,50,50)
Speed Input Slow (-50,-50,-10,0) Acceptable (-10,0,0,10) Fast (0,10,50,50)
Signal Output Brake (-5,-5,-2,-1) Maintain (-2,-1,1,2) Accelerate (1,2,5,5)

IF Distance = Low AND Approaching NOT Slow THEN Signal = Brake
IF Distance = Average AND Approaching = Fast THEN Signal = Brake
IF Speed = Fast THEN Signal = Brake
IF Distance NOT Low AND Approaching = Average THEN Signal = Maintain
IF Distance = High AND Approaching NOT Fast AND Speed = Acceptable THEN Signal = Maintain
IF Distance = Average AND Speed = Slow THEN Signal = Maintain
IF Distance = High AND Speed = Slow THEN Signal = Accelerate

I want to see it!

My friend Jan Bezget made a really cool 3D visualization (using OGRE) of the Cruise Control example. You can find his visualization here: Click me!



You have now seen that implementation of fuzzy logic can be very simple and effective. It's impressive that an easy AI approach such us fuzzy logic can be so useful. Canon used fuzzy logic for autofocusing, it's often used also in air conditioners, even in the Sendai subway system! I hope that you liked my article and my FuzzyLogic API implementation. Thank you for reading :)


This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


About the Author

Sašo Mađarić
Slovenia Slovenia
I'm Sašo Mađarić, student in master course of the computer scient in university FERI Maribor, Slovenia. I have knowledge programming languages like C, C++, Java, C#, Adobe Flash/Flex, Objective C 2.0, js,... I have couple of years experiences with developing software for some slovenian companies, but i also worked in private university PUC Minas Gerais located in Belo Horizonte, Brazil. I'm interested in many areas, like artificial intelligence, image processing, development of computer games, information systems... For more informations please contact me by email.

You may also be interested in...

Comments and Discussions

QuestionDefuzzyfication! Pin
Member 1212857112-Feb-16 14:07
memberMember 1212857112-Feb-16 14:07 
Questionfr->AddFuzzyRule(rule1); Problem Pin
Member 1193851727-Aug-15 3:10
memberMember 1193851727-Aug-15 3:10 
Questionmistake results? Pin
Member 1176890417-Jun-15 23:24
memberMember 1176890417-Jun-15 23:24 
AnswerI'm sorry. I solved this problem by myself. Pin
Member 1176890422-Jun-15 8:12
memberMember 1176890422-Jun-15 8:12 
QuestionHow to run it? Pin
Member 1118029329-Oct-14 19:26
memberMember 1118029329-Oct-14 19:26 
QuestionHellow brother.. I need to know how to handle 2 inputs and get an output Pin
MG Husny Ahmad20-Jan-14 5:00
memberMG Husny Ahmad20-Jan-14 5:00 
AnswerRe: Hellow brother.. I need to know how to handle 2 inputs and get an output Pin
Sašo Mađarić21-Jan-14 4:00
memberSašo Mađarić21-Jan-14 4:00 
GeneralPlease sir.. i feel little bit difficult to understand and how to run the system.. i want a rain forecast system.. Pin
MG Husny Ahmad21-Jan-14 4:38
memberMG Husny Ahmad21-Jan-14 4:38 
GeneralRe: Please sir.. i feel little bit difficult to understand and how to run the system.. i want a rain forecast system.. Pin
Sašo Mađarić24-Jan-14 8:11
memberSašo Mađarić24-Jan-14 8:11 
GeneralRe: Please sir.. i feel little bit difficult to understand and how to run the system.. i want a rain forecast system.. Pin
MG Husny Ahmad24-Jan-14 17:57
memberMG Husny Ahmad24-Jan-14 17:57 
Questiongood Pin
alannx4-Nov-13 16:32
memberalannx4-Nov-13 16:32 
AnswerRe: good Pin
Sašo Mađarić18-Jan-14 8:34
memberSašo Mađarić18-Jan-14 8:34 
GeneralMy vote of 5 Pin
Mihai MOGA8-Feb-12 7:31
memberMihai MOGA8-Feb-12 7:31 
GeneralMy vote of 5 Pin
Kanasz Robert18-Jan-12 21:52
mvpKanasz Robert18-Jan-12 21:52 
GeneralMy vote of 5 Pin
kanecc18-Jan-12 9:31
memberkanecc18-Jan-12 9:31 
GeneralRe: My vote of 5 Pin
Sašo Mađarić18-Jan-12 12:26
memberSašo Mađarić18-Jan-12 12:26 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.

Permalink | Advertise | Privacy | Terms of Use | Mobile
Web01 | 2.8.170308.1 | Last Updated 18 Jan 2012
Article Copyright 2012 by Sašo Mađarić
Everything else Copyright © CodeProject, 1999-2017
Layout: fixed | fluid