Starting in CS202, we're going to wean you from the IDE. Rather quickly, in fact. You are going to learn how to write C++ programs in a Unix environment. This will be far more cumbersome than using an IDE. However, it facilitates you learning about computers, which is an important part of your education.
We're in a fortunate time in history (writing this in 2019) that all operating systems have some version of Linux at their core. So, whether you are running native Linux, Windows, Mac-OS or whatever today's Pi operating system is, you should have access to a Linux shell with a C++ compiler. This needs to be the first thing that you do for this class -- besides learning how to use the lab computers, you should make sure you have your own personal access to a Unix environment. Consult the TA's in lab if you have questions. That's part of their job responsibilities.
Since this tutorial does not cover file permissions, please also read this web page, which discusses file permissions and chmod.
There is an updated verion of vi called vim. It is free, and is the default version of vi on our lab machines. It is usually part of mac downloads, and you can configure cygwin to install it. Better yet, on Windows, you can download a vim program so that you can simply double-click it and it pops up a vim window. Go ahead and do that.
Then, go to http://www.vim.org/docs.php and download the book PDF and start working through the tutorial. I know a low of vi tricks and will use them in class. If you see me do something and don't understand it, ask and I'll back up and show it to you.
Our example program is the canonical "hello world" program, which is in the file src/hw.cpp in the directory for these lecture notes (/home/jplank/cs202/Notes/Unix-Vi). Of course, if you click on that link, you can save the program on your own computer.
I will always use "UNIX>" to denote my shell prompt. I will usually have keyboard input either boldfaced, or boldfaced and in red. That helps you to figure out what I'm doing with these lecture notes.
You cannot run a C++ file. Instead, you have to "compile" it with a program called a "compiler." The compiler that we use is called g++. If you run g++ on a C++ file, and there are no errors, it will generate an "executable" file. By default, that file is named a.out. You may run that file by simply typing its name, preceded by "./" into the shell.
UNIX> pwd /home/jplank/cs202/Notes/Unix-Vi UNIX> ls bin index.html makefile src UNIX> ls src hw.cpp UNIX> ls -l src total 4 -rw-r--r--. 1 jplank jplank 103 Aug 18 12:57 hw.cpp UNIX> g++ src/hw.cpp UNIX> ls a.out bin index.html src UNIX> ls -l total 36 -rwxr-xr-x. 1 jplank jplank 18088 Aug 18 14:26 a.out drwxr-xr-x. 2 jplank jplank 19 Aug 18 14:20 bin -rw-r--r--. 1 jplank jplank 13461 Aug 18 13:35 index.html -rw-r--r--. 1 jplank jplank 202 Aug 18 14:20 makefile drwxr-xr-x. 2 jplank jplank 20 Aug 18 14:14 src UNIX> ./a.out Hello World! UNIX>In this example, I compiled src/hw.cpp and it created the executable a.out. I ran it by typing "./a.out", and it printed "Hello World!"
The "ls -l" gives you a detailed listing of the files, including ownership (jplank), last modification time (August 18, 12:57 for a.out), size (18088 bytes for a.out), and "permissions." Those are in the first word. The x's in the listing for a.out mean that it is a program that can be executed. (BTW, if you compile this, you'll very likely get a different size for a.out, as it depends on your machine and compiler).
I can make g++ create the executable with a different name using the "-o filename" flag. You put that flag before the "source file" (the .cpp file) and I typically like to put executables in the bin directory:
UNIX> rm a.out UNIX> g++ -o bin/hw src/hw.cpp UNIX> ls -l bin total 20 -rwxr-xr-x. 1 jplank jplank 18088 Aug 18 13:00 hw UNIX> bin/hw Hello World! UNIX>When your program has errors, the compiler will print out error messages, and it will not make an executable. Sometimes figuring out what the error is difficult. However, you usually get a line number of the problem, meaning you can edit the source file, go to that line, and try to figure it out. For example, go ahead and modify hw.cpp so that there is no semi-colon after "endl":
UNIX> vi src/hw.cpp ... delete that semi-colon UNIX> cat src/hw.cpp #include <iostream> using namespace std; int main() { cout << "Hello World!" << endl // There's no semi-colon after endl return 0; } UNIX> g++ src/hw.cpp src/hw.cpp: In function 'int main()': src/hw.cpp:6:33: error: expected ';' before 'return' cout << "Hello World!" << endl ^ ; return 0; ~~~~~~ UNIX>That's a nice error message -- you need a semi-colon on line 6. By the way, if you haven't used "cat" before, it simply prints a file to the screen. Fix the bug, recompile and rerun to double-check yourself. Now, edit it again, and delete the second quotation mark. I'll use "cat -n" to print line numbers when it prints the file:
UNIX> vi src/hw.cpp ... delete the second quotation mark: UNIX> cat -n src/hw.cpp 1 #include <iostream> 2 using namespace std; 3 4 main() 5 { 6 cout << "Hello World! << endl; // There's now no quotation mark after '!' 7 return 0; 8 } UNIX> g++ src/hw.cpp src/hw.cpp:6:11: warning: missing terminating " character cout << "Hello World! << endl; ^ src/hw.cpp:6:11: error: missing terminating " character cout << "Hello World! << endl; ^~~~~~~~~~~~~~~~~~~~~~ src/hw.cpp: In function 'int main()': src/hw.cpp:7:3: error: expected primary-expression before 'return' return 0; ^~~~~~ UNIX>That error printout is a little more cluttered, but it gets the point across. Some are more difficult. On my macintosh, when I try to compile that program, I get vomit on the screen:
UNIX> g++ src/hw.cpp hw.cpp:6:11: warning: missing terminating " character hw.cpp:6: error: missing terminating " character hw.cpp: In function 'int main()': hw.cpp:7: error: no match for 'operator<<' in 'std::cout << return 0 ' /usr/include/c++/4.2.1/ostream:112: note: candidates are: std::basic_ostream<_CharT, _Traits>& std::basic_ostream<_CharT, _Traits>::operator<<(std::basic_ostream<_CharT, _Traits>& (*)(std::basic_ostream<_CharT, _Traits>&)) [with _CharT = char, _Traits = std::char_traitsWhen you get that, just look at the first few lines and ignore the rest. The first few lines here help you diagnose the problem in the same way as on our lab machines.] /usr/include/c++/4.2.1/ostream:121: note: std::basic_ostream<_CharT, _Traits>& std::basic_ostream<_CharT, _Traits>::operator<<(std::basic_ios<_CharT, _Traits>& (*)(std::basic_ios<_CharT, _Traits>&)) [with _CharT = char, _Traits = std::char_traits ] /usr/include/c++/4.2.1/ostream:131: note: std::basic_ostream<_CharT, _Traits>& std::basic_ostream<_CharT, _Traits>::operator<<(std::ios_base& (*)(std::ios_base&)) [with _CharT = char, _Traits = std::char_traits ] /usr/include/c++/4.2.1/ostream:169: note: std::basic_ostream<_CharT, _Traits>& std::basic_ostream<_CharT, _Traits>::operator<<(long int) [with _CharT = char, _Traits = std::char_traits ] /usr/include/c++/4.2.1/ostream:173: note: std::basic_ostream<_CharT, _Traits>& std::basic_ostream<_CharT, _Traits>::operator<<(long unsigned int) [with _CharT = char, _Traits = std::char_traits ] /usr/include/c++/4.2.1/ostream:177: note: std::basic_ostream<_CharT, _Traits>& std::basic_ostream<_CharT, _Traits>::operator<<(bool) [with _CharT = char, _Traits = std::char_traits ] /usr/include/c++/4.2.1/bits/ostream.tcc:92: note: std::basic_ostream<_CharT, _Traits>& std::basic_ostream<_CharT, _Traits>::operator<<(short int) [with _CharT = char, _Traits = std::char_traits ] /usr/include/c++/4.2.1/ostream:184: note: std::basic_ostream<_CharT, _Traits>& std::basic_ostream<_CharT, _Traits>::operator<<(short unsigned int) [with _CharT = char, _Traits = std::char_traits ] /usr/include/c++/4.2.1/bits/ostream.tcc:106: note: std::basic_ostream<_CharT, _Traits>& std::basic_ostream<_CharT, _Traits>::operator<<(int) [with _CharT = char, _Traits = std::char_traits ] /usr/include/c++/4.2.1/ostream:195: note: std::basic_ostream<_CharT, _Traits>& std::basic_ostream<_CharT, _Traits>::operator<<(unsigned int) [with _CharT = char, _Traits = std::char_traits ] /usr/include/c++/4.2.1/ostream:204: note: std::basic_ostream<_CharT, _Traits>& std::basic_ostream<_CharT, _Traits>::operator<<(long long int) [with _CharT = char, _Traits = std::char_traits ] /usr/include/c++/4.2.1/ostream:208: note: std::basic_ostream<_CharT, _Traits>& std::basic_ostream<_CharT, _Traits>::operator<<(long long unsigned int) [with _CharT = char, _Traits = std::char_traits ] /usr/include/c++/4.2.1/ostream:213: note: std::basic_ostream<_CharT, _Traits>& std::basic_ostream<_CharT, _Traits>::operator<<(double) [with _CharT = char, _Traits = std::char_traits ] /usr/include/c++/4.2.1/ostream:217: note: std::basic_ostream<_CharT, _Traits>& std::basic_ostream<_CharT, _Traits>::operator<<(float) [with _CharT = char, _Traits = std::char_traits ] /usr/include/c++/4.2.1/ostream:225: note: std::basic_ostream<_CharT, _Traits>& std::basic_ostream<_CharT, _Traits>::operator<<(long double) [with _CharT = char, _Traits = std::char_traits ] /usr/include/c++/4.2.1/ostream:229: note: std::basic_ostream<_CharT, _Traits>& std::basic_ostream<_CharT, _Traits>::operator<<(const void*) [with _CharT = char, _Traits = std::char_traits ] /usr/include/c++/4.2.1/bits/ostream.tcc:120: note: std::basic_ostream<_CharT, _Traits>& std::basic_ostream<_CharT, _Traits>::operator<<(std::basic_streambuf<_CharT, _Traits>*) [with _CharT = char, _Traits = std::char_traits ] UNIX>
In lecture note and lab directories, I will include a file called makefile. When you type "make" in one of these directories, it will perform compilation for you. Also, if you type "make clean", it will delete temporary and compiled files. These are both super-useful features, so even if you don't learn how to write a makefile, you should get used to using make when I have written one:
UNIX> ls # As you note, a.out is leftover from previously. a.out bin index.html makefile src UNIX> ls bin # So is bin/hw. hw UNIX> make clean # "make clean" deletes these files. rm -f bin/* a.out UNIX> ls # See -- there's no more a.out bin index.html makefile src UNIX> ls bin # And no more bin/hw UNIX> make # Typing "make" compiles src/hw.cpp to bin/hw g++ -std=c++98 -Wall -Wextra -o bin/hw src/hw.cpp UNIX> bin/hw Hello World! UNIX>