AlwaysLearn

Resume

Things I Know and have done.

Contents

C++ Samples

<< Back

The code below parses strings of the form coef*sin(f*val) or coef*cos(f*val) and generates a waveform based on the string. This code was used in my Frequency Analyzer application.

MathParser.h Sample:

#pragma once
#include <math.h>
#include <vector>
#include <string>

using namespace std;

//From application "FrequencyAnalyzer.sln" (VS 2005) by John Alway
//MathParser.h/cpp:
//Parses equations of the form coef*sin(f*val), or coef*cos(f*val) or just coef;
//or if f = 0, then coef*sin(val) or coef*cos(val)

struct SMathUnit{
	float coef;
	int SinCos; //0 if neither, 1 if sin(), 2 if cos()
	int f; // f=1 and then 2*pi*f is part in
	float val; //the value in the sin(val) or cos(val) if there is one
};

class CMathParser {
	vector<SMathUnit> m_MathUnit;
public:
	CMathParser();
	int parseMathString(string &mathString);
	void calculate(int timeWave[]);
	int strToNumber(string str);
	void clear();
	~CMathParser();
private:
	float calcSin(float coef,float val,float samplePoint);
	float calcCos(float coef,float val,float samplePoint);

	void replace(string &str,string &str1,string &str2);
	int produceMathUnits(string &mathString,vector<string> &mathUnits);
	int processProducts(string &mathUnit,SMathUnit &mu);
	int putInProperForm(string &mathUnit);
	bool isValidChar(char chr,string str);
};
  

MathParser.cpp Sample:

#include "stdafx.h"
#include "MathParser.h"

extern int g_SampleRate;

CMathParser::CMathParser()
{
	m_MathUnit.clear();
}

int CMathParser::parseMathString(string &mathString)
{
	vector<string> mathUnits;
	SMathUnit  mu;
	char chr;
	int pos, start;
	
	//search for cos, sin and p2f sub strings
	//and replace them by c, s and f respectively

	if(mathString.length() == 0){
		mathString = "Error -- no equation";
		return 1;
	}
	replace(mathString,(string)" ",(string)"");	
	replace(mathString,(string)"p2f",(string)"f");
	replace(mathString,(string)"cos",(string)"c");
	replace(mathString,(string)"sin",(string)"s");	

	replace(mathString,(string)"-c",(string)"-1*c");
	replace(mathString,(string)"-s",(string)"-1*s");
	
	//break down elements that are additive (and subtracted)
	if(produceMathUnits(mathString,mathUnits))
		return 1; //error found

	for(int i=0;i<mathUnits.size();i++){
		processProducts(mathUnits[i],mu);
		m_MathUnit.push_back(mu);		
	}	
	mathUnits.clear();
	return 0;
}

int CMathParser::putInProperForm(string &mathUnit)
{
	int pos, start;
	char chr;

	//If character before any 'c' is a number, insert an *
	pos = mathUnit.find('c',0);
	if(pos != string::npos){
		if(pos == 0){
			replace(mathUnit,(string)"c",(string)"1*c");
		}else{
			if(isValidChar(mathUnit[pos-1],"0123456789.")){
				replace(mathUnit,(string)"c",(string)"*c");
			}
		}
	}

	pos = mathUnit.find('s',0);
	if(pos != string::npos){
		if(pos == 0){
			replace(mathUnit,(string)"s",(string)"1*s");
		}else{
			if(isValidChar(mathUnit[pos-1],"0123456789.")){
				replace(mathUnit,(string)"s",(string)"*s");
			}
		}
	}

	pos = mathUnit.find('f',0);
	if(pos != string::npos){
		if(isValidChar(mathUnit[pos+1],"0123456789.")){
			replace(mathUnit,(string)"f",(string)"f*");
		}
	}	

	return 0;
}

int CMathParser::processProducts(string &mathUnit,SMathUnit &mu)
{
	string num;
	char chr;
	int pos;

	mu.SinCos = 0;
	mu.coef = 1.0f;
	mu.f = 0;
	mu.val = 1.0f;
	//Put in proper form
	putInProperForm(mathUnit);
	//Is there an f?
	if(mathUnit.find('f',0) != string::npos){
		mu.f = 1; 
		replace(mathUnit,(string)"f",(string)"");
	}
	//Is there an 's'?
	if(mathUnit.find('s',0) != string::npos){
		mu.SinCos = 1; 
		replace(mathUnit,(string)"s",(string)"");
	}
	//Is there an 'c'?
	if(mathUnit.find('c',0) != string::npos){
		mu.SinCos = 2; 
		replace(mathUnit,(string)"c",(string)"");
	}
	
	if(mu.SinCos == 0){//only a coefficient
		sscanf_s((char *)mathUnit.c_str(),"%f",&mu.coef);
	}
	else{  //Extract coefficient from front of sin() or cos()
		pos = mathUnit.find('*',0);
		num = mathUnit.substr(0,pos);
		//convert from string to float

		sscanf_s((char *)num.c_str(),"%f",&mu.coef);
		//Get val part
		mathUnit = mathUnit.substr(pos+2);		
		replace(mathUnit,(string)"*",(string)"");
		replace(mathUnit,(string)")",(string)"");
		if(mathUnit.length() > 0)
			sscanf_s((char *)mathUnit.c_str(),"%f",&mu.val);		
	}	
	return 0;
}

int CMathParser::produceMathUnits(string &mathString,vector<string> &mathUnits)
{
	string str="";
	int pos;
	char chr;
	bool openParen=false;
	int start;

	for(int i=0;i < mathString.length();i++){
		chr = mathString[i];//.at(i);
		if(chr == '-' && i != 0 && openParen == false){
			mathUnits.push_back(str);
			str = "";			
		}else if(chr == '+' && i!=0 && openParen == false){
			mathUnits.push_back(str);
			str = "";
			continue;
		}
		else if(chr == '('){
			if(openParen)
			{
				mathString = "Error -- two opening parentheses in a row";
				return 1;
			}
			openParen = true;
		}
		else if(chr == ')'){
			if(openParen == false)
			{
				mathString = "Error -- two closing parentheses in a row";
				return 1;
			}
			openParen = false;
		}else if(isValidChar(chr,"0123456789.-+*csf") == false){
			mathString = "Error -- invalid character found";
			return 1;
		}
		str += chr;
	}
	mathUnits.push_back(str);
	return 0;
}

bool CMathParser::isValidChar(char chr,string str)
{
	//string str="0123456789.-+*csf";
	int pos = str.find(chr,0);

	if(pos == string::npos)//not a valid character
		return false;

	return true;
}
//replace str1 with str2 in str
void CMathParser::replace(string &str,string &str1,string &str2)
{
	int pos;
	int start=0;
	while(true){
		pos = str.find(str1,start);
		if(pos == string::npos) break;
		str.erase(pos,str1.length());
		str.insert(pos,str2,0,str2.length());
		start = pos + str2.length();
	}
}

void CMathParser::calculate(int timeWave[])
{
	SMathUnit mu;
	float value, total, samplePoint;
	for(int i=0;i<2048;i++){
		total = 0.0f;
		samplePoint = (float)i/(float)g_SampleRate;
		for(int j=0;j<(int)m_MathUnit.size();j++){
			mu = m_MathUnit[j];
			if(mu.SinCos == 0) { //just a constant
				value = mu.coef;
			}else if(mu.SinCos == 1) { // a sine function
				value = calcSin(mu.coef,mu.val,samplePoint);
			}else if(mu.SinCos == 2) { // a cosine function
				value = calcCos(mu.coef,mu.val,samplePoint);
			}
			total += value;
		}
		timeWave[i] = (int)total;
	}
}

float CMathParser::calcSin(float coef,float val,float samplePoint)
{
	float result;
	val *= 2.0f*3.14159265f;
	result = coef*sin(val*samplePoint);
	return result;
}

float CMathParser::calcCos(float coef,float val,float samplePoint)
{
	float result;
	val *= 2.0f*3.14159265f;
	result = coef*cos(val*samplePoint);
	return result;
}

//Converts str to a number if it is valid,
//otherwise returns val as a 0
int CMathParser::strToNumber(string str)
{	int val=0;

	//Remove any spaces
	replace(str,(string)" ",(string)""); 
	//isValidChar
	for(int i=0;i<str.length();i++){
		if(i == 0 && str[0] == '-'){
			continue;
		}
		else if(isValidChar(str[i],"0123456789") == false){			
			return val;
		}
	}
	sscanf_s(str.c_str(),"%d",&val);
	return val;
}
void CMathParser::clear()
{
	m_MathUnit.clear();
}

CMathParser::~CMathParser()
{
	m_MathUnit.clear();
}

 

<< Back
Resume Image