Full Transcript

Review of C/C++ Concepts: Core Programming Constructs Overview of C/C++ • C++ is a superset of the C language – Learning C++ implies learning C • The language has been designed so that it can be easily compiled to assembly and then to machine code. – Assembly and C can be seamlessly intermixed wi...

Review of C/C++ Concepts: Core Programming Constructs Overview of C/C++ • C++ is a superset of the C language – Learning C++ implies learning C • The language has been designed so that it can be easily compiled to assembly and then to machine code. – Assembly and C can be seamlessly intermixed with each other • Gives maximum flexibility to tap into the power of the CPU • However, power comes with a price – C is the fastest high level language around today • C++ is very close – Very mature and most standardized – More portable and interoperable than Java or Python – Thousands of libraries and tools are available. C++ – Java Overlap • Java is an indirect derivative of C/C++ • Java has been derived from C++ which is an extension of C – – – – Most of the syntax and semantics are similar Primitive data types are pretty identical Conditional and looping constructs are the same Function calls operate in a similar manner • There are differences too – C++ is strongly object oriented • Has concept of classes, methods, and other Object-Oriented philosophy – Concepts of pointers (or memory references) are deeply rooted in the C++ language – The language permits explicit control of memory management • Requires some care when used • We will not be using the C++ garbage collector Programming Paradigms • A variety of programming paradigms are supported by C++ – Imperative (aka procedural) programming • Standard programming paradigm in which statements are used to define changes to a program’s state (memory, devices etc.) • Most object-oriented programs fall under this category – Declarative programming • State desired action without stipulating how the action is to be performed. – Functional programming • Programs are defined as mathematical functions • Does not use state (global variables) or mutable data (variables) – Functions work only with arguments passed to them • It can be viewed as declarative programming Programming Paradigms (Contd.) • A variety of programming paradigms are supported by C++ (Contd.) – Generic Programming • Programs are written in terms of abstract types (or “types to be defined-later“) when the program is actually instantiated to run • Accomplished via templates in C++ – Metaprogramming • Programs that write or manipulate other programs (or themselves) as their data, or that do part of the work at compile time that would otherwise be done at runtime – Parallel programming • Automatic multithreading using OpenMP C++ programs • A C++ program essentially consists of a collection of interacting functions and methods • In C there are no methods; instead they are all functions – Methods/functions are subprograms – They accept parameters and may return values • Functions are described in two parts – Declaration: Merely defines the signature of a function » Signature includes the name of the method, parameters to the method and its return value » Declarations are optional but it is a good practice to have them in a program. – Definition: Consists of the signature and the body of the function » The body of a function contains the actual statements to implement the desired functionality » The body of a function must be placed between a set of flower brackets {} – Every program must have a main() function (it is not a method) • The main() function is typically the first function that is executed • The main() function may call other functions to perform various operations Libraries • Many standard operations are performed using C++ libraries – Including standard input and output – Mathematical operations – Other specialized operations • C++ libraries are used by importing them into a program by including suitable header files – Header files are C++ source code files that have only the declaration for various functions – Header files are included by using the #include compiler directive A Skeleton C++ program #include <iostream> int main(); Include the standard C++ I/O streams header file. This provides declaration for various I/O functions. Declaration for main function. Note the missing body and trailing semicolon (;). The main method must return an integer to the caller as per convention. It can optionally accept 2 or 3 parameters. int main() { Single line comments // Body of the main method // Declare local variables. // Place various C statements here. return 0; Definition for the main function. This } skeleton function simply returns 0 (zero) to the caller as per convention. Hello World (hello.cpp) /* include standard I/O functions library that provides definition for the standard output stream that must be used to display some data on the console.*/ #include <iostream> Multi-line comment. Begins with /* and ends with */ int main() { std::cout << “Hello World!\n”; return 0; } Insert the c-string “Hello World!\n” into standard output stream. All the data placed within double quotes (“”) is considered a cstring. Compiling and Running on Linux • Like all operating systems Linux is a C/C++ program – It is compiled using the GNU Compile Collection (GCC) – We will use GCC for compiling C/C++ programs in this course • C++ program are compiled to binary files and run directly on the native hardware without any virtual machines • Specifically we will use the executable named g++ as shown below $ g++ -std=c++11 hello.cpp –o hello $ ./hello Source file name Executable name (can be anything) Flag to select C++ 2011 standard. In Older versions of g++ the flag is --std=c++0x. Program Compilation Flow Language Source Code Preprocessor Revised Source Code Handles directives like #include etc. Standard Library (Collection of object files) (glibc) Compiler Assembly (Text file) Object File (binary) Assembler (GNU as) Linker (GNU ld) Executable (binary) Program Execution Hardware Function calls to OS are termed as “System calls” or “syscalls” Executable Program (binary) OS Loader (ldd) OS Kernel Standard Libraries (glibc) In-memory Binary Code Process Standard Library (Collection of object files) (glibc) Loader dynamically links programs & libraries together into one process. Drivers Signed Data types • The following primitive data types are similar to their Java counterparts – 2’s complement is used for their representation Data type Size char 1 byte Range -128 to +127 short 2 bytes -32,768 to +32,767 int / long float 4 bytes -2,147,483,648 to +2,147,483,647 4 bytes ±3.4E ± 38 (7 digits) double 8 bytes ± 1.7E ± 308 (15 digits) Unsigned Data types • The following primitive data types that are not available in Java. – Unsigned binary representation is used. Data type unsigned char Size 1 byte Range 0 to 255 unsigned short 2 bytes 0 to +65,535 unsigned int unsigned long 4 bytes 0 to +4,294,967,295 Boolean datatype • C++ provides a bool data type that is similar to Java’s boolean data type – C++ uses reserved words true and false for the boolean constants • Note that C language does not have an explicit Boolean data type – Integer value 0 is used to represent false – All other values represent true – You can pretty much use any primitive, integer data type for Boolean • Usually unsigned char data type is used. Strings in C++ • Similar to Java C++ provides a string object – The class std::string is close to java.lang.String • The most appropriate class is std::wstring • The std::wstring handles Unicode characters • For this class prefer std::string. – In C strings are treated as array of characters • C is not an object-oriented language – The std::string class handles transformations to-and-from C-strings – Refer to online documentation on std::string for various methods #include <iostream> #include <string> int main() { std::string str = “Hello World”; std::cout << str.substr(1, 5) << std::endl; return 0; This program prints: } ello Mathematical Expressions • Mathematical expressions and operators are identical in C++ and Java. – Rules of precedence, data type promotion, and type casting are identical #include <iostream> double PI = 3.142; A global variable accessible to all functions & methods in a given source file. int main() { int radius = 2; int volume = (int) (4 * PI * radius * radius / 3.0); char c = ‘A’; /* c = 65, ASCII code of ‘A’ */ int i = 1; return 0; } Operator Precedence Operators Description ++ -- Postfix/Prefix increment & decrement [] Array subscript . -> Element selection by reference and via pointer + - Unary plus and minus !~ Logical NOT and bit-wise NOT * Dereference a address/pointer & Obtain reference/pointer << >> & ^ && | || Bitwise left shift and right shift Bitwise AND, XOR, and OR Logical AND and OR ? : Ternary conditional operator , Multiple expression separator Hello World (hello.cpp) /* Mix and match printf and std::cout is handy for formatted output. However, the correct approach for formatted output is to use IOS flags. */ Header that defines C-style printf #include <iostream> #include <stdio.h> int main() { std::cout << “Hello World!\n”; printf(“Hello World!\n”); return 0; Java-type printf available in C/C++. This printf } is the same as System.out.printf() method in Java. Escape Sequences • Special representation for special characters – Indicated by a backslash (\) – Character followed by \ is interpreted as a special character – Escape sequences can be used as a part of format specifier and printf honors them. printf(“ \’Quote\’ ”); printf(“\\ back \\”); // Displays ‘Quote’ // Displays \ back \ Escape Sequences Sequence Description \” Double quote \’ Single quote \\ Blackslash itself \n New line. Go to start of next line. \r Go to start of current line \t Tab. 1-8 whitespaces to next stop. Formatted output with streams • In C++ stream oriented output is preferred – Prefer to use stream insertion operator operator<< for writing human-readable data • May it be to console or file • Use parameteric manipulators to format output – Parameteric manipulators are defined in iomanip header • Use to change number representation (decimal/octal/ hexadecimal) • Use to change justification and fill • Use to change precision for floating point numbers Parametric manipulation example #include  <iostream>   #include  <iomanip>   #include  <cmath>     int  main()  {      const  int  val  =  70;      std::cout  <<  "octal        :  "  <<  std::oct  <<  val  <<  std::endl                          <<  "hexal        :  "  <<  std::hex  <<  val  <<  std::endl                          <<  "decimal    :  "  <<  std::dec  <<  val  <<  std::endl;      std::cout  <<  "bool          :  "  <<  true                        <<  std::endl                          <<  "boolalpha:  "  <<  std::boolalpha    <<  true                            <<  std::endl;      std::cout  <<  "PI  (full):  "  <<  M_PI                        <<  std::endl                          <<  "PI              :  "  <<  std::setprecision(3)                            <<  M_PI  <<  std::endl;          return  0;   }   Output: octal : hexal : decimal : bool : boolalpha: PI (full): PI : 106 46 70 1 true 3.14159 3.14 Literal Constants • Constants can have type suffixes to illustrate the desired data types • Remember default is int for whole numbers and double for fractions – Examples • long Literal constants: -1L, 24534L, 2344556L • float Literal constants: -1F, 24.534F, 23.566F Choosing a Numerical data Type • When choosing numerical data types always prefer the smaller one – Save space in computer’s memory – Operations on smaller types are usually faster • Choice is determined by application needs – Have to know or decide what is the largest and smallest value that will be stored in a variable – Examples • • • • Data type for age (in years) of a child: unsigned har Data type for a persons weight (in pounds): short Data type for salary of a person: float Data type for π3 : double Numerical Data type compatibility • Value assigned to a variable must be compatible with its data type – Invalid statement: int i = 2.3; • Compiler will flag this as an error and will not compile your program – Smaller numbers can be automatically assigned to larger numerical data types • Such conversions are called widening conversions – They are automatically done by the compiler • char → short → int → long → float → double – Assigning larger data types to smaller ones requires explicit type casting • int x = (int) 3.142; • Such conversions are called narrowing conversions Type Casting • Used to force the compiler to perform assignments • Must be carefully used – Results in loss of information or data (values are always truncated and never rounded) • Avoid as much as possible • Can cast variables, constants, and expressions – Double check if you really need it, when you use it float x = (float) 1; // not necessary int y = 1.1; // error int z = (int) 1.1; // works, z=1 int a = (int) x; // necessary Type Promotion • Used to determine data type of an expression – Numeric expressions take the data type of the largest entity in the expression • Precedence plays a role! • Promotion is applied just before a mathematical operation is performed. – Automatically done by the compiler int x = -10; float pi = 3.142f; int k = x * 0.5; // ERROR (assign double to int) float f = pi * x * x; int j = x * pi; // ERROR (cannot assign float to int) Standard Input • Standard Input is performed via the standard input stream std::cin /* cin is standard input typically tied to keyboard input.*/ #include <iostream> int main() { std::cout << "Enter your full name: "; std::string name; Reads multiple words (until newline) getline(std::cin, name); std::cout << "Enter your age: "; int age; std::cin >> age; std::cout << "Hello " << name << "! You are " << age << " years old.\n"; return 0; } Program Output (user inputs in green): Enter your full name: Hal Enter your age: 10 Hello Hal! You are 10 years old. Conditional statements • Standard syntax for if...else statements: #include <iostream> int main() { int a = 10, if (a < b) std::cout } else { std::cout } return 0; } b = 20; { << “a is less than b\n”; << “a is *not* less than b\n”; Ternary operator • Ternary operator (?:) provides a shortcut for conditional expression – Use it sparingly in code for simple selections – Comes in handy to initialize constants int i; std::cin >> i; std::cout << ((i < 0) ? "Negative" : "Positive") << std::endl; Conditional statements (String Comparison) • C++ provides operators for std::string comparison as if they were numbers. #include <iostream> #include <string> int main() { std::cout << "Enter two words: "; std::string word1, word2; std::cin >> word1 >> word2; std::cout << "The words are " << (word1 == word2 ? "" : "not ") << "equal\n"; } std::cout << "First word is " << (word1 < word2 ? "" : "not ") << "lexicographically lower than second word.\n"; return 0; switch Statement • Switch statement is pretty similar to Java – Can be used only with primitive types int value; switch (value) { case 1: /* Do stuff for 1 */ break; case 2: /* Do stuff for 2 */ break; default: /* Do stuff when value is not 1 or 2 */ } Looping Constructs • The following looping constructs are similar in C and Java • The difference is all loop variables must be predefined – for int i; for(i = 0; (i < 100); i++) { /* do something */ } – While while (i < 100) { /* do something */ i++; } – do..while do { i++; } while (i < 100); Loop Example #include <iostream> int main() { // Print first 10 integers in reverse int number; for (number = 10; (number > 0); number--) { std::cout << number << std::endl; } Output of this program is: return 0; 10 9 } 8 7 6 5 4 3 2 1 Word Count #include <iostream> int main(int argc, char *argv[]) { int count = 0; std::string word; // Loop until End-Of-File (EOF) while (std::cin >> word) { if (word == argv[1]) { count++; } } std::cout << "Occurrences of " << argv[1] << ”: " << count << std::endl; return 0; $ ./word_count } Press Ctrl+D (right after pressing ENTER) to input logical End-Of-File (EOF) one testing one two thee one two buckle my shoe Occurrences of one: 2 Nested Loops • Loops and conditional statements can be nested within each other (indefinitely): – You have to choose the appropriate type of nesting based on the type of logic you are trying to implement: // Prints a triangle of *s on the console #include <iostream> int main() { int row, col; for(row = 1; (row < 5); row++) { for(col = 0; (col < row); col++) { std::cout << "*”; Output of this program is: } * std::cout << std::endl; ** } *** return 0; **** } Functions/Methods • Functions and Methods in C++ are similar in nature to methods in Java – Functions are methods that are not part of a class • C language is not object oriented and does not use methods – Parameters to functions must be defined – Primitive types are typically passed by value • They may also be passed by reference in C++ – Complex data types (such as arrays & objects) are typically passed by reference. • C/C++ requires prototype declaration for functions and methods – In certain cases only – Rule-of-thumb: Define prototypes for all functions at the beginning of the source code. Example /* const for parameters guarantees the caller that this method will not change the value of the parameters*/ unsigned char isFactor1(const int number, const int factor) { int0)main() { if ((number % factor) == { if (isFactor2(15129, 123)) { return 1; // true printf(“True!”); } } return 0; // false } } unsigned char isFactor2(const int number, const int factor) { return ((number % factor) == 0); } Function Prototypes • A function prototype is simply the declaration of the function without any body – The body of the function is defined elsewhere • Possibly even in a different source file – Handy for recursive functions / methods – Examples: unsigned char isFactor1(const int number, const int factor); void display(const int number); Recursion • Functions and methods can call each other to accomplish recursion – Self recursion • Function calls itself – Mutual recursion • Two functions call each other int factorial(int num) { return (num <= 1) ? 1 : num * factorial(num - 1); } int isEven(int); bool isOdd(int num) { return (num == 0) ? false : isEven(abs(num) - 1); } bool isEven(int num) { return (num == 0) ? true : isOdd(abs(num) - 1); } Passing objects by reference #include <iostream> #include <string> #include <cctype> void upperRef(std::string& str) { for(unsigned i = 0; (i < str.length()); i++) { str[i] = toupper(str[i]); } } Program Output: THIS IS A TEST int main() { std::string test = "This is a test"; Function call changes value of test! upperRef(test); std::cout << test << std::endl; return 0; } Passing objects by value #include <iostream> #include <string> #include <cctype> std::string upperObj(std::string str) { for(unsigned i = 0; (i < str.length()); i++) { str[i] = toupper(str[i]); } return str; Program Output: THIS IS A TEST } This is a test int main() { std::string test = "This is a test"; std::cout << upperObj(test) << std::endl; std::cout << test << std::endl; return 0; }

Use Quizgecko on...
Browser
Browser