Starting to Program in C++ (Basics & I/O)

Similar documents
CS354 gdb Tutorial Written by Chris Feilbach

Lab: Supplying Inputs to Programs

CSE 333. Lecture 9 - intro to C++ Hal Perkins Department of Computer Science & Engineering University of Washington

CSE 374 Programming Concepts & Tools. Hal Perkins Spring 2010

CS2141 Software Development using C/C++ Compiling a C++ Program

CMSC162 Intro to Algorithmic Design II Blaheta. Lab March 2019

CSE 374 Programming Concepts & Tools

CSE 374 Programming Concepts & Tools. Hal Perkins Fall 2015 Lecture 19 Introduction to C++

Welcome Back. CSCI 262 Data Structures. Hello, Let s Review. Hello, Let s Review. How to Review 1/9/ Review. Here s a simple C++ program:

Separate Compilation of Multi-File Programs

Welcome Back. CSCI 262 Data Structures. Hello, Let s Review. Hello, Let s Review. How to Review 8/19/ Review. Here s a simple C++ program:

PIC 10A Objects/Classes

Today in CS162. External Files. What is an external file? How do we save data in a file? CS162 External Data Files 1

Fall 2017 CISC/CMPE320 9/27/2017

C++ Basics. Data Processing Course, I. Hrivnacova, IPN Orsay

CSE 374 Programming Concepts & Tools

Chapter 1 Getting Started

CSE 303: Concepts and Tools for Software Development

C++ Support Classes (Data and Variables)

CSE 333 Lecture 9 - intro to C++

COMP Lecture Notes The Compiler

CSE 100: STREAM I/O, BITWISE OPERATIONS, BIT STREAM I/O

Understanding main() function Input/Output Streams

assembler Machine Code Object Files linker Executable File

CE221 Programming in C++ Part 1 Introduction

Lab 1: First Steps in C++ - Eclipse

Compilation and Execution Simplifying Fractions. Loops If Statements. Variables Operations Using Functions Errors

Chapter 1 - What s in a program?

Software Engineering /48

Piyush Kumar. input data. both cout and cin are data objects and are defined as classes ( type istream ) class

QUIZ. What is wrong with this code that uses default arguments?

y

Hello, World! in C. Johann Myrkraverk Oskarsson October 23, The Quintessential Example Program 1. I Printing Text 2. II The Main Function 3

Practicum 5 Maps and Closures

Operator overloading

377 Student Guide to C++

Scientific Computing

Object Oriented Design

These are notes for the third lecture; if statements and loops.

CS 220: Introduction to Parallel Computing. Arrays. Lecture 4

Reviewing gcc, make, gdb, and Linux Editors 1

Compiling with Multiple Files The Importance of Debugging CS 16: Solving Problems with Computers I Lecture #7

CSE 303: Concepts and Tools for Software Development

COSC 2P91. Introduction Part Deux. Week 1b. Brock University. Brock University (Week 1b) Introduction Part Deux 1 / 14

Intro. Scheme Basics. scm> 5 5. scm>

A couple of decent C++ web resources you might want to bookmark:

5. Applicative Programming. 1. Juli 2011

Saleae Device SDK Starting a Device SDK Project on Windows Starting a Device SDK Project on Linux... 7

C++ Basics. Lecture 2 COP 3014 Spring January 8, 2018

Cours de C++ Introduction

CSE 333 Interlude - make and build tools

Using Karel with Eclipse

Cpt S 122 Data Structures. Introduction to C++ Part II

COSC 2P95. Procedural Abstraction. Week 3. Brock University. Brock University (Week 3) Procedural Abstraction 1 / 26

CSCI 1100L: Topics in Computing Lab Lab 11: Programming with Scratch

Computer Science 2500 Computer Organization Rensselaer Polytechnic Institute Spring Topic Notes: C and Unix Overview

CS Software Engineering for Scientific Computing. Lecture 5: More C++, more tools.

Lecture 14: more class, C++ streams

Why C++ is much more fun than C (C++ FAQ)?

Computer Science II Lecture 2 Strings, Vectors and Recursion

Computer Science II Lecture 1 Introduction and Background

C++ Input/Output: Streams

Programmazione. Prof. Marco Bertini

How to approach a computational problem

CSE 333 Lecture 6 - data structures

Notes By: Shailesh Bdr. Pandey, TA, Computer Engineering Department, Nepal Engineering College

Project 1 Balanced binary

CS 220: Introduction to Parallel Computing. Beginning C. Lecture 2

CS1 Lecture 3 Jan. 18, 2019

Fast Introduction to Object Oriented Programming and C++

CS664 Compiler Theory and Design LIU 1 of 16 ANTLR. Christopher League* 17 February Figure 1: ANTLR plugin installer

Installing and Using Dev-C++

Chris' Makefile Tutorial

C++ For Science and Engineering Lecture 2

Compilers Project 3: Semantic Analyzer

Chapter 1 Introduction to Computers and C++ Programming

CS164: Programming Assignment 2 Dlex Lexer Generator and Decaf Lexer

CMSC 201 Fall 2016 Lab 09 Advanced Debugging


C Compilation Model. Comp-206 : Introduction to Software Systems Lecture 9. Alexandre Denault Computer Science McGill University Fall 2006

CSCI-1200 Data Structures Fall 2018 Lecture 3 Classes I

School of Computer Science CPS109 Course Notes 5 Alexander Ferworn Updated Fall 15

Computer Science 322 Operating Systems Mount Holyoke College Spring Topic Notes: C and Unix Overview

C / C++ Coding Rules

Spring CS Homework 12 p. 1. CS Homework 12

CS-XXX: Graduate Programming Languages. Lecture 9 Simply Typed Lambda Calculus. Dan Grossman 2012

Discussion 1H Notes (Week 3, April 14) TA: Brian Choi Section Webpage:

Linux Tutorial #1. Introduction. Login to a remote Linux machine. Using vim to create and edit C++ programs

Lecture 12 CSE July Today we ll cover the things that you still don t know that you need to know in order to do the assignment.

Lecture 2, September 4

G52CPP C++ Programming Lecture 17

CS125 : Introduction to Computer Science. Lecture Notes #4 Type Checking, Input/Output, and Programming Style

CS11 Intro C++ Spring 2018 Lecture 3

The Structure of a C++ Program

Separate Compilation Model

Outline. 1 Function calls and parameter passing. 2 Pointers, arrays, and references. 5 Declarations, scope, and lifetimes 6 I/O

6. Pointers, Structs, and Arrays. March 14 & 15, 2011

TOPIC 2 INTRODUCTION TO JAVA AND DR JAVA

Streams. Ali Malik

Basic program The following is a basic program in C++; Basic C++ Source Code Compiler Object Code Linker (with libraries) Executable

Transcription:

Copyright by Bruce A. Draper. 2017, All Rights Reserved. Starting to Program in C++ (Basics & I/O) On Tuesday of this week, we started learning C++ by example. We gave you both the Complex class code and the code for the programming assignment. That has given you a chance to look at a lot of C++, and hopefully to learn from it. But the problem with learning from examples is that you see things you don t understand, and then what? The answer is that you go and find out about those specific topics. We start that today by focusing on aspects of C++ that are different from Java and that you need for the first programming assignment: the compiler and I/O. What does the g++ command do? Two things, actually. First it compiles each source (.cpp) file from C++ to object code, which can be thought of as assembly code with symbolic addresses. The symbolic links point to addresses of methods defined in other files, and are necessary because every source file is compiled independently of every other source file. At this step, the g++ compiler creates an object (.o) file for every source (.cpp) file. Then g++ calls the linker to combine all the object files into a single executable file, resolving the symbolic links in the process. This produces the executable file. How do you compile a project from the command line? Well, for starters, you only compile your source (.cpp) files. Your header (.h) files are presumably included in one or more of your source files, or else they have no effect. To compile your source files, you could type: g++ *.cpp This would call the compiler on every source (.cpp) file in your directory, and then call the linker on the resulting object (.o) files to produce an executable file named a.out. It would then delete the object files. Unfortunately, this would almost certainly lead to a compiler error, as the compiler would not be able to find the files you told it to include. In particular, if you file has a line like: #include <foo.h> The compiler won t find it. It will generate an error because it can t find it, and then more errors because the rest of your file needed to classes or function in Foo. You could fix is by putting the filename in quotes (making it a string), but in my opinion this is poor style. Using a string filename tells the compiler to look in your local directory. This is fine for PA1, but will break as soon as you want to reuse code by including the same file in several projects. So it is better not to go down this path. Instead, it is better to tell the compiler where to look for your header files. In unix, the current directory is always called. (yes, that s a period with nothing else). The I flag tells the compiler to look in a directory for header files. Putting these two things together, we get: g++ -I. *.cpp Now your code should compile. (If it doesn t, there is probably a syntax problem with your code.) Note that you can use the I flag many times, if you want the compiler to look at multiple

directories. This is common for large projects. Also, the compiler automatically knows where the standard template library is, so you can write things like #include<vector> without worrying where the vector file is. A similar thing happens with external libraries: you have to tell the compiler which libraries to include. For example, if you want to compile a program that uses X11 commands, you need to tell it to use the X11 library. You can do this via: g++ -I. *.cpp lx11 X11 is a standard library, so the compiler knows where it is. The compiler just needs to know which library to link to. If you wanted to link to a non-standard library, you would use the L flag to tell the compiler where to find the non-standard library. For example, if you had a non-standard library called MyLib in the current directory, you would compile using g++ -I. L. lmylib *.cpp But we get ahead of ourselves. We are not using extra libraries yet So now you can compile your code, but it produces an executable called a.out. That s OK, you can always rename the executable file, but you would probably like the compiler to name the executable something else, like PA1 (for programming assignment 1). You can do this with the output flag, -o g++ -I. *.cpp o PA1 Two more flags you should get in the habit of using. Wall turns on all compiler warnings. Warnings are things in your code that aren t syntax errors, but are almost certainly semantic errors. For example, if you reach the end of a non-void function without returning a value, or if you declare a variable and never use it, possibly because of a misspelling. You should always include the Wall flag, and fix anything it warns you about. g preserves the symbol table as part of the executable. There is a very slight cost to this (it makes the executable file larger), but it is needed if you want to run the debugger or a profiler or many other development tools. Therefore, while your program is in development you should always get in the habit of using the g flag. Therefore a good command-line compilation command for programming assignment #1 is: g++ -Wall g I. *.cpp o PA1 There are still more compiler flags that we won t get into (the resources page of the class website has a link to the compiler documentation). This is already complex, however. Fortunately, we don t invoke the compiler from the command line very often. Instead, we use make files, as introduced in the recitation session. A good make file not only allows you to forget the compiler flags, it supports separate compilation. Let s look at a sample make file, of the type you might make for assignment #1. My make file begins with three lines: CC = g++ LFLAGS = -o PA1 CFLAGS = -g Wall I. -c

What do these lines do? They declare variables for the make system. The first line is mostly a convention. It declares the compiler (we use g++) as a variable named CC. This is useful in large projects where you may be targeting different platforms with different compilers. It allows you to change all the compile commands for all the files in the project by just changing the first line of the make file. We will not change compilers in this course, however, so I am just showing this to you to show the convention. The second line defines the flags I will use for the linker (hence LFLAGS ). At the moment, the only flags I need to send to the linker are the flags for renaming the output. I want the output to be called PA1, not a.out, and o PA1 renames the output file. More generally, however, if I were linking to other libraries, this is where I would put the l and L flags. The third line defines the flags for the compiler (hence CFLAGS ). As discussed above, the -g flag preserves information for the debugger and other tools, the Wall flag turns on warnings, and the I. flag tells the compiler to look in the current directory for include files. The c flag tells the compiler to compile but not link. Instead, produce a.o file with the same name as the source file (e.g. main.cpp becomes main.o). If I have just one class in Assignment #1 called histogram, then the rest of my make file might look like this: PA1:<tab>main.o histogram.o <tab>$(cc) main.o histogram.o $(LFLAGS) main.o:<tab>main.cpp histogram.h <tab>$(cc) main.o $(CFLAGS) histogram.o:<tab>histogram.cpp histogram.h <tab>$(cc) histogram.o $(CFLAGS) The first command tells the make system how to make the executable PA1 by linking together object files, namely main.o and histogram.o. The items on the first line are the target object to be made, in this case PA1, and the files it depends on, main.o and histogram.o. The idea is that when the user tells it to make PA1, it will first check if main.o and histogram.o are up to date. If they are, it calls the linker using the information in the second line. If they aren t, it recursively calls make to update the files it depends on, and then calls the linker. The second line is simply the linker command, with variables expanded (so that $(CC) becomes g++, etc.). A note about syntax. In the example above, I have used <tab> to mark the tab character. In an editor, this will look like a series of spaces (how many depends on the editor), but make is picky. Where I have marked <tab> it must be a tab character, not spaces, or make will throw a syntax error. The groups of lines after the first two compile source code into object code. The first one, for example, compiles main.cpp into main.o; the second one compiles histogram.c into histogram.o. The c flag in CFLAGS tells the compiler to compile but not link. As before, the files after the colon and the target (e.g. main.o) specify the files that the target depends on. If any of these files have been changed, then the target needs to be recompiled. Now, on to I/O. There are two basic I/O classes: ostream for output, and istream for input. You have to include them, because they are classes in a library, not language primitives. To do this, write

#include <iostream> (You don t need a space between include and <, but spaces are allowed) Warning: One of the things I dislike about your text is that it tends to omit the include statements in its examples. If you try one of their examples and it won t compile, think about what include statements you might need to add. How do we use streams? Output streams, in particular, are easy. There is a predefined output stream call std::cout. It is defined to be standard output, as is usually the terminal (unless it has been rerouted, for example by a unix pipe). If I have an integer a, and want to write its value to the terminal, then I just write: std::cout << a; << is called the insertion operator (because it inserts values into streams), and it will work for any primitive type. int, double, char, you name it. There are a couple of things to note. You can output many things in one line by daisy chaining the << symbol, for example: std::cout << a << b; The insertion operator only outputs what you tell it to, however, so if you want a space between two integers, you have to put it there, as in: std::cout << a << << b; Also, Booleans print as 0 or 1 (they are implemented as small constants). To write an end-of-line character (carriage return), insert std::endl into the stream. For example: std::cout << a << << b << std::endl; std::endl is actually more than just a carriage return. It also causes the system to flush the output buffer, i.e. it forces the system to immediately print the line, since otherwise I/O is buffered. This can matter if you are using print statements to debug your program. Still, in general, output is easy for primitives. To output instances of a class, you overload the insertion operator but we ll hold off on that until later. You can do the homework assignment by just outputting primitives. There is a second pre-defined output stream called std::cerr. It behaves like std::cout (both default to the terminal), but is separate. This stream is intended for errors, and allows shell scripts and users to separate the normal output to std::cout from the errors written to std::cerr. Input from the terminal is just about as easy. The input stream from the terminal is predefined as std::cin. To read an integer from an input stream, you could write the following: int a; std::cin >> a;

>> is called the extraction operator, because it extracts values from streams Quick question: between the lines above, what is the value of a? (answer: undefined) But what exactly does it read? The >> operator will: Skip initial whitespace Read as many non-whitespace characters as it can interpret to be the data type you asked for. For example, let s say the input stream contains the following characters: 14 5i This example is motivated by the Complex class presented earlier. If you read an integer from this stream using >>, it will skip the initial spaces, and then read 14 as an integer. The input stream now contains 5i. What if you do it again? The second time it will skip a space, and then read 5. It cannot interpret i as an integer, so it stops and returns the number 5. Note that no error occurred: you asked it to read an integer, and it did. Look back at the Complex number code I gave you on Monday, and look at the Read() method of the Complex number class. It does exactly this. The format of a complex number is 1+2i (or 3-2i). What if you read into a char (character) now? It will set the char to be i, and again the read will succeed. What if instead you read into an integer again? Then it fails i is not an integer. So what happens? First, the read fails, so the integer you are reading into is unchanged. The input stream does not throw an error. It has the same value it had before the read operation. (This value might be undefined, hence the question above.) Second, the input stream enters the fail state. I repeat that no error is thrown, however. So how do you know if a read succeeded? By checking the fail() method of the stream. If a read fails, then istr.fail() becomes true. So after every read, you should check for istr.fail(). Again, look at the Complex code for examples. So what happens if you keep going after a read has failed? Well, your code will continue to run, but once a stream has failed, every subsequent read from that stream will fail also. This can produce some real gibberish, not to mention infinite loops. So always check for failures. Why not throw an error? Because I might be testing the input of a stream. Can I read it as an int? If not, can I read it as something else? To do this, I can clear the fail state from the stream (istr.clear()) and try again. It can get annoying typing std:: all the time. The std:: is there because all the standard libraries are in the std namespace. To avoid all this typing, add

using std::cin; using std::cout; using std::endl; Right below the #include <iostream> statement at the top of the file. Now, istream and ostream are abstract streams classes. They do input and output in general, not to any particular file or device. std::cin and std::cout are instances of more specific derived classes that do input and output to standard streams Although you will often write your IO functions in terms of istream and ostream, you rarely instantiate them. Instead you instantiate one of 2 derived classes. In the case of input, the two most common derived classes are ifstream & istringstream (there is also ofstream and ostringstream for output, and all of these are in the std namespace). An ifstream is an input stream from a file. You will need this for the assignment. In particular, you will need to open an input string from the file named in argv[1]. For example, you will probably have a line that looks like: ifstream istr(argv[1]); Once you instantiate an ifstream, it works just like an istream in terms of the >> operator. Indeed, you may choose to pass it as an instance of istream (if you remember polymorphism from CS161). An istringstream is an input stream from a string. This might also be handy for the assignment, particularly if you want your error messages to contain line number. (This is not required, but it is a nice thing to do, and you may appreciate it down the road if you have I/O errors.) You need to use #include<fstream> to use ifstream, and you need to use #include<sstream> to use istringstream. Is there more to I/O? Of course. You can format things in various ways, detect the end-of-file condition (a subset of fail()), read a line of code at a time, etc. But this should get you started. Use your reference! One last comment about programming assignments in general. When you are programming, there is always a customer. You program for someone. In this case, I am the customer. If there are details I haven t specified, you need to ask about them. Why might I (the customer) leave things unspecified? One of two reasons: 1. I know what I want, I just forgot to say it (or thought it was obvious), or 2. I don t know what I want. Be sensitive to this distinction. You can t negotiate in case #1, but you might be able to influence the answer in case #2. For example, in a business setting you might point out that implementing X will take a month, but Y can be built in a week. Is Y just as good?