CS140 Lecture notes -- Unix, Vi, Files and Compiling

  • Jim Plank
  • Directory: ~plank/cs140/Notes/Unix-Vi
  • Lecture notes: http://www.cs.utk.edu/~plank/plank/classes/cs140/Notes/Unix-Vi
  • Last modification date: Tue Jan 10 18:42:50 EST 2012

    Where you are and where you are going

    In CS102, you learned to program using an IDE, which is itself a program to facilitate C++. The intent of this is to get the rewards of programming to you quickly, without a lot of the frustrations that you get when you don't use an IDE.

    Starting in CS140, 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.

    There are three major operating systems for laptops and computers these days: Windows, Mac OS-X, and the Unix machines (Linux, Solaris, etc). Our lab machines are Linux machines, and they will be the ones on which I assume we will be working. OS-X is nice because it actually has an integrated Unix environment. You can go to Applications and Utilities, and there will be a Terminal application. When you run it, you will be running a standard Unix command-line interpreter, called a shell. Life is good.

    On Windows, life is more difficult. You have two options. The first is to simply log into a Unix machine over the internet. Look for a "secure shell" program, and use it to log into one of our lab machines remotely. The second is to download a Unix environment for Windows. I typically use Cygwin -- it's free (download from www.cygwin.com, and for the most part, it works like you'd hope it would. It is a program on top of windows, though, and doesn't act like a true Unix operating system all the time. Such is life. I would recommend that if you want to work on a Windows machine, that you go ahead and download cygwin, and make sure that it has the programs vi and g++ installed.


    Learning Unix

    I'll do some basic Unix in class. However, Kevin Heard from Berkeley has written a wonderful tutorial, available at http://people.ischool.berkeley.edu/~kevin/unix-tutorial/. Work through the first five chapters, plus chapter 8. We don't support passwd, so don't worry about that yet. Also, don't spend too much time learning pico. You'll want to use a more powerful editor, like vi or emacs.

    Since this tutorial does not cover file permissions, please also read this web page, which discusses file permissions and chmod.

    Learning Vi

    The editor vi is my editor of choice. It is ancient, and getting it into your muscle memory takes a little time and dedication. It's worth it, in my opinion. However, you can use any editor you want: emacs, pico, even TextEdit or Wordpad. Still, give vi a try, because vi helps to make you think like a Computer Scientest.

    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.

    Files and Compilation

    After wading through the Unix and Vi tutorials, you will be able to create text files in your own directories. In Unix, C++ programs are text files, typically with the .cpp extension. A program may reside in one file, or it may be spread over many files. We'll start with just one file for now.

    Our example program is the canonical "hello world" program, which is in the file hw.cpp in the directory for these lecture notes (/home/plank/cs140/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> ls
    hw.cpp
    UNIX> ls -l
    total 8
    -rw-r--r--  1 plank  staff  98 Jan 11 13:22 hw.cpp
    UNIX> g++ hw.cpp
    UNIX> ls 
    a.out	hw.cpp
    UNIX> ls -l
    total 32
    -rwxr-xr-x  1 plank  staff  9776 Jan 11 13:29 a.out
    -rw-r--r--  1 plank  staff    98 Jan 11 13:22 hw.cpp
    UNIX> ./a.out
    Hello World!
    UNIX> 
    
    In this example, I compiled 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 (plank), last modification time (Jan 11 12:29 for a.out), size (9776 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.

    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):

    UNIX> rm a.out
    UNIX> g++ -o hw hw.cpp
    UNIX> ls -l
    total 32
    -rwxr-xr-x  1 plank  staff  9776 Jan 11 13:33 hw
    -rw-r--r--  2 plank  staff    98 Jan 11 13:22 hw.cpp
    UNIX> ./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 hw.cpp
    ... delete that semi-colon
    UNIX> cat hw.cpp
    #include 
    using namespace std;
    
    main()
    {
      cout << "Hello World!" << endl
      exit(0);
    }
    UNIX> g++ hw.cpp
    hw.cpp: In function "int main()":
    hw.cpp:7: error: expected `;' before "exit"
    UNIX> 
    
    That's a nice error message -- you need a semi-colon on line 7. Actually, it's line six, but the compiler says 7 because it discovered the error when it read the "exit" command. 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 hw.cpp
    ... delete the second quotation mark:
    UNIX> cat -n hw.cpp
         1	#include 
         2	using namespace std;
         3	
         4	main()
         5	{
         6	  cout << "Hello World! << endl;
         7	  exit(0);
         8	}
    UNIX> g++ 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: 'exit' was not declared in this scope
    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++ 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 << exit(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_traits]
    /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> 
    
    When 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.