-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathTheory.cpp
More file actions
323 lines (254 loc) · 10.4 KB
/
Copy pathTheory.cpp
File metadata and controls
323 lines (254 loc) · 10.4 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
#include <iostream>
#include <string>
#include <memory>
/***
Example functions demonstating various C++ features.The nested functions are turned to strings for visual aid when explaining but actual nested functions are not allowed in C++.
This is also writen in a ".cpp" file to indicate the language, make use of the C++ standard library and show the syntax highlighting as well as the correction of code snippets.
***/
// Namespace (allows reusing of entities with same name by using accesing namespaces; kinda wraping them in an object).
namespace alpha
{
int value = 5;
};
namespace beta
{
int value = 10;
};
void exampleNamespace()
{
int value = 2;
// Not declaring namespace will use "local" value.
std::cout << "Printed value: " << value << std::endl;
// But declaring namespace will use that "namespace's value".
std::cout << "Printed value: " << alpha::value << std::endl;
// Can also declare what "namespace" is used for definitions. Loading the prefix|package before its useage which is later infered by what members are accessed.
using namespace std;
/***
Or, preferably to avoid naming conflicts and unnecessary renaming or memory overhead,
We can load a specific member of the "namespace" akin to accessing a json file.
***/
using std::string;
};
void exampleTypeRenaming()
{
/***
The "typedef" is used to rename existing data types or give them "nicknames";
So here "type_standard" of string is renamed to "str_t"; t used to indicate its a type.
***/
typedef std::string strTypeDef_t;
// But the common way of doing it has now changed to "using" for type renaming. Because it also works with templates.
using strUsing_t = std::string;
// So here all denominations represent the same type.
std::string fluff1 = "fluff";
strTypeDef_t fluff2 = "fluff";
strUsing_t fluff3 = "fluff";
};
void exampleInputAndOutput()
{
// '::' scope resolution operator; kind of like '.something' in object accessing .
std::string input;
// User input assigned to the input variable.
std::cin >> input;
// After the user inputs wrong data, we should use "clear" to reset the error flags on input and continue reading.
std::cin.clear();
/***
For longer strings "getline" can be used, if "cin" is preceeding "getline" the "\n" character after user input will be passed on to the second cin inside "getline" user input because of buffering.
This happens because "cin" reads until the white space character and does not consume the "\n" token at the end which ends up being buffered to the next input operation.
( Unlike "cin" , "getline" consumes the new line character at the end of the input ).
To avoid that we can use "ws" to clear the buffer of whitespace characters, before checking for new user input.
***/
std::getline(std::cin >> std::ws, input);
// For further sanitization we use "ignore" to clear the buffer of unwanted characters. The 2 parameters are number of characters to flush OR everything until "\n" is found, hopefuly at the end of the input.
std::cin.ignore(10000, '\n');
// And for an even clearer way instead of using an arbitrary number we can define the size of the numeric limits to the maximum stream size, which means everything in the buffer.
std::cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n');
// The "fflush" command forces "cout" to push whatever is inside the buffer before doing anything else. Not recommended for INPUT sanitization.
std::fflush(stdout);
// For OUTPUT sanitization we can simply use "endl" to add a new line and flush the buffer.
std::cout << "output" << std::endl;
};
// But, instead of declaring it like 3 different functions with the same name but different signatures ( name + parameters ), we can use templates.
template <typename T>
void exampleOverloadingAndTemplates()
{
// As opposed to TS, where you can declare different optional arguments to overload a function, the cpp overload is:
std::string example = "int function(int argument) {}";
std::string example = "std::string function(std::string argument) {}";
std::string example = "double function(double argument) {}";
/***
Here "T" is fulfilling the role of a placeholder for the type of argument passed to the function.
Which will be defined once the function is called with a specific type.
***/
std::string example = "dataType function(T argument) {}";
// We can either do type comparisons without defining when the type is known, be it at compile time or runtime.
if (std::is_same_v<T, int typeExpected>)
{
std::string example = "return dataType Logic";
};
/***
Or we can use "constexpr" and tell the compiler to only compile if something matches the if condition.
Meaning it can clean overhead at compile time but can break if used with runtime data checks.
***/
if constexpr (std::is_same_v<T, int typeExpected>)
{
std::string example = "return dataType Logic";
}
/***
Either way, we then access the type comparison "is_same" and pass parameters of T (type of passed argument) with the expected type.
And it compares the two data types and creates a boolean value, which we can access as a result with "_v".
***/
/***
Or for multiple types we can use several "typename", since "T" is instanced for local scope of each function (T is different for each different function),
but not instanced per variable, where ( argument1, argument2 ) might be different types.
***/
template <typename S, typename U, typename V>
std::string example = "dataType function(S argument1, U argument2, V argument3) {}";
// And then run comparison and logic based on types inside.
if (std::is_same_v<S, int typeExpected>)
{
std::string example = "return Logic";
};
// There is also the alternative of using "auto" for type deduction, but it is compile deduced and not as flexible, its basically lazy typing and slightly safer than using "any" in typescript.
auto variable = randomType();
};
void exampleArrays()
{
// Arrays can be declared statically or dynamically. And the array can be initialized with values or they can be added later.
int arrayStaticValues[5] = {1, 2, 3, 4, 5};
// Declaring values after initializing array with set size.
int arrayStaticNoValues[5] = {};
int arrayStaticNoValues[5] = {1, 2, 3, 4, 5};
// Dynamic arrays are allocated memory on the heap at runtime and require dealocation.
int n = std::cin.get();
int *arrayDynamic = new int[n];
// To avoid manual memory management use of smart pointers is recommended.
std::unique_ptr<int[]> arrayName(new int[n]);
// Can use "sizeof" to determine the size of array in bytes.
sizeof(arrayStaticValues);
// This can also be used to determine the number of elements in a static array.
std::string strings[] = {"one", "two", "three"};
sizeof(strings) / sizeof(std::string);
sizeof(strings) / sizeof(strings[0]);
// When passing an array to a function it decays to a pointer so the sizeof does not work as expected.
std::string example = "std::string function(std::string strings[]){}";
// Minimal detail I never use when looping
for (std::string string : strings)
{
};
// Arrays can also be multi dimensional, akin to matrixes.
std::string elements[3][3] = {
{"one", "two", "three"},
{"four", "five", "six"},
{"seven", "eight", "nine"}};
// Which can be used similarly to an ECS system for entity component storage or movement logic.
enum ComponentIndex
{
POS_X,
POS_Y,
POS_Z,
VEL_X,
VEL_Y,
VEL_Z,
COUNT
};
// We might want to also declare this dynamically later on but for now its a static value to showcase the concept.
const int ENTITY_COUNT = 2;
// We can either declare "component_count" or use the safer "count" method and access it as a member of the enum.
float movementLogic[ENTITY_COUNT][ComponentIndex::COUNT] = {
{1.0f, 2.0f, 3.0f, 0.1f, 0.2f, 0.3f}, // Entity 0
{4.0f, 5.0f, 6.0f, 0.4f, 0.5f, 0.6f}, // Entity 1
};
// So here accesing position of entity 1 on the Y axis would be:
float entity1POS_Y = movementLogic[1][ComponentIndex::POS_Y]; // Outputs 5.0f
// And if we really wanted to create a key value sort of system in multidimensional arrays we can always just use 2 enums.
enum entityIndex
{
ENTITY_0,
ENTITY_1,
};
// And then access it accordingly.
float entity0POS_Z = movementLogic[entityIndex::ENTITY_0][ComponentIndex::POS_Z]; // Outputs 3.0f
};
void memory()
{
// Memory can be accessed with &.
int age = 99;
// Like so.
std::cout << &age << std::endl;
/***
Pasing arguments to a function is usually done by value which copies the original values of the arguments.
In order to change the original values, we pass by reference "&value" or by pointer.
***/
std::string name = "NameCreative";
// "*" dereferencing value and pointing at its address "&".
std::string *pName = &name;
// Always initialize manual pointers even if its with "nullptr" and check if the pointer was assigned an address before "*" dereferencing.
int *pointer = nullptr;
// Dynamic memory (after the program is compiled) allocated at runtime.
int *pNum = NULL;
pNum = new int;
// Substitute with data input or math from received data.
*pNum = 2;
// Dealocate memory from heap.
delete pNum;
};
// Recursion, less code but more memory use. Useful for sorting algorythms.
void recursionWalk(int steps)
{
// Call the function within itself.
if (steps > 0)
{
recursionWalk(steps - 1);
};
};
// Structs are structures that group related variables under one name.
void structs()
{
// Similar to schemas in json.
struct student
{
// Can set default values at initialization, unlike enums where you can only alter the index.
std::string name;
double gpa;
bool enrolled;
};
student Johny;
student Judith;
student Jake;
Johny.enrolled = true;
Judith.gpa = 2.1;
Jake.name = "Bonkers";
};
// Classes, members, and constructors.
void classes()
{
// Refering to same named values say in a constructor.
class Student
{
private:
int creditCardNumber = 666;
// You can either specify what "friends" aka functions can access the private members directly.
friend void giveHackerFreeStuff();
// Or you can use a getter to read the data.
int getCreditCardNumberForNSA()
{
return creditCardNumber;
};
// And a setter to change the data inside the private member
void setMakeStudentBroke(int fakeCard)
{
creditCardNumber = fakeCard;
};
public:
std::string name;
int age;
double gpa;
// Refering to the constructors arguments of same name by calling this ( local scope ) value.
Student(std::string name, int age, double gpa)
{
this->name = name;
this->age = age;
this->gpa = gpa;
};
};
};