Google
 

Friday, August 27, 2010

Apple Share 1: Memory- Stack Structure of Procedures

 

PPT of the training:

 

Here is the code:

// fib_n_rec main
#include <stdio.h>

int main()
{
int n;
printf("Please input the n for Fibonacci Program:\n");

scanf("%d", &n);

int result = fib_n_rec(n);

printf("The result is %d.\n",result);

return 0;
}
//fib_n_rec
int fib_n_rec(int n)
{
int i = 1;
int val = 1;
int nval = 1;

while (i < n) {
int t = val+nval;
val = nval;
nval = t;
i++;
}

return val;
}
/*fib_n_rec.s*/
.file "fib_n_rec.c"
.text
.globl _fib_n_rec
.def _fib_n_rec; .scl 2; .type 32; .endef
_fib_n_rec:
pushl %ebp
movl %esp, %ebp
subl $16, %esp
movl $1, -16(%ebp)
movl $1, -12(%ebp)
movl $1, -8(%ebp)
jmp L2
L3:
movl -8(%ebp), %edx
movl -12(%ebp), %eax
addl %edx, %eax
movl %eax, -4(%ebp)
movl -8(%ebp), %eax
movl %eax, -12(%ebp)
movl -4(%ebp), %eax
movl %eax, -8(%ebp)
addl $1, -16(%ebp)
L2:
movl -16(%ebp), %eax
cmpl 8(%ebp), %eax
jl L3
movl -12(%ebp), %eax
leave
ret
//fib_rec.c
int fib_rec(int n)
{
int prev_val, val;

if (n <= 2)
return 1;
prev_val = fib_rec(n-2);
val = fib_rec(n-1);
return prev_val + val;
}

//fib_rec_main.c
#include <stdio.h>

int main()
{
int n;
printf("Please input the n for Fibonacci Program:\n");

scanf("%d", &n);

int result = fib_rec(n);

printf("The result is %d.\n",result);

return 0;
}
/*fib_rec.s*/
.file "fib_rec.c"
.text
.globl _fib_rec
.def _fib_rec; .scl 2; .type 32; .endef
_fib_rec:
pushl %ebp
movl %esp, %ebp
subl $24, %esp
cmpl $2, 8(%ebp)
jg L2
movl $1, -20(%ebp)
jmp L3
L2:
movl 8(%ebp), %eax
subl $2, %eax
movl %eax, (%esp)
call _fib_rec
movl %eax, -8(%ebp)
movl 8(%ebp), %eax
subl $1, %eax
movl %eax, (%esp)
call _fib_rec
movl %eax, -4(%ebp)
movl -4(%ebp), %edx
movl -8(%ebp), %eax
addl %edx, %eax
movl %eax, -20(%ebp)
L3:
movl -20(%ebp), %eax
leave
ret
//swapadd.c
int swap_add(int *xp, int *yp)
{
int x = *xp;
int y = *yp;

*xp = y;
*yp = x;
return x + y;
}

int caller(int arg1, int arg2)
{
//int arg1 = 534;
//int arg2 = 1057;
int sum = swap_add(&arg1, &arg2);
int diff = arg1 - arg2;
return sum * diff;
}
//swapadd_main.c

#include <stdio.h>

int main()
{
printf("Please input two not-zero integers:\n");
int arg1 = 0, arg2 = 0;
scanf("%d,%d", &arg1, &arg2);
int result = caller( arg1, arg2);

printf("The result is %d!\n", result);

return 0;
}
/*swapadd.s*/
.file "swapadd.c"
.text
.globl _swap_add
.def _swap_add; .scl 2; .type 32; .endef
_swap_add:
pushl %ebp
movl %esp, %ebp
subl $16, %esp
movl 8(%ebp), %eax
movl (%eax), %eax
movl %eax, -8(%ebp)
movl 12(%ebp), %eax
movl (%eax), %eax
movl %eax, -4(%ebp)
movl 8(%ebp), %edx
movl -4(%ebp), %eax
movl %eax, (%edx)
movl 12(%ebp), %edx
movl -8(%ebp), %eax
movl %eax, (%edx)
movl -4(%ebp), %edx
movl -8(%ebp), %eax
addl %edx, %eax
leave
ret
.globl _caller
.def _caller; .scl 2; .type 32; .endef
_caller:
pushl %ebp
movl %esp, %ebp
subl $24, %esp
leal 12(%ebp), %eax
movl %eax, 4(%esp)
leal 8(%ebp), %eax
movl %eax, (%esp)
call _swap_add
movl %eax, -8(%ebp)
movl 8(%ebp), %edx
movl 12(%ebp), %eax
movl %edx, %ecx
subl %eax, %ecx
movl %ecx, %eax
movl %eax, -4(%ebp)
movl -8(%ebp), %eax
imull -4(%ebp), %eax
leave
ret

Wednesday, August 25, 2010

C++ Primer, Fourth Edition:Reading notes:Chapter 2. Variables and Basic Types

Part I: The Basics

Programming languages have distinctive features that determine the kinds of applications for which they are well suited. They also share many fundamental attributes. Essentially all languages provide:

  • Built-in data types such as integers, characters, and so forth

  • Expressions and statements to manipulate values of these types

  • Variables, which let us give names to the objects we use

  • Control structures, such as if or while, that allow us to conditionally execute or repeat a set of actions

    Functions that let us abstract actions into callable units of computation

    Most modern programming languages supplement this basic set of features in two ways: They let programmers extend the language by defining their own data types, and they provide a set of library routines that define useful functions and data types not otherwise built into the language.

    In C++, as in most programming languages, the type of an object determines what operations can be performed on it.

    In contrast, C++ is a statically typed language; type-checking is done at compile time. As a consequence, the compiler must be told the type of every name used in the program before that name can be used.

    One of the primary design goals of C++ is to let programmers define their own types that are as easy to use as the built-in types. The Standard C++ library uses these features to implement a rich library of class types and associated functions.

    Chapter 2. Variables and Basic Types

    In C++ the support for types is extensive: The language itself defines a set of primitive types and ways in which we can modify existing types. It also provides a set of features that allow us to define our own types.

    2.1. Primitive Built-in Types

    1. The void type has no associated values and can be used in only a limited set of circumstances. The void type is most often used as the return type for a function that has no return value
    2. The size of the arithmetic types varies across machines. By size, we mean the number of bits used to represent the type. The standard guarantees a minimum size for each of the arithmetic types, but it does not prevent compilers from using larger sizes. Indeed, almost all compilers use a larger size for int than is strictly required.
    3. Table 2.1. C++: Arithmetic Types
      1. Table 2.1. C   Arithmetic Types
    4. Because the number of bits varies, the maximum (or minimum) values that these types can represent also vary by machine.

    2.1.1. Integral Types

    1. The arithmetic types that represent integers, characters, and boolean values are collectively referred to as the integral types.
    2. There are two character types: char and wchar_t. The char type is guaranteed to be big enough to hold numeric values that correspond to any character in the machine's basic character set. As a result, chars are usually a single machine byte. The wchar_t type is used for extended character sets, such as those used for Chinese and Japanese, in which some characters cannot be represented within a single char.
    3. The types short, int, and long represent integer values of potentially different sizes. Typically, shorts are represented in half a machine word, ints in a machine word, and longs in either one or two machine words (on 32-bit machines, ints and longs are usually the same size)
    4. Machine-Level Representation of The Built-in Types
      1. The C++ built-in types are closely tied to their representation in the computer's memory. Computers store data as a sequence of bits, each of which holds either 0 or 1.
      2. At the bit level, memory has no structure and no meaning.
      3. The most primitive way we impose structure on memory is by processing it in chunks. Most computers deal with memory as chunks of bits of particular sizes, usually powers of 2.
      4. Although the exact sizes can vary from one machine to another, we usually refer to a chunk of 8 bits as a "byte" and 32 bits, or 4 bytes, as a "word."
      5. Most computers associate a numbercalled an addresswith each byte in memory.
      6. To give meaning to the byte at address 736425, we must know the type of the value stored there. Once we know the type, we know how many bits are needed to represent a value of that type and how to interpret those bits.
    5. Signed and Unsigned Types
      1. The integral types, except the boolean type, may be either signed or unsigned. As its name suggests, a signed type can represent both negative and positive numbers (including zero), whereas an unsigned type represents only values greater than or equal to zero.
      2. The integers, int, short, and long, are all signed by default. To get an unsigned type, the type must be specified as unsigned, such as unsigned long. The unsigned int type may be abbreviated as unsigned. That is, unsigned with no other type implies unsigned int.
      3. Unlike the other integral types, there are three distinct types for char: plain char, signed char, and unsigned char. Although there are three distinct types, there are only two ways a char can be represented. The char type is respresented using either the signed char or unsigned char version. Which representation is used for char varies by compiler.
    6. How Integral Values Are Represented
      1. In an unsigned type, all the bits represent the value.
      2. The C++ standard does not define how signed types are represented at the bit level. Instead, each compiler is free to decide how it will represent signed types. These representations can affect the range of values that a signed type can hold. We are guaranteed that an 8-bit signed type will hold at least the values from 127 through 127; many implementations allow values from 128 through 127.
      3. Under the most common strategy for representing signed integral types, we can view one of the bits as a sign bit. Whenever the sign bit is 1, the value is negative; when it is 0, the value is either 0 or a positive number.
    7. Assignment to Integral Types
      1. The type of an object determines the values that the object can hold. This fact raises the question of what happens when one tries to assign a value outside the allowable range to an object of a given type. The answer depends on whether the type is signed or unsigned.
      2. For unsigned types, the compiler must adjust the out-of-range value so that it will fit. The compiler does so by taking the remainder of the value modulo the number of distinct values the unsigned target type can hold.
      3. For the unsigned types, a negative value is always out of range. An object of unsigned type may never hold a negative value. Some languages make it illegal to assign a negative value to an unsigned type, but C++ does not.
      4. Beware: In C++ it is perfectly legal to assign a negative number to an object with unsigned type. The result is the negative value modulo the size of the type. So, if we assign 1 to an 8-bit unsigned char, the resulting value will be 255, which is 1 modulo 256.
      5. When assigning an out-of-range value to a signed type, it is up to the compiler to decide what value to assign. In practice, many compilers treat signed types similarly to how they are required to treat unsigned types. That is, they do the assignment as the remainder modulo the size of the type. However, we are not guaranteed that the compiler will do so for the signed types.

    2.1.2. Floating-Point Types

    1. The types float, double, and long double represent floating-point single-, double-, and extended-precision values.
    2. Typically, floats are represented in one word (32 bits), doubles in two words (64 bits), and long double in either three or four words (96 or 128 bits). The size of the type determines the number of significant digits a floating-point value might contain.
    3. Beware:The float type is usually not precise enough for real programsfloat is guaranteed to offer only 6 significant digits. The double type guarantees at least 10 significant digits, which is sufficient for most calculations.

    2.2. Literal Constants

    1. a literal constant: literal because we can speak of it only in terms of its value; constant because its value cannot be changed. Every literal has an associated type.
    2. Literals exist only for the built-in types. There are no literals of class types. Hence, there are no literals of any of the library types.
    3. Advice: Using the Built-in Arithmetic Types
      1. C++, like C, is designed to let programs get close to the hardware when necessary, and the integral types are defined to cater to the peculiarities of various kinds of hardware. Most programmers can (and should) ignore these complexities by restricting the types they actually use.
      2. In practice, many uses of integers involve counting.When counting in other circumstances, it is usually right to use an unsigned value. Doing so avoids the possibility that a value that is too large to fit results in a (seemingly) negative result.
      3. When performing integer arithmetic, it is rarely right to use shorts. In most programs, using shorts leads to mysterious bugs when a value is assigned to a short that is bigger than the largest number it can hold. What happens depends on the machine, but typically the value "wraps around" so that a number too large to fit turns into a large negative number. For the same reason, even though char is an integral type, the char type should be used to hold characters and not for computation. The fact that char is signed on some implementations and unsigned on others makes it problematic to use it as a computational type.
      4. On most machines, integer calculations can safely use int. Technically speaking, an int can be as small as 16 bitstoo small for most purposes. In practice, almost all general-purpose machines use 32-bits for ints, which is often the same size used for long. The difficulty in deciding whether to use int or long occurs on machines that have 32-bit ints and 64-bit longs. On such machines, the run-time cost of doing arithmetic with longs can be considerably greater than doing the same calculation using a 32-bit int. Deciding whether to use int or long requires detailed understanding of the program and the actual run-time performance cost of using long versus int.
      5. Determining which floating-point type to use is easier: It is almost always right to use double. The loss of precision implicit in float is significant, whereas the cost of double precision calculations versus single precision is negligible. In fact, on some machines, double precision is faster than single. The precision offered by long double usually is unnecessary and often entails considerable extra run-time cost.
    4. Rules for Integer Literals
      1. We can write a literal integer constant using one of three notations: decimal, octal, or hexadecimal. These notations, of course, do not change the bit representation of the value, which is always binary.
      2. Literal integer constants that begin with a leading 0 (zero) are interpreted as octal; those that begin with either 0x or 0X are interpreted as hexadecimal.
      3. By default, the type of a literal integer constant is either int or long. The precise type depends on the value of the literalvalues that fit in an int are type int and larger values are type long. By adding a suffix, we can force the type of a literal integer constant to be type long or unsigned or unsigned long. We specify that a constant is a long by immediately following the value with either L or l (the letter "ell" in either uppercase or lowercase).
      4. TIPS: When specifying a long, use the uppercase L: the lowercase letter l is too easily mistaken for the digit 1.
      5. In a similar manner, we can specify unsigned by following the literal with either U or u. We can obtain an unsigned long literal constant by following the value by both L and U.
      6. There are no literals of type short.
    5. Rules for Floating-Point Literals : 2010.8.23 learning mark
      1. We can use either common decimal notation or scientific notation to write floating-point literal constants.
      2. Using scientific notation, the exponent is indicated either by E or e.
      3. By default, floating-point literals are type double.
      4. We indicate single precision by following the value with either F or f. Similarly, we specify extended precision by following the value with either L or l
      5. 3.14159F .001f 12.345L 0. 3.14159E0f 1E-3F 1.2345E1L 0e0
    6. Boolean and Character Literals
      1. The words true and false are literals of type bool
      2. Printable character literals are written by enclosing the character within single quotation marks:'a'  '2'  ','  ' '  // blank
      3. We can obtain a wide-character literal of type wchar_t by immediately preceding the character literal with an L, as in     L'a'
    7. Escape Sequences for Nonprintable Characters
      1. Some characters are nonprintable.
      2. Nonprintable characters and special characters are written using an escape sequence. An escape sequence begins with a backslash. The language defines the following escape sequences:
      3. An escape sequence begins with a backslash. The language defines the following escape sequences:

          newline

          \n

          horizontal tab

          \t

          vertical tab

          \v

          backspace

          \b

          carriage return

          \r

          formfeed

          \f

          alert (bell) 

          \a

          backslash

          \\

          question mark

          \?

          single quote

          \'

          double quote

          \"

      4. We can write any character as a generalized escape sequence of the form \ooo where ooo represents a sequence of as many as three octal digits. The value of the octal digits represents the numerical value of the character.
      5. The following examples are representations of literal constants using the ASCII character set: \7 (bell) \12 (newline) \40 (blank) \0 (null) \062 ('2') \115 ('M')
      6. The character represented by '\0' is often called a "null character," and has special significance,
      7. We can also write a character using a hexadecimal escape sequence \xddd consisting of a backslash, an x, and one or more hexadecimal digits.
    8. Character String Literals
      1. String literals are arrays of constant characters,
      2. String literal constants are written as zero or more characters enclosed in double quotation marks. Nonprintable characters are represented by their underlying escape sequence.
      3. For compatibility with C, string literals in C++ have one character in addition to those typed in by the programmer. Every string literal ends with a null character added by the compiler.
      4. A character literal 'A'  represents the single character A, whereas “A" represents an array of two characters: the letter A and the null character.
      5. Just as there is a wide character literal, such as L'a' there is a wide string literal, again preceded by L, such as L"a wide string literal" The type of a wide string literal is an array of constant wide characters. It is also terminated by a wide null character.
    9. Concatenated String Literals
      1. Two string literals (or two wide string literals) that appear adjacent to one another and separated only by spaces, tabs, or newlines are concatenated into a single new string literal.
      2. What happens if you attempt to concatenate a string literal and a wide string literal? For example:     std::cout << "multi-line " L"literal " << std::endl; The result is undefinedthat is, there is no standard behavior defined for concatenating the two different types. The program might appear to work, but it also might crash or produce garbage values. Moreover, the program might behave differently under one compiler than under another.
    10. Advice: Don't Rely on Undefined Behavior
      1. Programs that use undefined behavior are in error. If they work, it is only by coincidence. Undefined behavior results from a program error that the compiler cannot detect or from an error that would be too much trouble to detect.
      2. Unfortunately, programs that contain undefined behavior can appear to execute correctly in some circumstances and/or on one compiler. There is no guarantee that the same program, compiled under a different compiler or even a subsequent release of the current compiler, will continue to run correctly. Nor is there any guarantee that what works with one set of inputs will work with another.
      3. Programs should not (knowingly) rely on undefined behavior. Similarly, programs usually should not rely on machine-dependent behavior, such as assuming that the size of an int is a fixed and known value. Such programs are said to be nonportable. When the program is moved to another machine, any code that relies on machine-dependent behavior may have to be found and corrected. Tracking down these sorts of problems in previously working programs is, mildly put, a profoundly unpleasant task.
    11. Multi-Line Literals
      1. There is a more primitive (and less useful) way to handle long strings that depends on an infrequently used program formatting feature: Putting a backslash as the last character on a line causes that line and the next to be treated as a single line.
      2. // ok: A \ before a newline ignores the line break
              std::cou\
              t << "Hi" << st\
              d::endl;
      3. is equivalent to      std::cout << "Hi" << std::endl;
      4. Note that the backslash must be the last thing on the line no comments or trailing blanks are allowed.
      5. Also, any leading spaces or tabs on the subsequent lines are part of the literal.
      6. For this reason, the continuation lines of the long literal do not have the normal indentation.

    Section 2.3.  Variables

    1. Key Concept: Strong Static Typing

      1. C++ is a statically typed language, which means that types are checked at compile time. The process by which types are checked is referred to as type-checking.
      2. In most languages, the type of an object constrains the operations that the object can perform. If the type does not support a given operation, then an object of that type cannot perform that operation.
      3. In C++, whether an operation is legal or not is checked at compile time. When we write an expression, the compiler checks that the objects used in the expression are used in ways that are defined by the type of the objects. If not, the compiler generates an error message; an executable file is not produced.
      4. As our programs, and the types we use, get more complicated, we'll see that static type checking helps find bugs in our programs earlier. A consequence of static checking is that the type of every entity used in our programs must be known to the compiler. Hence, we must define the type of a variable before we can use that variable in our programs.
    2. 2.3.1. What Is a Variable?

      1. A variable provides us with named storage that our programs can manipulate.
      2. Each variable in C++ has a specific type, which determines the size and layout of the variable's memory; the range of values that can be stored within that memory; and the set of operations that can be applied to the variable.
      3. C++ programmers tend to refer to variables as "variables" or as "objects" interchangeably.
      4. Lvalues and Rvalues
        1. there are two kinds of expressions in C++:
        2. lvalue (pronounced "ell-value"): An expression that is an lvalue may appear as either the left-hand or right-hand side of an assignment.
        3. rvalue (pronounced "are-value"): An expression that is an rvalue may appear on the right- but not left-hand side of an assignment.
        4. Variables are lvalues and so may appear on the left-hand side of an assignment. Numeric literals are rvalues and so may not be assigned.
        5. Note: In the course of the text, we'll see a number of situations in which the use of an rvalue or lvalue impacts the behavior and/or the performance of our programsin particular when passing and returning values from a function.
      5. Terminology: What Is an object?
        1. C++ programmers tend to be cavalier in their use of the term object. Most generally, an object is a region of memory that has a type. More specifically, evaluating an expression that is an lvalue yields an object.
        2. Strictly speaking, some might reserve the term object to describe only variables or values of class types. Others might distinguish between named and unnamed objects, always referring to variables when discussing named objects. Still others distinguish between objects and values, using the term object for data that can be changed by the program and using the term value for those that are read-only.
        3. In this book, we'll follow the more colloquial usage that an object is a region of memory that has a type. We will freely use object to refer to most of the data manipulated by our programs regardless of whether those data have built-in or class type, are named or unnamed, or are data that can be read or written.
    3. 2.3.2. The Name of a Variable

      1. The name of a variable, its identifier, can be composed of letters, digits, and the underscore character. It must begin with either a letter or an underscore. Upper- and lowercase letters are distinct: Identifiers in C++ are case-sensitive.
      2. Best Pratices: There is no language-imposed limit on the permissible length of a name, but out of consideration for others that will read and/or modify our code, it should not be too long.
      3. C++ Keywords: C++ reserves a set of words for use within the language as keywords. Keywords may not be used as program identifiers.Table 2.2. C   Keywords
      4. C++ also reserves a number of words that can be used as alternative names for various operators. These alternative names are provided to support character sets that do not support the standard set of C++ operator symbols.
      5. In addition to the keywords, the standard also reserves a set of identifiers for use in the library. Identifiers cannot contain two consecutive underscores, nor can an identifier begin with an underscore followed immediately by an upper-case letter. Certain identifiers those that are defined outside a function may not begin with an underscore.
      6. Conventions for Variable Names
        1. There are a number of generally accepted conventions for naming variables. Following these conventions can improve the readability of a program.
        2. A variable name is normally written in lowercase letters.
        3. An identifier is given a mnemonic name that is, a name that gives some indication of its use in a program, such as on_loan or salary.
        4. An identifier containing multiple words is written either with an underscore between each word or by capitalizing the first letter of each embedded word.
        5. Best Practices: The most important aspect of a naming convention is that it be applied consistently
      7.  

    4. 2.3.3. Defining Objects

      1. Each definition starts with a type specifier, followed by a comma-separated list of one or more names. A semicolon terminates the definition.
      2. The type determines the amount of storage that is allocated for the variable and the set of operations that can be performed on it.
      3. Multiple variables may be defined in a single statement:
      4. Initialization
        1. A definition specifies a variable's type and identifier. A definition may also provide an initial value for the object. An object defined with a specified first value is spoken of as initialized.
        2. C++ supports two forms of variable initialization: copy-initialization and direct-initialization. The copy-initialization syntax uses the equal (=) symbol; direct-initialization places the initializer in parentheses: int ival(1024); // direct-initialization int ival = 1024; // copy-initialization
        3. Beware:Although, at this point in the book, it may seem obscure to the reader, in C++ it is essential to understand that initialization is not assignment. Initialization happens when a variable is created and gives that variable its initial value. Assignment involves obliterating an object's current value and replacing that value with a new one.
        4. Many new C++ programmers are confused by the use of the = symbol to initialize a variable. It is tempting to think of initialization as a form of assignment. But initialization and assignment are different operations in C++. This concept is particularly confusing because in many other languages the distinction is irrelevant and can be ignored. Moreover, even in C++ the distinction rarely matters until one attempts to write fairly complex classes. Nonetheless, it is a crucial concept and one that we will reiterate throughout the text.
        5. Note:There are subtle differences between copy- and direct-initialization when initializing objects of a class type. We won't completely explain these differences until Chapter 13. For now, it's worth knowing that the direct syntax is more flexible and can be slightly more efficient.
      5. Using Multiple Initializers
        1. When we initialize an object of a built-in type, there is only one way to do so: We supply a value, and that value is copied into the newly defined object. For built-in types, there is little difference between the direct and the copy forms of initialization.
        2. For objects of a class type, there are initializations that can be done only using direct-initialization.
      6. Initializing Multiple Variables
        1. When a definition defines two or more variables, each variable may have its own initializer. The name of an object becomes visible immediately, and so it is possible to initialize a subsequent variable to the value of one defined earlier in the same definition. Initialized and uninitialized variables may be defined in the same definition. Both forms of initialization syntax may be intermixed:
    5. 2.3.4. Variable Initialization Rules

      1. When we define a variable without an initializer, the system sometimes initializes the variable for us. What value, if any, is supplied depends on the type of the variable and may depend on where it is defined.
      2. Initialization of Variables of Built-in Type
        1. Whether a variable of built-in type is automatically initialized depends on where it is defined.
        2. Variables defined outside any function body are initialized to zero.
        3. Variables of built-in type defined inside the body of a function are uninitialized.
        4. Using an uninitialized variable for anything other than as the left-hand operand of an assignment is undefined.
        5. Bugs due to uninitialized variables can be hard to find. As we cautioned on page 42, you should never rely on undefined behavior.
        6. Best Practices: We recommend that every object of built-in type be initialized. It is not always necessary to initialize such variables, but it is easier and safer to do so until you can be certain it is safe to omit an initializer.
      3. Caution: Uninitialized Variables Cause Run-Time Problems
        1. Using an uninitialized object is a common program error, and one that is often difficult to uncover. The compiler is not required to detect a use of an uninitialized variable, although many will warn about at least some uses of uninitialized variables. However, no compiler can detect all uses of uninitialized variables.
        2. Sometimes, we're lucky and using an uninitialized variable results in an immediate crash at run time. Once we track down the location of the crash, it is usually pretty easy to see that the variable was not properly initialized.
        3. Other times, the program completes but produces erroneous results. Even worse, the results can appear correct when we run our program on one machine but fail on another. Adding code to the program in an unrelated location can cause what we thought was a correct program to suddenly start to produce incorrect results.
        4. The problem is that uninitialized variables actually do have a value. The compiler puts the variable somewhere in memory and treats whatever bit pattern was in that memory as the variable's initial state. When interpreted as an integral value, any bit pattern is a legitimate valuealthough the value is unlikely to be one that the programmer intended. Because the value is legal, using it is unlikely to lead to a crash. What it is likely to do is lead to incorrect execution and/or incorrect calculation.
      4. Initialization of Variables of Class Type
        1. Each class defines how objects of its type can be initialized. Classes control object initialization by defining one or more constructors
        2. Each class may also define what happens if a variable of the type is defined but an initializer is not provided. A class does so by defining a special constructor, known as the default constructor. This constructor is called the default constructor because it is run "by default;" if there is no initializer, then this constructor is used. The default constructor is used regardless of where a variable is defined.
        3. Most classes provide a default constructor. If the class has a default constructor, then we can define variables of that class without explicitly initializing them.
        4. Some class types do not have a default constructor. For these types, every definition must provide explicit initializer(s). It is not possible to define variables of such types without giving an initial value.
    6. 2.3.5. Declarations and Definitions

      1. In order for multiple files to access the same variable, C++ distinguishes between declarations and definitions.
      2. A definition of a variable allocates storage for the variable and may also specify an initial value for the variable. There must be one and only one definition of a variable in a program.
      3. A declaration makes known the type and name of the variable to the program. A definition is also a declaration: When we define a variable, we declare its name and type.
      4. We can declare a name without defining it by using the extern keyword. A declaration that is not also a definition consists of the object's name and its type preceded by the keyword extern:extern int i; // declares but does not define i int i; // declares and defines i
      5. An extern declaration is not a definition and does not allocate storage. In effect, it claims that a definition of the variable exists elsewhere in the program. A variable can be declared multiple times in a program, but it must be defined only once.
      6. A declaration may have an initializer only if it is also a definition because only a definition allocates storage. The initializer must have storage to initialize. If an initializer is present, the declaration is treated as a definition even if the declaration is labeled extern:extern double pi = 3.1416; // definition
      7. An extern declaration may include an initializer only if it appears outside a function.
      8. Because an extern that is initialized is treated as a definition, any subseqent definition of that variable is an error:
      9. Similarly, a subsequent extern declaration that has an initializer is also an error:
      10. The distinction between a declaration and a definition may seem pedantic but in fact is quite important.
      11. NOTE:In C++ a variable must be defined exactly once and must be defined or declared before it is used.
      12. Any variable that is used in more than one file requires declarations that are separate from the variable's definition. In such cases, one file will contain the definition for the variable. Other files that use that same variable will contain declarations for but not a definition of that same variable.
    7. 2.3.6. Scope of a Name

      1. The context used to distinguish the meanings of names is a scope. A scope is a region of the program. A name can refer to different entities in different scopes.
      2. Most scopes in C++ are delimited by curly braces. Generally, names are visible from their point of declaration until the end the scope in which the declaration appears.
      3. Names defined outside any function have global scope; they are accessible from anywhere in the program.
      4. local scope.
      5. It can be used in that statement but not elsewhere in main. It has statement scope.
      6. Scopes in C++ Nest
        1. Scopes in C++ Nest
          1. Beware:Programs such as the preceeding are likely to be confusing. It is almost always a bad idea to define a local variable with the same name as a global variable that the function uses or might use. It is much better to use a distinct name for the local.
          2. We'll have more to say about local and global scope in Chapter 7 and about statement scope in Chapter 6. C++ has two other levels of scope: class scope, which we'll cover in Chapter 12 and namespace scope, which we'll see in Section 17.2.
    8. 2.3.7. Define Variables Where They Are Used

      1. In general, variable definitions or declarations can be placed anywhere within the program that a statement is allowed. A variable must be declared or defined before it is used.
      2. Best Practices:It is usually a good idea to define an object near the point at which the object is first used.
      3. Defining an object where the object is first used improves readability. The reader does not have to go back to the beginning of a section of code to find the definition of a particular variable. Moreover, it is often easier to give the variable a useful initial value when the variable is defined close to where it is first used.
      4. One constraint on placing declarations is that variables are accessible from the point of their definition until the end of the enclosing block. A variable must be defined in or before the outermost scope in which the variable will be used.
    9.  

    Section 2.4.  const Qualifier

    1. magic number, one whose significance is not evident within the context of its use. It is as if the number had been plucked by magic from thin air.)
    2. The second problem is maintainability.
    3. Defining a const Object
      1. The const type qualifier provides a solution: It transforms an object into a constant.
      2. NOTE:Because we cannot subsequently change the value of an object declared to be const, we must initialize it when it is defined:
    4. const Objects Are Local to a File By Default
      1. Unlike other variables, unless otherwise specified, const variables declared at global scope are local to the file in which the object is defined. The variable exists in that file only and cannot be accessed by other files.
      2. We can make a const object accessible throughout the program by specifying that it is extern:
      3. NOTE:Nonconst variables are extern by default. To make a const variable accessible to other files we must explicitly specify that it is extern

    Section 2.5.  References

    1. A reference serves as an alternative name for an object. In real-world programs, references are primarily used as formal parameters to functions.
    2. In this section we introduce and illustrate the use of references as independent objects.
    3. A reference is a compound type that is defined by preceding a variable name by the & symbol. A compound type is a type that is defined in terms of another type. In the case of references, each reference type "refers to" some other type. We cannot define a reference to a reference type, but can make a reference to any other data type.
    4. A reference must be initialized using an object of the same type as the reference:
    5. A Reference Is an Alias
      1. Because a reference is just another name for the object to which it is bound, all operations on a reference are actually operations on the underlying object to which the reference is bound:
      2. NOTE: When a reference is initialized, it remains bound to that object as long as the reference exists. There is no way to rebind a reference to a different object.
      3. The important concept to understand is that a reference is just another name for an object.
      4. A consequence of this rule is that you must initialize a reference when you define it; initialization is the only way to say to which object a reference refers.
    6. Defining Multiple References
      1. We can define multiple references in a single type definition. Each identifier that is a reference must be preceded by the & symbol:
    7. const References
      1. A const reference is a reference that may refer to a const object:
    8. Terminology: const Reference is a Reference to const: C++ programmers tend to be cavalier in their use of the term const reference. Strictly speaking, what is meant by "const reference" is "reference to const." Similarly, programmers use the term "nonconst reference" when speaking of reference to a nonconst type. This usage is so common that we will follow it in this book as well.
    9. A const reference can be initialized to an object of a different type or to an rvalue (Section 2.3.1, p. 45), such as a literal constant: (The same initializations are not legal for nonconst references. Rather, they result in compile-time errors. The reason is subtle and warrants an explanation.)
      • int i = 42; // legal for const references only const
      • int &r = 42;
      • const int &r2 = r + i;
    10. Allowing only const references to be bound to values requiring temporaries avoids the problem entirely because a const reference is read-only.
    11. NOTE:A nonconst reference may be attached only to an object of the same type as the reference itself.
    12. A const reference may be bound to an object of a different but related type or to an rvalue.

    Section 2.6.  Typedef Names

    1. A typedef lets us define a synonym for a type:
    2. A typedef name can be used as a type specifier:
    3. A typedef definition begins with the keyword typedef, followed by the data type and identifier. The identifier, or typedef name, does not introduce a new type but rather a synonym for the existing data type. A typedef name can appear anywhere in a program that a type name can appear.
    4. Typedefs are commonly used for one of three purposes:
      1. To hide the implementation of a given type and emphasize instead the purpose for which the type is used
      2. To streamline complex type definitions, making them easier to understand

      3. To allow a single type to be used for more than one purpose while making the purpose clear each time the type is used

    Section 2.7.  Enumerations

    1. Enumerations provide an alternative method of not only defining but also grouping sets of integral constants.
    2. Defining and Initializing Enumerations
      1. An enumeration is defined using the enum keyword, followed by an optional enumeration name, and a comma-separated list of enumerators enclosed in braces.
      2.  enum open_modes {input, output, append}; // input is 0, output is 1, and append is 2
    3. Enumerators Are const Values
      1. We may supply an initial value for one or more enumerators. The value used to initialize an enumerator must be a constant expression. A constant expression is an expression of integral type that the compiler can evaluate at compile time. An integral literal constant is a constant expression, as is a const object (Section 2.4, p. 56) that is itself initialized from a constant expression.
      2. An enumerator value need not be unique.
      3. It is not possible to change the value of an enumerator. As a consequence an enumerator is itself a constant expression and so can be used where a constant expression is required.
    4. Each enum Defines a Unique Type
      1. Each enum defines a new type. An object of enumeration type may be initialized or assigned only by one of its enumerators or by another object of the same enumeration type:

    Section 2.8.  Class Types

    1. In C++ we define our own data types by defining a class. A class defines the data that an object of its type contains and the operations that can be executed by objects of that type.
    2. Class Design Starts with the Operations
      1. Each class defines an interface and implementation. The interface consists of the operations that we expect code that uses the class to execute. The implementation typically includes the data needed by the class. The implementation also includes any functions needed to define the class but that are not intended for general use.
      2. When we define a class, we usually begin by defining its interfacethe operations that the class will provide. From those operations we can then determine what data the class will require to accomplish its tasks and whether it will need to define any functions to support the implementation.
    3. Defining the Sales_item Class
      1. A class definition starts with the keyword class followed by an identifier that names the class. The body of the class appears inside curly braces. The close curly must be followed by a semicolon.
      2. Beware:It is a common mistake among new programmers to forget the semicolon at the end of a class definition.
      3. The class body, which can be empty, defines the data and operations that make up the type. The operations and data that are part of a class are referred to as its members.The operations are referred to as the member functions (Section 1.5.2, p. 24) and the data as data members.
      4. The class also may contain zero or more public or private access labels. An access label controls whether a member is accessible outside the class. Code that uses the class may access only the public members.
      5. When we define a class, we define a new type. The class name is the name of that type.
      6. Each class defines its own scope (Section 2.3.6, p. 54). That is, the names given to the data and operations inside the class body must be unique within the class but can reuse names defined outside the class.
    4. Class Data Members
      1. The data members of a class are defined in somewhat the same way that normal variables are defined.
      2. The data members of a class define the contents of the objects of that class type.
      3. There is one crucially important difference between how we define variables and class data members: We ordinarily cannot initialize the members of a class as part of their definition. When we define the data members, we can only name them and say what types they have. Rather than initializing data members when they are defined inside the class definition, classes control initialization through special member functions called constructors
    5. Access Labels
      1. Access labels control whether code that uses the class may use a given member. Member functions of the class may use any member of their own class, regardless of the access level. The access labels, public and private, may appear multiple times in a class definition. A given label applies until the next access label is seen.
      2. The public section of a class defines members that can be accessed by any part of the program. Ordinarily we put the operations in the public section so that any code in the program may execute these operations.
      3. Code that is not part of the class does not have access to the private members.
    6. Using the struct Keyword
      1. C++ supports a second keyword, struct, that can be used to define class types. The struct keyword is inherited from C.
      2. If we define a class using the class keyword, then any members defined before the first access label are implicitly private; ifwe usethe struct keyword, then those members are public.
      3. Whether we define a class using the class keyword or the struct keyword affects only the default initial access level.
      4. There are only two differences between this class definition and our initial class definition: Here we use the struct keyword, and we eliminate the use of public keyword immediately following the opening curly brace. Members of a struct are public, unless otherwise specified, so there is no need for the public label.
      5. NOTE:The only difference between a class defined with the class keyword or the struct keyword is the default access level: By default, members in a struct are public; those in a class are private.

    Section 2.9.  Writing Our Own Header Files

    1. ordinarily class definitions go into a header file.
    2. In fact, C++ programs use headers to contain more than class definitions.
    3. Programs made up of multiple files need a way to link the use of a name and its declaration. In C++ that is done through header files.
    4. To allow programs to be broken up into logical parts, C++ supports what is commonly known as separate compilation. Separate compilation lets us compose a program from several files.
    5. 2.9.1. Designing Our Own Headers
      1. A header provides a centralized location for related declarations. Headers normally contain class definitions, extern variable declarations, and function declarations,
      2. Proper use of header files can provide two benefits: All files are guaranteed to use the same declaration for a given entity; and should a declaration require change, only the header needs to be updated.
      3. Some care should be taken in designing headers. The declarations in a header should logically belong together. A header takes time to compile. If it is too large programmers may be reluctant to incur the compile-time cost of including it.
      4. TIPS:To reduce the compile time needed to process headers, some C++ implementations support precompiled header files. For more details, consult the reference manual of your C++ implementation.
      5. Headers Are for Declarations, Not Definitions
        1. When designing a header it is essential to remember the difference between definitions, which may only occur once, and declarations, which may occur multiple times
      6. Compiling and Linking Multiple Source Files
        1. To produce an executable file, we must tell the compiler not only where to find our main function but also where to find the definition of the member functions defined by the Sales_item class. Let's assume that we have two files: main.cc, which contains the definition of main, and Sales_item.cc, which contains the Sales_item member functions. We might compile these files as follows:
          1. $ CC -c main.cc Sales_item.cc # by default generates a.exe # some compilers generate a.out
          2. $ CC -c main.cc Sales_item.cc -o main # puts the executable in main.exe
        2. where $ is our system prompt and # begins a command-line comment. We can now run the executable file, which will run our main program.
        3. If we have only changed one of our .cc source files, it is more efficient to recompile only the file that actually changed. Most compilers provide a way to separately compile each file. This process usually yields a .o file, where the .o extension implies that the file contains object code.
        4. The compiler lets us link object files together to form an executable. On the system we use, in which the compiler is invoked by a command named CC, we would compile our program as follows:

            $ CC -c main.cc              # generates main.o
            $ CC -c Sales_item.cc        # generates Sales_item.o
            $ CC main.o Sales_item.o     # by default generates a.exe;
                                                             # some compilers generate a.out

            # puts the executable in main.exe
            $ CC main.o Sales_item.o -o main

        5. You'll need to check with your compiler's user's guide to understand how to compile and execute programs made up of multiple source files.
        6. Many compilers offer an option to enhance the error detection of the compiler. Check your compiler's user's guide to see what additional checks are available.
      7. Beware:Because headers are included in multiple source files, they should not contain definitions of variables or functions.
      8. There are three exceptions to the rule that headers should not contain definitions: classes, const objects whose value is known at compile time, and inline functions (Section 7.6 (p. 256) covers inline functions) are all defined in headers. These entities may be defined in more than one source file as long as the definitions in each file are exactly the same.
      9. These entities are defined in headers because the compiler needs their definitions (not just declarations) to generate code.
      10. That const objects are defined in a header may require a bit more explanation.
    6. Some const Objects Are Defined in Headers
      1. Recall that by default a const variable (Section 2.4, p. 57) is local to the file in which it is defined. As we shall now see, the reason for this default is to allow const variables to be defined in header files.
      2. Generally speaking, a constant expression is an expression that the compiler can evaluate at compile-time. A const variable of integral type may be a constant expression when it is itself initialized from a constant expression. However, for the const to be a constant expression, the initializer must be visible to the compiler. To allow multiple files to use the same constant value, the const and its initializer must be visible in each file. To make the initializer visible, we normally define such consts inside a header file. That way the compiler can see the initializer whenever the const is used.
      3. There is one important implication of this behavior. When we define a const in a header file, every source file that includes that header has its own const variable with the same name and value.
      4. When the const is initialized by a constant expression, then we are guaranteed that all the variables will have the same value. Moreover, in practice, most compilers will replace any use of such const variables by their corresponding constant expression at compile time. So, in practice, there won't be any storage used to hold const variables that are initialized by constant expressions.
      5. When a const is initialized by a value that is not a constant expression, then it should not be defined in header file. Instead, as with any other variable, the const should be defined and initialized in a source file. An extern declaration for that const should be made in the header, enabling multiple files to share that variable.
    7. 2.9.2. A Brief Introduction to the Preprocessor
      1. The #include facility is a part of the C++ preprocessor. The preprocessor manipulates the source text of our programs and runs before the compiler. C++ inherits a fairly elaborate preprocessor from C. Modern C++ programs use the preprocessor in a very restricted fashion.
      2. A #include directive takes a single argument: the name of a header. The pre-processor replaces each #include by the contents of the specified header. Our own headers are stored in files. System headers may be stored in a compiler-specific format that is more efficient. Regardless of the form in which a header is stored, it ordinarily contains class definitions and declarations of the variables and functions needed to support separate compilation.
    8. Headers Often Need Other Headers
      1. Headers often #include other headers. The entities that a header defines often use facilities from other headers.
      2. Including other headers is so common that it is not unusual for a header to be included more than once in the same source file.
      3. Accordingly, it is important to design header files so that they can be included more than once in a single source file. We must ensure that including a header file more than once does not cause multiple definitions of the classes and objects that the header file defines. A common way to make headers safe uses the preprocessor to define a header guard. The guard is used to avoid reprocessing the contents of a header file if the header has already been seen.
    9. Avoiding Multiple Inclusions
      1. Beware:Names used for preprocessor variables must be unique within the program. Any uses of a name that matches a preprocessor variable is assumed to refer to the preprocessor variable.
      2. To help avoid name clashes, preprocessor variables usually are written in all uppercase letters.
      3. A preprocessor variable has two states: defined or not yet defined. Various preprocessor directives define and test the state of preprocessor variables. The #define directive takes a name and defines that name as a preprocessor variable. The #ifndef directive tests whether the specified preprocessor variable has not yet been defined. If it hasn't, then everything following the #ifndef is processed up to the next #endif.
      4. We can use these facilities to guard against including a header more than once:
               #ifndef SALESITEM_H
          #define SALESITEM_H
          // Definition of Sales_itemclass and related functions goes here
          #endif

      5. Best Practices: Headers should have guards, even if they aren't included by another header. Header guards are trivial to write and can avoid mysterious compiler errors if the header subsequently is included more than once.
      6. This strategy works well provided that no two headers define and use a pre-processor constant with the same name. We can avoid problems with duplicate preprocessor variables by naming them for an entity, such as a class, that is defined inside the header. A program can have only one class named Sales_item. By using the class name to compose the name of the header file and the preprocessor variable, we make it pretty likely that only one file will use this preprocessor variable.

    10. Using Our Own Headers

      1. The #include directive takes one of two forms:
             #include <standard_header>
        #include "my_file.h"

      2. If the header name is enclosed by angle brackets (< >), it is presumed to be a standard header. The compiler will look for it in a predefined set of locations, which can be modified by setting a search path environment variable or through a command line option. The search methods used vary significantly across compilers. We recommend you ask a colleague or consult your compiler's user's guide for further information. If the header name is enclosed by a pair of quotation marks, the header is presumed to be a nonsystem header. The search for nonsystem headers usually begins in the directory in which the source file is located.


    Exercise 2.3~Exercise 2.6::

    // EXE-2.1.cpp : Defines the entry point for the console application.
    #include "stdafx.h"
    #include <iostream>
    using namespace std;
    int main()
    {
    unsigned char a(-1);
    //So, if we assign -1 to an 8-bit unsigned char, the resulting value will be 255, which is 1 modulo 256.
    cout << static_cast<int>(a) << endl;
    //Exercise 2.3:
    //If a short on a given machine has 16 bits then what is the largest number that can be assigned to a short? To an unsigned short?
    short lowerBound = 0x8000;
    short upperBound = 0x7FFF;
    unsigned short upperBoundOfUnsigned = 0xFFFF;

    cout << "The upper bound of signed short is " << upperBound << endl;
    cout << "The lower bound of signed short is " << lowerBound << endl;
    cout << "The upper bound of unsigned short is " << upperBoundOfUnsigned << endl;

    //Exercise 2.4:
    //What value is assigned if we assign 100,000 to a 16-bit unsigned short? What value is assigned if we assign 100,000 to a plain 16-bit short?
    //When the value to be signed is out range, the PC will get the lower bits with the variable type's length;
    //Here the PC will cut the value as 2bytes, 16bits;
    //1000000 in HEX is 0xF4240, and the lower 16bits is 0x4240. The 0x4240 in dec is 16960.
    //So the signed and unsigned short will both get the 16960 value for the sign bit of the 0x4240 is zero;
    signed short val1 = 1000000; // expected 16990, but actually is 16960; why?
    unsigned short val2 = 1000000; // expected 16975 why it is 16960
    cout << "The value of signed short with the 1000000 is " << val1 << endl;
    cout << "The value of unsigned short with the 1000000 is " << val2 << endl;

    // Here try assign the 1032768 ( 0xFC240) assign to signed and unsigned short;
    // The lower 16bits is 0xC240. For the sign bit is 1, so it will get different value;
    val1 = 1032768;
    val2 = 1032768;
    cout << "The value of signed short with the 1032768 is " << val1 << endl;
    cout << "The value of unsigned short with the 1032768 is " << val2 << endl;

    return 0;
    }

    Exercise 2.9:



  • 1024f is ilegal, 1024.0f works;



  • 3.14UL, the UL is not defined, 3.14L works;


    Exercise 2.10:

    #include "stdafx.h"
    #include <iostream>
    using namespace std;

    int main()
    {
    //Using escape sequences, write a program to print 2M followed by a newline. Modify the program to print 2, then a tab, then an M, followed by a newline.

    cout << "2M\n" ;
    cout << "2\tM\n";

    return 0;
    }

    Exercise 2.11:

    #include "stdafx.h"
    #include <iostream>
    using namespace std;

    int main()
    {
    //Write a program that prompts the user to input two numbers, the base and exponent. Print the result of raising the base to the power of the exponent.
    cout << "Please input the base and exponent(be care the sequence):" << endl;
    int base, exponent;
    cin >> base >> exponent;
    int product(1);
    for (int i = 0; i < exponent ; ++i)
    {
    product*=base;
    }
    cout << "The result is :" << product << endl;
    return 0;
    }


    Exercise 2.30:

    Define the data members of classes to represent the following types:

         (a) a phone number            (b) an address
    (c) an employee or a company (d) a student at a university



    Exercise 2.33:


    Determine what options your compiler offers for increasing the warning level. Recompile selected earlier programs using this option to see whether additional problems are reported.

    ?


  • Sunday, August 22, 2010

    C++ Primer, Fourth Edition: Reading notes:Chapter 1. Getting Started

    This chapter introduces most of the basic elements of C++: built-in, library, and class types; variables; expressions; statements; and functions. Along the way, we'll briefly explain how to compile and execute a program.

    Having read this chapter and worked through the exercises, the reader should be able to write, compile, and execute simple programs.

    Learning a new programming language requires writing programs.

    1.1. Writing a Simple C++ Program

    1. The operating system uses the value returned by main to determine whether the program succeeded or failed. A return value of 0 indicates success.
    2. A function definition specifies four elements: the return type, the function name, a (possibly empty) parameter list enclosed in parentheses, and the function body. The main function may have only a restricted set of parameters.
    3. The main function is special in various ways, the most important of which are that the function must exist in every C++ program and it is the (only) function that the operating system explicitly calls.
      1. The main function is required to have a return type of int, which is the type that represents integers.
      2. The main function may have only a restricted set of parameters.
    4. On most systems, the return value from main is a status indicator.
      1. A return value of 0 indicates the successful completion of main.
      2. Any other return value has a meaning that is defined by the operating system.
      3. Usually a nonzero return indicates that an error occurred. Each operating system has its own way of telling the user what main returned
    5. How you compile a program depends on your operating system and compiler.
    6. The suffix for C++ program files depends on which compiler you're running. Other conventions include:prog1.cxx   prog1.cpp     prog1.cp     prog1.C
    7. Invoking the GNU or Microsoft Compilers
      1. By default the command to invoke the GNU compiler is g++: $ g++ prog1.cc -o prog1
      2. The Microsoft compilers are invoked using the command cl: C:\directory> cl -EHsc prog1.cpp
    8. Running the Compiler from the Command Line
      1. UNIX compilers tend to put their executables in a file named a.out. To run an executable we supply that name at the command-line prompt:   $ a.exe
      2. On UNIX systems you sometimes must also specify which directory the file is in, even if it is in the current directory. In such cases, we would write $ ./a.exe
      3. The value returned from main is accessed in a system-dependent manner. On both UNIX and Windows systems, after executing the program, you must issue an appropriate echo command.
        1. On UNIX systems, we obtain the status by writing     $ echo $? 
        2. To see the status on a Windows system, we write    C:\directory> echo %ERRORLEVEL%
    9. Exercises Section 1.1.1
    10. compile and run

    Note:

    1. Semicolons mark the end of most statements in C++.

    1.2. A First Look at Input/Output

    Fundamental to the iostream library are two types named istream and ostream, which represent input and output streams, respectively. A stream is a sequence of characters intended to be read from or written to an IO device of some kind. The term "stream" is intended to suggest that the characters are generated, or consumed, sequentially over time.

    1. Standard Input and Output Objects
      1. The library defines four IO objects.
      2. cin (pronounced "see-in"). This object is also referred to as the standard input.
      3. cout (pronounced "see-out"). It is often referred to as the standard output.
      4. The library also defines two other ostream objects, named cerr and clog (pronounced "see-err" and "see-log," respectively).The cerr object, referred to as the standard error, is typically used to generate warning and error messages to users of our programs.The clog object is used for general information about the execution of the program.
    2. A Program that Uses the IO Library
        #include <iostream>
        using namespace std;
        int main()
        {
        cout << "Please enter two numbers:" << endl;
        // the input should initialzie as 0, else
        // when the input the not integer, the sum will be redomly
        //int v1,v2;
        int v1(0),v2(0);
        cin >> v1 >> v2;
        // can be used like this style
        // The both style works same
        //cin >> v1 >> v2;
        //cin >> v1;
        //cin >> v2;

        cout << "The sum of "
        << v1
        << " and "
        << v2
        << " is "
        << v1 + v2
        << "."
        << endl;
        return 0;
        }

    3. The first line of our program is a preprocessor directive: #include <iostream>;which tells the compiler that we want to use the iostream library. The name inside angle brackets is a header. Every program that uses a library facility must include its associated header. The #include directive must be written on a single linethe name of the header and the #include must appear on the same line. In general, #include directives should appear outside any function. Typically, all the #include directives for a program appear at the beginning of the file.
    4. endl is a special value, called a manipulator, that when written to an output stream has the effect of writing a newline to the output and flushing the buffer associated with that device. By flushing the buffer, we ensure that the user will see the output written to the stream immediately.
    5. The prefix std:: indicates that the names cout and endl are defined inside the namespace named std. Namespaces allow programmers to avoid inadvertent collisions with the same names defined by a library.
    6. Key Concept: Initialized and Uninitialized Variables

      1. Initialization is an important concept in C++ and one to which we will return throughout this book.
      2. Initialized variables are those that are given a value when they are defined.
      3. When we define a variable, we should give it an initial value unless we are certain that the initial value will be overwritten before the variable is used for any other purpose. If we cannot guarantee that the variable will be reset before being read, we should initialize it


    Note



    1. When writing a C++ program, in most places that a space appears we could instead use a newline. One exception to this rule is that spaces inside a string literal cannot be replaced by a newline. Another exception is that spaces are not allowed inside preprocessor directives.

     


    1.3. A Word About Comments




      1. Comments help the human readers of our programs. They are typically used to summarize an algorithm, identify the purpose of a variable, or clarify an otherwise obscure segment of code. Comments do not increase the size of the executable program. The compiler ignores all comments.
      2. Too many comments intermixed with the program code can obscure the code. It is usually best to place a comment block above the code it explains.
      3. Comments should be kept up to date as the code itself changes. Programmers expect comments to remain accurate and so believe them, even when other forms of system documentation are known to be out of date. An incorrect comment is worse than no comment at all because it may mislead a subsequent reader.

    1.4. Control Structures



    1. 1.4.1. The while Statement

      1. while (condition) while_body_statement;
      2. A while executes by (repeatedly) testing the condition and executing the associated while_body_statement until the condition is false.
      3. the compound assignment operator, (the += operator). This operator adds its right-hand operand to its left-hand operand.
      4. the prefix increment operator (the ++ operator). The increment operator adds one to its operand.
      5. Key Concept: Indentation and Formatting of C++ Programs

        1. C++ programs are largely free-format, meaning that the positioning of curly braces, indentation, comments, and newlines usually has no effect on the meaning of our programs.
        2. Endless debates occur as to the right way to format C or C++ programs. Our belief is that there is no single correct style but that there is value in consistency. We tend to put the curly braces that delimit functions on their own lines. We tend to indent compound input or output expressions so that the operators line up,
        3. The important thing to keep in mind is that other ways to format programs are possible. When choosing a formatting style, think about how it affects readability and comprehension. Once you've chosen a style, use it consistently.


    2. 1.4.2. The for Statement

      1. In pre-Standard C++ names defined in a for header were accessible outside the for itself. This change in the language definition can surprise people accustomed to using an older compiler when they instead use a compiler that adheres to the standard.
      2. Compilation Revisited: The following are the most common kinds of errors a compiler will detect.

        1. Syntax errors.
        2. Type errors.
        3. Declaration errors. Every name used in a C++ program must be declared before it is used. Failure to declare a name usually results in an error message.
        4. An error message contains a line number and a brief description of what the compiler believes we have done wrong. It is a good practice to correct errors in the sequence they are reported. Often a single error can have a cascading effect and cause a compiler to report more errors than actually are present. It is also a good idea to recompile the code after each fixor after making at most a small number of obvious fixes. This cycle is known as edit-compile-debug.


    3. 1.4.3. The if Statement
    4. 1.4.4. Reading an Unknown Number of Inputs
        #include <iostream>
        using namespace std;

        int main()
        {
        cout << "Please enter all numbers that you want to sum (just use ctrl+z to end your input sequence):" << endl;
        int val(0),sum(0);
        while( cin >> val)
        {
        sum += val;
        }
        cout << "The sum is " << sum << endl;
        // Issue :
        // when running how can I input end-of-file character on the screen to end the input?
        return 0;
        }


    5. When we use an istream as a condition, the effect is to test the state of the stream. If the stream is validthat is, if it is still possible to read another input then the test succeeds. An istream becomes invalid when we hit end-of-file or encounter an invalid input, such as reading a value that is not an integer. An istream that is in an invalid state will cause the condition to fail
    6. Entering an End-of-file from the Keyboard:Operating systems use different values for end-of-file. On Windows systems we enter an end-of-file by typing a control-z simultaneously type the "ctrl" key and a "z." On UNIX systems, including Mac OS-X machines, it is usually control-d.

    1.5. Introducing Classes



    1. In C++ we define our own data structure by defining a class. The class mechanism is one of the most important features in C++. In fact, a primary focus of the design of C++ is to make it possible to define class types that behave as naturally as the built-in types themselves.
    2. To use a class we need to know three things:

      1. What is its name?
      2. Where is it defined?
      3. What operations does it support?

    3. 1.5.1. The Sales_item Class

      1. Conventionally, class types are stored in a file with a name that, like the name of a program source file, has two parts: a file name and a file suffix. Usually the file name is the same as the class defined in the header. The suffix usually is .h, but some programmers use .H, .hpp, or .hxx.
      2. Key Concept: Classes Define Behavior

        1. As we go through these programs that use Sales_items, the important thing to keep in mind is that the author of the Sales_item class defined all the actions that can be performed by objects of this class. That is, the author of the Sales_item data structure defines what happens when a Sales_item object is created and what happens when the addition or the input and output operators are applied to Sales_item objects, and so on.
        2. In general, only the operations defined by a class can be used on objects of the class type. For now, the only operations we know we can peeform on Sales_item objects are the ones listed on page 21.

      3. A member function is a function that is defined by a class. Member functions are sometimes referred to as the methods of the class.
      4. Member functions are defined once for the class but are treated as members of each object. We refer to these operations as member functions because they (usually) operate on a specific object. In this sense, they are members of the object, even though a single definition is shared by all objects of the same type.
      5. When we call a member function, we (usually) specify the object on which the function will operate. This syntax uses the dot operator (the "." operator)
      6. The dot operator applies only to objects of class type: The left-hand operand must be an object of class type; the right-hand operand must name a member of that type.
      7. Unlike most other operators, the right operand of the dot (".") operator is not an object or value; it is the name of a member.


    1.6. The C++ Program


    Exercises Section:


    Exercise 1.3:

    #include <iostream>
    using namespace std;
    int main()
    {
    cout << "Hello world!" << endl;
    return 0;
    }
    Exercise 1.4:
    #include <iostream>
    using namespace std;

    int main()
    {
    cout << "Please enter two numbers:" << endl;
    int a(0),b(0);

    cin >> a >> b;

    cout << "The product of " << a << " and " << b << " is " << a * b << endl;
    return 0;
    }

    Exercise 1.5:


    Exercise 1.6:

    	// should be the following
    std::cout << "The sum of " << v1
    << " and " << v2
    << " is " << v1 + v2
    << std::endl;
    Exercise 1.8:
    #include <iostream>

    int main()
    {
    std::cout << "/*";
    std::cout << "*/";
    // the third is incorrect!
    //std::cout << /* "*/" */;

    return 0;
    }
    Exercise 1.9:
    #include <iostream>
    using namespace std;
    int main()
    {
    int sum = 0;
    for (int i = -100; i <= 100; ++i)
    {
    sum += i;
    }
    cout << "The sum is " << sum << endl;
    return 0;
    }

    Exercise 1.10:

    #include<iostream>
    using namespace std;

    int main()
    {
    int sum(0),i(50);
    while(i<=100)
    {
    sum+=i;
    i++;
    }
    cout<<"The sum from 50 to 100 is "<< sum <<endl;
    return 0;
    }

    //#include <iostream>
    //using namespace std;
    //
    //int main()
    //{
    // int sum(0);
    // for (int i = 50 ;i <= 100; ++i )
    // {
    // sum +=i;
    // }
    // cout << "The sum from 50 to 100 is " << sum << endl;
    // return 0;
    //}


    Exercise 1.11:

    #include <iostream>
    using namespace std;

    int main()
    {
    for (int i = 10 ; i >= 0 ; --i)
    {
    cout << i << endl;
    }
    //int i(10);
    //while(i >=0)
    //{
    // cout << i-- << endl;
    //}
    return 0;
    }
    Exercise 1.12:

    Exercise 1.16:

    #include<iostream>
    using namespace std;

    int main()
    {
    cout << "Please enter two numbers:" << endl;
    int v1(0),v2(0);
    cin >> v1 >> v2;

    int larger(0);
    if(v1 > v2)
    {
    larger = v1;
    }
    else if ( v1 == v2)
    {
    cout << "The two numbers " << v1 << " and " << v2 << " are equal!";
    return 0;
    }
    else
    {
    larger = v2;
    }
    cout << "The bigger is " << larger << " of the two numbers " << v1 << " and " << v2 << endl;
    return 0;
    }

    Exercise 1.17:

    #include <iostream>
    using namespace std;

    //Write a program to ask the user to enter a series of numbers.
    //Print a message saying how many of the numbers are negative numbers.

    int main()
    {
    cout << "Please enter a series of numbers:" << endl;
    int val(0);
    int times(0);
    while(cin >> val)
    {
    if(val < 0)
    {
    times++;
    }
    }
    cout << "There are totally " << times << " negative numbers!" << endl;
    return 0;
    }
    Exercise 1.18:
    //Write a program that prompts the user for two numbers and writes each number in the range specified by the two numbers to the standard output.

    #include <iostream>
    using namespace std;

    int main()
    {
    cout << "Please input the range:" << endl;
    int lower(0),larger(0);
    cin >> lower >> larger;
    if(lower > larger)
    {
    int tmp = lower;
    lower = larger;
    larger = tmp;
    }
    cout << "The numbers in the range of the two numbers " << lower << " and " << larger << " are:" << endl;
    for ( int val = lower; val <= larger;++val)
    {
    cout << val << endl;
    }
    return 0;
    }
    Exercise 1.19:
    Exercise 1.20:
    //Write a program to sum the numbers in a user-specified range, omitting the if test that sets the upper and lower bounds. Predict what happens if the input is the numbers 7 and 3, in that order. Now run the program giving it the numbers 7 and 3, and see if the results match your expectation. If not, restudy the discussion on the for and while loop until you understand what happened.
    #include <iostream>
    int main()
    {
    std::cout << "Enter two numbers:" << std::endl;
    int v1, v2;
    std::cin >> v1 >> v2; // read input
    // use smaller number as lower bound for summation
    // and larger number as upper bound
    int lower(v1), upper(v2);
    //if (v1 <= v2) {
    // lower = v1;
    // upper = v2;
    //} else {
    // lower = v2;
    // upper = v1;
    //}
    int sum = 0;
    // sum values from lower up to and including upper
    for (int val = lower; val <= upper; ++val)
    sum += val; // sum = sum + val

    std::cout << "Sum of " << lower
    << " to " << upper
    << " inclusive is "
    << sum << std::endl;
    return 0;
    }
    Exercise 1.21:
    #include <iostream>
    #include "Sales_item.h"
    using namespace std;

    /*
    The Web site (http://www.awprofessional.com/cpp_primer) contains a copy of Sales_item.h in the Chapter 1 code directory. Copy that file to your working directory. Write a program that loops through a set of book sales transactions, reading each transaction and writing that transaction to the standard output.
    */

    int main()
    {
    Sales_item item;
    int max(100);
    Sales_item itemArray[100];
    int times(0);
    while(cin >> item && times < max)
    {
    //cout<< item1 << endl;
    itemArray[times++] = item;
    }
    cout << "All your input are:" << endl;
    cout << "Totally " << times << " Sales items" <<endl;
    while(times >= 0)
    {
    cout << itemArray[times--] << endl;
    }
    return 0;
    }
    Exercise 1.22:
    //Write a program that reads two Sales_item objects that have the same ISBN and produces their sum.
    #include <iostream>
    #include "Sales_item.h"
    using namespace std;

    int main()
    {
    cout << "Please enter two same sales item:" << endl;
    Sales_item item1 , item2;
    cin >> item1 >> item2;

    if( item1.same_isbn(item2))
    {
    cout << "The sum of " << item1 << " and " << item2 << " is " << item1 + item2 << endl;
    }
    else
    {
    cout << "Your input are not the same ISBN!" << endl;
    }
    return 0;
    }
    Exercise 1.23:
    //Write a program that reads several transactions for the same ISBN. Write the sum of all the transactions that were read.
    #include "Sales_item.h"
    #include <iostream>
    using namespace std;

    int main()
    {
    cout << "Please input your sales item to sum:" << endl;
    Sales_item trans, sum;
    int times(1);
    if(cin >> sum)
    {
    while(cin >> trans)
    {
    if(sum.same_isbn(trans))
    {
    sum += trans;
    times++;
    }
    else
    {
    cout << "Your input must the same as your first input ISBN!" << endl;
    sum = trans;
    }
    }
    cout << "Totally " << times << " items you have entered!" << endl;
    cout << "The sum is " << sum << endl;
    }
    else
    {
    cout << "No data!" << endl;
    return -1;
    }
    return 0;
    }
    Exercise 1.24:
    /*
    Write a program that reads several transactions. For each new transaction that you read, determine if it is the same ISBN as the previous transaction, keeping a count of how many transactions there are for each ISBN. Test the program by giving multiple transactions. These transactions should represent multiple ISBNs but the records for each ISBN should be grouped together.

    */

    #include "Sales_item.h"
    #include <iostream>
    using namespace std;

    int main()
    {
    cout << "Please input your sales item to sum:" << endl;
    Sales_item trans, sum;
    int times(1);
    if(cin >> sum)
    {
    while(cin >> trans)
    {
    if(sum.same_isbn(trans))
    {
    sum += trans;
    }
    else
    {
    cout << "Your input must the same as your first input ISBN!" << endl;
    // I don't think here the sum should be updated!
    //sum = trans;
    }
    times++;
    }
    cout << "Totally " << times << " items you have entered!" << endl;
    cout << "The sum is " << sum << endl;
    }
    else
    {
    cout << "No data!" << endl;
    return -1;
    }
    return 0;
    }
    Exercise 1.25:?
    Exercise 1.26:?