C++ 'extras'"But wait - there's MORE!!" |
C++ is a big language, ie. has LOTS of features, syntax, patterns, etc. It is impossible to cover them all in under 3 weeks!
Today we'll touch on aspects that we had left out - an assortment to 'round out' our learning of C++.
Spend more time after this course, to play with these additional items you encounter today.
Earlier we saw how to create (write into) a file, using the 'ofstream' class (via #include
Correspondingly, the 'ifstream' class is used to READ IN data from (text as well as binary) files.
Here is sample code that shows file reading: we open a file and read in 'word' by 'word' (tokens separated by blanks) - you can adapt this to read all sorts of text data. This one counts the number of occurences of "the", in the US Constitution :)
A container is simply an object that stores data (eg. vector, PGMImage, an array..). C++ comes with a huge list of commonly-used containers, out of the box. The built-in 'vector' container is an industrial-strength version of a simple array. Here is an example of its usage.
A 'stack' is a VERY useful container/data structure. It has two main operations: push(), pop(). Among other things, it is useful for evaluating expressions in Reverse Polish Notation (RPN). Eg. given the RPN expression 3 4 2 * 1 5 - 2 3 ^ ^ / +, here is the evaluation:
A data structure:
So - many real-world PROBLEMS can be solved computationally, via ALGORITHMS that manipulate (the contents of) DATA STRUCTURES. Remember: algorithms+datastructures=programs.
There is/are a variety of containers, each with many methods - take the time to learn what they are, where they are useful, and how to use them (doing so will save you time!). Here are four good sources of info:
As if standard containers are not enough, C++ also gives you implementations of algorithms for sorting, searching, counting, etc. Again, knowing (about) these can be valuable!
Here is an example that shows sort() at work.
This is a mechanism to isolate and group a set of vars, objects, functions:
namespace identifier
{
named_entities
}
Why? One reason: because we can have two different 'versions' of a variable or function, and use either one (or have three versions, etc).
This shows an example of its use.
'Exception' is another name for error, which can be triggered by a LOT of causes: invalid calculation, invalid file, access restrictions, memory shortage, etc, etc. If we don't "catch" an error that is "thrown" to us, our program will stop working at the point of the error occurence, ie it will 'crash'.
Using exceptions, we can code 'defensively', to HANDLE errors (possibly work around them), instead of letting our program just crash.
Try NOT to do this :)
Instead, might be better to think about creating an abstract base class with A's and B's methods (all made pure virtual), and "implementing" (a la Java) such an 'interface'.
Here is more on the topic.
C++ offers yet another form of 'overloading' (or polymorphism): 'templated' ("type tunable") classes.
Consider the 'row' class we created earlier, which helps create a chain (int *) of ints. What if we want a chain of doubles instead? We'd need to create a DoubleRow (for example), with a double *ptr; if we want a chain of chars, we'd create CharRow with a char *ptr, and so on. That's a lot of needless code replication (where len and printRow() are copied and used over and over - this goes against an important/practical/useful principle in coding: "do not repeat code needlessly".
Creating a single, 'tunable', 'templated' row class helps solve this problem:
template <typename T> class row {
private:
..
}// row
On occasion, you might need to call 'legacy' C functions inside a C++ source (esp. ones that use malloc() and free()). To do so, you need to use the 'extern' keyword:
// C function declarations, wrapped in an extern
extern "C" {
int g(double);
double h();
};// extern "C"
// defns for above, C code [not C++]
int g(double d)
{
/* ... */
}
double h()
{
/* ... */
}
// C++ code that calls our C functions
void fn(int i, double d) {
int ii = g(d);
double dd = h();
// ...
}
//..
fn(7,3.14); // C++ call that will make C calls
Here is a complete program that shows the above.
The 'asm' keyword (or '__asm__') is used to specify 'inline' assembly code (where RAW registers are used for data manipulation at the processor level, using assembly language code such as mov, add, sub etc.).
Standard C++ vars (including those inside objects, accessible by pointers etc) can be intermixed with assembly code, making it easy to 'feed' data into an assembler routine, and 'extract' results out of it. This can make for VERY powerful programming, where we mix higher level constructs (function calls, 'if' statements..) with lower level instructions that are directly executed by the underlying processor. Here is the assembly language for the Intel x86 family of processors.
Below is an example [run it in repl.it or CodeBlocks!], modified from the code here :
#include <iostream>
using namespace std;
// here's the "usual" way
int gcdUsual(int a, int b) {
if (a == 0)
return b;
return gcdUsual(b%a, a);
}// gcdUsual()
// note that in the body of gcd() below, we're using assembly language instructions such
// as movl and je; %%eax etc are registers. Google 'assembly language tutorial' for more info.
// here's the "cool" way :)
int gcdASM(int a, int b) {
int result ;
/* Compute Greatest Common Divisor using Euclid's Algorithm */
__asm__ __volatile__ ( "movl %1, %%eax;"
"movl %2, %%ebx;"
"CONTD: cmpl $0, %%ebx;"
"je DONE;"
"xorl %%edx, %%edx;"
"idivl %%ebx;"
"movl %%ebx, %%eax;"
"movl %%edx, %%ebx;"
"jmp CONTD;"
"DONE: movl %%eax, %0;" : "=g" (result) : "g" (a), "g" (b)
);
return result ;
}// gcdASM()
int main() {
int first, second ;
cout << "Enter two integers (to obtain their GCD), eg. 28 12: " << endl;
cin >> first >> second;
cout << "The GCD of " << first << " and " << second << " is " << gcdUsual(first,second) << ", computed using gcdUsual" << endl;
cout << "The GCD of " << first << " and " << second << " is " << gcdASM(first,second) << ", computed using gcdASM" << endl;
return 0 ;
}// main()
Before the compiler compiles your code, the code is pre-processed by.. the pre-processor. Eg. #include
'#define NUM 100' for example will cause the pre-processor to substitute (search-and-replace) 100 for every occurence of NUM in your code.
Here is more: http://www.cplusplus.com/doc/tutorial/preprocessor/
You can pass arguments into the main() function [since it is a function like any other], by running a program like so (in a shell):
genMandel 1024 768 fun.pgm -2 -1 -1 1
To do so, you need to handle command line arguments, where the main() function's arg list typically looks like so:
int main(int argc, char* argv[])
Here is a complete example. Note that we'd use atoi() and atof() to convert incoming strings to numbers [ALL arguments passed in, come in as strings!].
This replit.com program is another example.
A 'Makefile' contains dependencies that specify which source files need to be compiled and linked, and what needs to be (re)generated. It is VERY useful when you need to compile dozens, hundreds or even thousands (!) of source (.h, .cpp) files into a single executable or library.
Specifically, in a makefile, you'll find several 'target-dependency-command' triplets of this form:
scanner.o: scanner.c scanner.h gcc -Wall -c scanner.c
The above means that "if scanner.c or scanner.h [dependency] is NEWER/RECENT (timestamp-wise) compared to scanner.o [target] , run 'gcc -Wall -c scanner.c' [command] to generate a newer scanner.o". Note that the command MUST start with a 'tab' character [the whitespace in front of 'gcc...' above are not space characters, it's a single 'tab']!
'make' is a program that processes the dependencies in Makefile; it can also be used to compile Java programs, and even be used for non-compilation tasks [such as image-processing dataflows].
Here is more on 'make': https://www.cs.colby.edu/maxwell/courses/tutorials/maketutor/ and http://www.cs.swarthmore.edu/~newhall/unixhelp/howto_makefiles.html
Such makefiles are a big part of 'build' systems, created and maintained by 'DevOps' teams ['Automate the compilation...'].