Lecture 14: Structure (2)
Structure example: Floating point number
#include <iostream>
#include <cctype> // isdigit()
#include <cmath> // pow()
#include <climits> // INT_MAX
using namespace std;
typedef struct Float_t
{
int sign;
int exp;
long mantissa;
} Float;
void normalize_float(Float &f)
{
while (f.mantissa > 0 && f.mantissa % 10 == 0)
{
f.mantissa /= 10;
f.exp++;
}
while (f.mantissa > INT_MAX)
{
f.mantissa /= 10;
f.exp++;
}
if (f.mantissa == 0)
{
f.exp = 0;
f.sign = 1;
}
}
Float parse_float_number(char input_buffer[])
{
Float result;
result.sign = 1;
result.exp = 0;
result.mantissa = 0;
int i = 0;
if (input_buffer[i] == '-')
{
result.sign = -1;
i++;
}
if (input_buffer[i] == '0')
{
i++;
}
else
{
while (isdigit(input_buffer[i]))
{
result.mantissa = result.mantissa * 10 + input_buffer[i] - '0';
i++;
}
}
if (input_buffer[i] == '.')
{
i++;
int factor = 1;
while (isdigit(input_buffer[i]))
{
result.mantissa = result.mantissa * 10 + input_buffer[i] - '0';
factor *= 10;
i++;
}
result.exp = -1 * (int)log10(factor);
}
if (input_buffer[i] == 'e' || input_buffer[i] == 'E')
{
i++;
int exp = 0;
if (input_buffer[i] == '-')
{
i++;
while (isdigit(input_buffer[i]))
{
exp = exp * 10 + input_buffer[i] - '0';
i++;
}
result.exp += -1 * exp;
}
else
{
while (isdigit(input_buffer[i]))
{
exp = exp * 10 + input_buffer[i] - '0';
i++;
}
result.exp += exp;
}
}
// normalize the result float
normalize_float(result);
return result;
}
void print_float_number(Float number)
{
if (number.sign == -1)
{
cout << "-";
}
cout << number.mantissa;
if (number.exp != 0)
{
cout << "e" << number.exp;
}
}
void clean_up_input_buffer(char input_buffer[])
{
for (int i = 0; input_buffer[i] != '\0'; i++)
{
input_buffer[i] = '\0';
}
}
Float add(Float a, Float b)
{
Float result;
int same_sign = a.sign * b.sign;
if (a.exp == b.exp)
{
result.sign = a.sign;
result.exp = a.exp;
result.mantissa = a.mantissa + same_sign * b.mantissa;
}
else if (a.exp > b.exp)
{
result.sign = a.sign;
result.exp = a.exp;
long exp_factor = (long)pow(10, a.exp - b.exp);
result.mantissa = a.mantissa + same_sign * b.mantissa / exp_factor;
}
else
{
result.sign = b.sign;
result.exp = b.exp;
long exp_factor = (long)pow(10, b.exp - a.exp);
result.mantissa = b.mantissa + same_sign * a.mantissa / exp_factor;
}
if (result.mantissa < 0)
{
result.sign *= -1;
result.mantissa *= -1;
} else if (result.mantissa == 0) {
result.sign = 1;
}
normalize_float(result);
return result;
}
Float sub(Float a, Float b)
{
Float result;
int same_sign = a.sign * b.sign;
if (a.exp == b.exp)
{
result.sign = a.sign;
result.exp = a.exp;
result.mantissa = a.mantissa - same_sign * b.mantissa;
}
else if (a.exp > b.exp)
{
result.sign = a.sign;
result.exp = a.exp;
long exp_factor = (long)pow(10, a.exp - b.exp);
result.mantissa = a.mantissa - same_sign * b.mantissa / exp_factor;
}
else
{
result.sign = b.sign;
result.exp = b.exp;
long exp_factor = (long)pow(10, b.exp - a.exp);
result.mantissa = b.mantissa - same_sign * a.mantissa / exp_factor;
}
if (result.mantissa < 0)
{
result.sign *= -1;
result.mantissa *= -1;
} else if (result.mantissa == 0) {
result.sign = 1;
}
normalize_float(result);
return result;
}
Float mul(Float a, Float b)
{
Float result;
result.sign = a.sign * b.sign;
result.exp = a.exp + b.exp;
result.mantissa = a.mantissa * b.mantissa;
normalize_float(result);
return result;
}
Float div(Float a, Float b)
{
Float result;
result.sign = a.sign * b.sign;
result.exp = a.exp - b.exp;
result.mantissa = a.mantissa / b.mantissa;
normalize_float(result);
return result;
}
int main()
{
char input_buffer[10000 + 1]; // + 1 for the last '\0'
Float a, b;
cout << "Input a float number (a) in (-)xxx.xxx(e|E)(-)(xxx): ";
cin >> input_buffer;
a = parse_float_number(input_buffer);
clean_up_input_buffer(input_buffer);
cout << "(a) = ";
print_float_number(a);
cout << endl;
cout << "Input a float number (b) in (-)xxx.xxx(e|E)(-)(xxx): ";
cin >> input_buffer;
b = parse_float_number(input_buffer);
clean_up_input_buffer(input_buffer);
cout << "(b) = ";
print_float_number(b);
cout << endl;
cout << "(a) + (b) = ";
print_float_number(add(a, b));
cout << endl;
cout << "(a) - (b) = ";
print_float_number(sub(a, b));
cout << endl;
cout << "(a) * (b) = ";
print_float_number(mul(a, b));
cout << endl;
cout << "(a) / (b) = ";
print_float_number(div(a, b));
cout << endl;
return 0;
}
$ g++ -g test.cpp && ./a.out
Input a float number (a) in (-)xxx.xxx(e|E)(-)(xxx): -123.456e3
(a) = -123456
Input a float number (b) in (-)xxx.xxx(e|E)(-)(xxx): 456.789e4
(b) = 456789e1
(a) + (b) = 444444e1
(a) - (b) = 469134e1
(a) * (b) = -563933427e3
(a) / (b) = 0
$
Structure example: Polynomial Equation
#include <iostream>
#include <cctype> // isdigit()
#include <vector>
using namespace std;
typedef struct Poly_t
{
int coef;
int exp;
} Poly;
void normalize(vector<Poly> &poly)
{
for (int i = 0; i < poly.size(); i++)
{
if (poly[i].coef == 0)
{
poly.erase(poly.begin() + i);
i--;
}
}
}
vector<Poly> parse_poly(char input_buffer[])
{
vector<Poly> result;
int i = 0;
while (input_buffer[i] != '\0')
{
Poly p;
int sign = 1;
p.coef = 0;
p.exp = 0;
if (input_buffer[i] == '-')
{
sign = -1;
i++;
}
else if (input_buffer[i] == '+')
{
i++;
}
if (input_buffer[i] == '0')
{
p.coef = 0;
i++;
}
else
{
while (isdigit(input_buffer[i]))
{
p.coef = p.coef * 10 + input_buffer[i] - '0';
i++;
}
}
p.coef *= sign;
if (input_buffer[i] == 'x')
{
i++;
if (input_buffer[i] == '^')
{
i++;
while (isdigit(input_buffer[i]))
{
p.exp = p.exp * 10 + input_buffer[i] - '0';
i++;
}
}
}
result.push_back(p);
}
return result;
}
void print_poly(const vector<Poly> &poly)
{
if (poly.size() == 0)
{
cout << "0";
return;
}
for (int i = 0; i < poly.size(); i++)
{
if (poly[i].coef == 0)
{
continue;
}
if (poly[i].coef >= 1 && i != 0)
{
cout << "+" << poly[i].coef;
}
else if (poly[i].coef == -1)
{
cout << "-";
}
else
{
cout << poly[i].coef;
}
if (poly[i].exp == 0)
{
continue;
}
else
{
cout << "x^" << poly[i].exp;
}
}
}
vector<Poly> poly_add(const vector<Poly> &a, const vector<Poly> &b)
{
vector<Poly> result;
int i = 0;
int j = 0;
while (i < a.size() && j < b.size())
{
if (a[i].exp == b[j].exp)
{
Poly p;
p.exp = a[i].exp;
p.coef = a[i].coef + b[j].coef;
result.push_back(p);
i++;
j++;
}
else if (a[i].exp > b[j].exp)
{
result.push_back(a[i]);
i++;
}
else
{
result.push_back(b[j]);
j++;
}
}
while (i < a.size())
{
result.push_back(a[i]);
i++;
}
while (j < b.size())
{
result.push_back(b[j]);
j++;
}
normalize(result);
return result;
}
void clean_up_input_buffer(char input_buffer[])
{
for (int i = 0; input_buffer[i] != '\0'; i++)
{
input_buffer[i] = '\0';
}
}
int main()
{
char input_buffer[10000 + 1];
vector<Poly> a, b;
cout << "Enter polynomial a: ";
cin >> input_buffer;
a = parse_poly(input_buffer);
clean_up_input_buffer(input_buffer);
cout << "Polynomial a: ";
print_poly(a);
cout << endl;
cout << "Enter polynomial b: ";
cin >> input_buffer;
b = parse_poly(input_buffer);
clean_up_input_buffer(input_buffer);
cout << "Polynomial b: ";
print_poly(b);
cout << endl;
vector<Poly> c = poly_add(a, b);
cout << "Polynomial c = a + b: ";
print_poly(c);
cout << endl;
}
$ g++ -g test.cpp && ./a.out
Enter polynomial a: -30x^3+20x^1
Polynomial a: -30x^3+20x^1
Enter polynomial b: 50x^3-20
Polynomial b: 50x^3-20
Polynomial c = a + b: 20x^3+20x^1-20
$
Structure example: Geometry Object
Ref: Computational geometry - Wikipedia
#include <iostream>
#include <vector>
using namespace std;
typedef struct Point_t
{
int x;
int y;
} Point;
typedef struct Triangle_t
{
Point p[3];
} Triangle;
typedef struct Quadrilateral_t
{
Point p[4];
} Quadrilateral;
typedef struct Polygon_t
{
vector<Point> p;
} Polygon;
Point parse_point(char input_buffer[], int i)
{
Point p;
while (input_buffer[i] != '\0')
{
if (input_buffer[i] == '(')
{
i++;
}
if (input_buffer[i] == '0')
{
p.x = 0;
i++;
}
else
{
while (isdigit(input_buffer[i]))
{
p.x = p.x * 10 + input_buffer[i] - '0';
i++;
}
}
if (input_buffer[i] == ',')
{
i++;
}
if (input_buffer[i] == '0')
{
p.y = 0;
i++;
}
else
{
while (isdigit(input_buffer[i]))
{
p.y = p.y * 10 + input_buffer[i] - '0';
i++;
}
}
if (input_buffer[i] == ')')
{
break;
}
}
return p;
}
Triangle parse_triangle(char input_buffer[])
{
Triangle t;
int i = 0;
while (input_buffer[i] != '\0')
{
for (int j = 0; j < 3; j++)
{
if (input_buffer[i] == '(')
{
i++;
}
t.p[j] = parse_point(input_buffer, i);
i += 2;
}
}
return t;
}
Quadrilateral parse_quadrilateral(char input_buffer[])
{
Quadrilateral q;
int i = 0;
while (input_buffer[i] != '\0')
{
for (int j = 0; j < 4; j++)
{
if (input_buffer[i] == '(')
{
i++;
}
q.p[j] = parse_point(input_buffer, i);
i += 2;
}
}
return q;
}
Polygon parse_polygon(char input_buffer[])
{
Polygon poly;
int i = 0;
while (input_buffer[i] != '\0')
{
if (input_buffer[i] == '(')
{
i++;
}
poly.p.push_back(parse_point(input_buffer, i));
i += 2;
}
return poly;
}
void print_geometry(const Point &p)
{
cout << "(" << p.x << ", " << p.y << ")" << endl;
}
void print_geometry(const Triangle &t)
{
cout << "Triangle: " << endl;
for (int i = 0; i < 3; i++)
{
print_geometry(t.p[i]);
}
}
void print_geometry(const Quadrilateral &q)
{
cout << "Quadrilateral: " << endl;
for (int i = 0; i < 4; i++)
{
print_geometry(q.p[i]);
}
}
void print_geometry(const Polygon &poly)
{
cout << "Polygon: " << endl;
for (int i = 0; i < poly.p.size(); i++)
{
print_geometry(poly.p[i]);
}
}
unsigned long int area(const Triangle &t)
{
unsigned long int sum = 0;
for (int i = 0; i < 3; i++)
{
sum += t.p[i].x * t.p[(i + 1) % 3].y;
sum -= t.p[i].y * t.p[(i + 1) % 3].x;
}
return sum / 2;
}
unsigned long int area(const Quadrilateral &q)
{
unsigned long int sum = 0;
for (int i = 0; i < 4; i++)
{
sum += q.p[i].x * q.p[(i + 1) % 4].y;
sum -= q.p[i].y * q.p[(i + 1) % 4].x;
}
return sum / 2;
}
unsigned long int area(const Polygon &poly)
{
unsigned long int sum = 0;
for (int i = 0; i < poly.p.size(); i++)
{
sum += poly.p[i].x * poly.p[(i + 1) % poly.p.size()].y;
sum -= poly.p[i].y * poly.p[(i + 1) % poly.p.size()].x;
}
return sum / 2;
}
int main()
{
char input_buffer[10000 + 1];
cout << "Enter the type of geometry (t|q|p) with points (x,y): ";
cin.getline(input_buffer, 10000);
if (input_buffer[0] == 't')
{
Triangle t = parse_triangle(input_buffer + 1);
print_geometry(t);
cout << "Area: " << area(t) << endl;
}
else if (input_buffer[0] == 'q')
{
Quadrilateral q = parse_quadrilateral(input_buffer + 1);
print_geometry(q);
cout << "Area: " << area(q) << endl;
}
else if (input_buffer[0] == 'p')
{
Polygon poly = parse_polygon(input_buffer + 1);
print_geometry(poly);
cout << "Area: " << area(poly) << endl;
}
else
{
cout << "Invalid input" << endl;
}
}
$ g++ -g test.cpp && ./a.out
Enter the type of geometry (t|q|p) with points (x,y): t((0,0),(1,1),(0,4))
Triangle:
(0, 0)
(1, 1)
(0, 4)
Area: 2
$ g++ -g test.cpp && ./a.out
Enter the type of geometry (t|q|p) with points (x,y): q((0,0),(1,1),(3,4),(0,4))
Quadrilateral:
(0, 0)
(1, 1)
(3, 4)
(0, 4)
Area: 6
$ g++ -g test.cpp && ./a.out
Enter the type of geometry (t|q|p) with points (x,y): p((0,0),(1,1),(3,4),(4,4),(0,4))
Polygon:
(0, 0)
(1, 1)
(3, 4)
(4, 4)
(0, 4)
Area: 6
$
Structure example: Vector & Matrix (Mathmatical)
#include <iostream>
#include <vector>
#include <cmath>
using std::cin;
using std::cout;
using std::endl;
typedef struct Vector_t
{
std::vector<double> unit;
double length;
} Vector;
typedef struct Matrix_t
{
std::vector<Vector> row_vectors;
} Matrix;
Vector parse_vector(char input_buffer[], int &i)
{
Vector v;
int number = 0
// parse normal vector
while (input_buffer[i] != '\0')
{
if (input_buffer[i] == '[')
{
i++;
}
if (input_buffer[i] == '0')
{
v.unit.push_back(0);
i++;
}
else
{
while (isdigit(input_buffer[i]))
{
number = number * 10 + input_buffer[i] - '0';
i++;
}
v.unit.push_back(number);
number = 0;
}
if (input_buffer[i] == ',')
{
i++;
}
if (input_buffer[i] == ' ')
{
i++;
}
if (input_buffer[i] == ']')
{
break;
}
}
// calc vector length
for (int j = 0; j < v.unit.size(); j++)
{
v.length = v.length + v.unit[j] * v.unit[j];
}
v.length = sqrt(v.length);
// normalize vector
for (int j = 0; j < v.unit.size(); j++)
{
v.unit[j] = v.unit[j] / v.length;
}
return v;
}
Matrix parse_matrix(char input_buffer[])
{
Matrix m;
// parse matrix
int i = 0;
while (input_buffer[i] != '\0')
{
if (input_buffer[i] == '[')
{
i++;
}
while (input_buffer[i] != ']')
{
m.row_vectors.push_back(parse_vector(input_buffer, i));
}
if (input_buffer[i] == ']')
{
i++;
}
}
return m;
}
void print_vector(const Vector &v)
{
cout << "[";
for (int i = 0; i < v.unit.size(); i++)
{
cout << v.unit[i] * v.length;
if (i != v.unit.size() - 1)
{
cout << ", ";
}
}
cout << "]";
}
void print_matrix(const Matrix &m)
{
cout << "[";
for (int i = 0; i < m.row_vectors.size(); i++)
{
print_vector(m.row_vectors[i]);
cout << endl;
}
cout << "]";
}
int main()
{
char input_buffer[10000 + 1];
cout << "Enter a vector: ";
cin.getline(input_buffer, 10000);
int i = 0;
Vector v = parse_vector(input_buffer, i);
cout << "Vector v: " << endl;
print_vector(v);
cout << endl;
cout << "Length: " << v.length << endl;
cout << endl;
cout << "Enter a matrix: ";
cin.getline(input_buffer, 10000);
Matrix m = parse_matrix(input_buffer);
cout << "Matrix m: " << endl;
print_matrix(m);
cout << endl;
}
$ g++ -g test.cpp && ./a.out
Enter a vector: [9,10,11,12]
Vector v:
[9, 10, 11, 12]
Length: 21.1187
Enter a matrix: [[1,2,3,4][5,6,7,8][9,10,11,12]]
Matrix m:
[[1, 2, 3, 4]
[5, 6, 7, 8]
[9, 10, 11, 12]
]
$