1. Trang chủ
  2. » Công Nghệ Thông Tin

Microsoft Visual C++ Windows Applications by Example phần 2 doc

43 332 0

Đang tải... (xem toàn văn)

Tài liệu hạn chế xem trước, để xem đầy đủ mời bạn chọn Tải xuống

THÔNG TIN TÀI LIỆU

Thông tin cơ bản

Định dạng
Số trang 43
Dung lượng 473,16 KB

Các công cụ chuyển đổi và chỉnh sửa cho tài liệu này

Nội dung

This function takes an integer and returns its square.In the example above, the parameter n in Square is called a formal parameter, and the value 3 in Square called in main is called an

Trang 1

In the examples above, it is not strictly necessary to surround the output statements with brackets However, it would be necessary in the case of several statements

In this book, brackets are always used The brackets and the code in between is called

if (i = 1) // Always true.

{

//

}

One way to avoid the mistake is to swap the variable and the value As a value can

be compared but not assigned, the compiler will issue an error message if you by mistake enter one equals sign instead of two signs

default statement can be omitted, and we can only have one default alternative However, it must not be placed at the end of the switch statement, even though it is considered good practice to do so

Trang 3

Iteration Statements

Iteration statements iterate one statement (or several statements inside a block)

as long as certain condition is true The simplest iteration statement is the while

statement It repeats the statement as long as the given expression is true The

example below writes the numbers � to �0

We can also use the for statement, which is a more compact variant of the while statement It takes three expressions, separated by semicolons In the code below, the first expression initializes the variable, the repetition continues as long as the second expression is true, and the third expression is executed at the end of each repetition

for (int i = 1; i <= 10; ++i)

Trang 4

for (int i = 1; i <= 10; ++i)

Trang 5

The goto statement is, however, considered to give rise to unstructured code,

so called "spaghetti code" I strongly recommend that you avoid the goto

statement altogether

Expression Statements

An expression can form a statement

a = b + 1; // Assignment operator.

cout << "Hello, World!"; // Stream operator.

WriteNumber(5); // Function call.

In the above examples, we are only interested in the side effects; that a is assigned a new value or that a text or a number is written We are allowed to write expression statements without side effects; even though it has no meaning and it will probably

be erased by the compiler

a + b * c;

Functions

A function can be compared to a black box We send in information (input) and we

receive information (output) In C++, the input values are called parameters and the output value is called a return value The parameters can hold every type, and the

return value can hold every type except the array

Trang 6

To start with, let us try the function Square This function takes an integer and returns its square.

In the example above, the parameter n in Square is called a formal parameter, and the

value 3 in Square called in main is called an actual parameter.

Let us try a more complicated function, SquareRoot takes a value of double type and returns its square root The idea is that the function iterates and calculates increasingly better root values by taking the mean value of the original value divided with the current root value and the previous root value The process continues until the difference between two consecutive root values has reached an acceptable tolerance Just like main, a function can have local variables dRoot and dPrevRoot

hold the current and previous value of the root, respectively

#include <iostream>

using namespace std;

double SquareRoot(double dValue)

{

const double EPSILON = 1e-12;

double dRoot = dValue, dOldRoot = dValue;

while (true)

{

dRoot = ((dValue / dRoot) + dRoot) / 2;

cout << dRoot << endl;

if ((dOldRoot - dRoot) <= EPSILON)

Trang 7

void PrintSign(int iValue)

There is no problem if the execution of a void function reaches the end of the code,

it just jumps back to the calling function However, a non-void function shall always return a value before reaching the end of the code The compiler will give a warning

if it is possible to reach the end of a non-void function

Local and Global Variables

There are four kinds of variables Two of them are local and global variables, which

we consider in this section The other two kinds of variables are class fields and exceptions, which will be dealt with in the class and exception sections of the

next chapter

Trang 8

A global variable is defined outside a function and a local variable is defined inside

cout << "Global variable: " << iGlobal // 1

<< ", Local variable: " << iLocal // 2

<< endl;

}

A global and a local variable can have the same name In that case, the name in the function refers to the local variable We can access the global variable by using two colons (::)

int iNumber = 1;

void main()

{

int iNumber = 2;

cout << "Global variable: " << ::iNumber // 1

<< ", Local variable: " << iNumber; // 2

cout << "Global variable: " << ::iNumber // 1

<< ", Local variable: " << iNumber; // 3

}

}

Trang 9

Global variables are often preceded by g_ in order to distinguish them from local variables.

int g_iNumber = 1;

void main()

{

int iNumber = 2;

cout << "Global variable: " << g_iNumber // 1

<< ", Local variable: " << iNumber; // 3

}

Call-by-Value and Call-by-Reference

Say that we want to write a function for switching the values of two variables

int iNum1 = 1, iNum2 = 2;

cout << "Before: " << iNum1 << ", " << iNum2 << endl;

Swap(iNum1, iNum2);

cout << "After: " << iNum1 << ", " << iNum2 << endl;

}

Unfortunately, this will not work; the variables will keep their values The

explanation is that the values of iFirstNum and iSecondNum in main are copied into

iNum1 and iNum2 in Swap Then iNum1 and iNum2 exchange values with the help if

iTemp However, their values are not copied back into iFirstNum and iSecondNum

in main

Trang 10

The problem can be solved with reference calls Instead of sending the values of the

actual parameters, we send their addresses by adding an ampersand (&) to the type

As you can see in the code, the Swap call in main is identical to the previous one without references However, the call will be different

int iFirstNum = 1, iSecondNum = 2;

cout << "Before: " << iFirstNum << ", " << iSecondNum

Trang 11

In this case, we do not send the values of iFirstNum and iSecondNum, but rather their addresses Therefore, iNum1 and iNum2 in Swap does in fact contain the

addresses of iFirstNum and iSecondNum of main As in the reference section above,

we illustrate this with dashed arrows Therefore, when iNum1 and iNum2 exchange values, in fact the values of iFirstNum and iSecondNum are exchanged

A similar effect can be obtained with pointers instead of references In that

case, however, both the definition of the function as well as the call from main are different

int iFirstNum = 1, iSecondNum = 2;

cout << "Before: " << iFirstNum << ", " << iSecondNum

Trang 12

In this case, pNum1 and pNum2 are pointers, and therefore drawn with continuous lines Apart from that, the effect is the same.

Default Parameters

A default parameter is a parameter that will be given a specific value if the call does not include its value In the example below, all three calls are legitimate In the first call, iNum2 and iNum3 will be given the values 9 and 99, respectively; in the second call, iNum3 will be given the value 99 Default values can only occur from the right

in the parameter list; when a parameter is given a default value, all the following parameters must also be given default values

cout << Add(1) << endl; // 1 + 9 + 99 = 109

cout << Add(1, 2) << endl; // 1 + 2 + 99 = 102

cout << Add(1, 2 ,3) << endl; // 1 + 2 + 3 = 6

}

Trang 13

Several different functions may be overloaded, which means that they may have

the same name as long as they do not share exactly the same parameter list C++

supports context-free overloading, the parameter lists must differ, it is not enough

to let the return types differ The languages Ada and Lisp support context-dependent

overloading, two functions may have the same name and parameter list as long as they have different return types

cout << Add(1) << endl; // 1

cout << Add(1, 2) << endl; // 1 + 2 = 3

cout << Add(1, 2 ,3) << endl; // 1 + 2 + 3 = 6

}

Static Variables

In the function below, iCount is a static local variable, which means that it is initialized when the execution of the program starts It is not initialized when the function is called

Trang 14

If iCount was a regular local variable (without the keyword static), the function would at every call write that the function has been called once as iCount would be initialized to zero at every call.

The keyword static can, however, also be used to define functions and global variables invisible to the linker and other object files.invisible to the linker and other object files.nvisible to the linker and other object files

Recursion

A function may call itself; it is called recursion In the following example, the

mathematical function factorial (n!) is implemented It can be defined in two ways

The first definition is rather straightforward The result of the function applied to a

positive integer n is the product of all positive integers up to and including n.

int Factorial(int iNumber)

An equivalent definition involves a recursive call that is easier to implement

int Factorial(int iNumber)

Trang 15

Definition and Declaration

It's important to distinguish between the terms definition and declaration For a

function, its definition generates code while the declaration is merely an item of

information to the compiler A function declaration is also called a prototype.

When it comes to mutual recursion (two functions calling each other), at least the second of them must have a prototype to avoid compiler warnings I recommend that you put prototypes for all functions at the beginning of the file In the following example, we use two functions to decide whether a given non-negative integer is even or odd according to the following definitions

bool Even(int iNum);

bool Odd(int iNum);

bool Even(int iNum)

Trang 16

If we use prototypes together with default parameters, we can only indicate the default value in the prototype, not in the definition.

Higher Order Functions

A function that takes another function as a parameter is called a higher order function

Technically, C++ does not take the function itself as a parameter, but rather a pointer

to the function However, the pointer mark (*) may be omitted The following example takes an array of the given size and applies the given function to each integer in the array

Trang 17

// Doubles every value in the array.

ApplyArray(numberArray, iArraySize, Double);//2,4,6,8,10

PrintArray(numberArray, iArraySize);

// Squares every value in the array.

ApplyArray(numberArray, iArraySize, Square);//4,16,36,64,100

PrintArray(numberArray, iArraySize);

}

One extra point in the example above is the method of finding the size of an array;

we divide the size of the array with the size of its first value This method only works

on static arrays, not on dynamically allocated arrays or arrays given as parameters to functions A parameter array is in fact converted to a pointer to the type of the array The following two function definitions are by definition equivalent

void PrintArray(int intArray[], int iSize)

The main() Function

The main program is in fact a function; the only special thing about it is that it is the start point of the program execution Just like a regular function it can have

formal parameters and return a value However, the parameter list must have a

special format The first parameter iArgCount is an integer indicating the number of arguments given by the system The second parameter vpValues (vp stands for vector

of pointers) holds the arguments It is an array of pointers to characters, which can

be interpreted as an array of strings, holding the system arguments However, the first value of the array always holds the path name of the program In some tutorials, the traditional parameter names argc and argv are used instead iArgCount and

vpValues The program below writes its path name and its arguments

#include <iostream>

using namespace std;

int main(int iArgCount, char* vpValues[])

Trang 18

cout << "Path name: " << vpValues[0] << endl;

The arguments can be input from the command prompt

The return value of the main function can (besides void) only be signed or unsigned int The return value is often used to return an error code to the operating system; usually, zero indicates ok and a negative value indicates an error The program below tries to allocate a large chunk of memory It returns zero if it turns out well, minus one otherwise

#include <cstdlib>

int main()

{

const int BLOCK_SIZE = 7FFFFFFF;

void* pBlock = new (nothrow) char[BLOCK_SIZE];

The preprocessor is a tool that precedes the compiler in interpreting the code The

#include directive is one of its parts It opens the file and includes its text So far,

we have only included system header files, whose names are surrounded by arrow brackets (< and >) Later on, we will include our own header files Then we will use parentheses instead of arrow brackets The difference is that the preprocessor looks for the system header files in a special system file directory while it looks for our

Trang 19

Another part of the preprocessor is the macros There are two kinds: with or without

parameters A macro without parameters works like a constant

#define ARRAY_SIZE 256

int arr[ARRAY_SIZE];

The predefined macros DATE , TIME , FILE , and LINE holds today's date, the current time, the current line number, and the name of the

file, respectively

Macros with parameters act like functions with the difference being that they do not perform any type checking, they just replace the text A macro is introduced with the

#define directive and is often written with capitals

#define ADD(a, b) ((a) + (b))

cout << ADD(1 + 2, 3 * 4) << endl; // 15

One useful macro is assert, it is defined in the header file cassert It takes a

logical parameter and exits the program execution with an appropriate message

if the parameter is false exit is a standard function that aborts the execution of the program and returns an integer value to the operating system When a macro definition stretches over several lines, each line except the last one must end with

a backslash

#define assert(test) \

{ \

if (!(test)) \

{ \

cout << "Assertion: \"" << #test << "\" on line " \ << LINE << " in file " << FILE << "."; \ ::exit(-1); \

} \

}

In the error handling section of the next chapter, we will define an error checking macro displaying the error message in a message box

It is also possible to perform conditional programming by checking the value of

macros In the following example, we define a system integer according to the underlying operating system

#ifdef WINDOWS

#define SYSINT int

#endif

#ifdef LINUX

#define SYSINT unsigned int

#endif

Trang 21

Let's revise the points quickly in brief as discussed in this chapter:

The text of a program is called its source code It is translated into target code by the compiler The target code is then linked to target code of other programs, finally resulting in executable code.

The basic types of C++ can be divided into the integral types char, short int, int, and long int, and the floating types float, double, and long double The integral types can also be signed or unsigned.

Values of a type can be organized into an array, which is indexed by an integer The first index is always zero An enum value is an enumeration of named values It is also possible to define new types with typedef, though that

feature should be used carefully

A pointer holds the memory address of another value There are operators to

obtain the value pointed at and to obtain the address of a value A reference

is a simpler version of a pointer A reference always holds the address of a specific value while a pointer may point at different values A pointer

can also be used to allocate memory dynamically; that is, during the

program execution

The operators can be divided into the arithmetic operators addition,

subraction, multiplication, division, and modulo; the relational operators equal to, not equal to, less than, less than or equal to, greater than, and greater than or equal to; the logical operators not, and, and or; the bitwise operators inverse, and, or, and xor; the assignment operators, and the condition operator There is also the operator sizeof, which gives the size in bytes of values of a certain type The statments of C++ can divided into the selection statements if and switch, the iteration statements while and for, and the jump statements break, continue, and goto, even thought goto should be avoided.

A function may take one or more formal parameters as input When it is called,

a matching list of actual parameters must be provided A function may also

return a value of arbitrary type, with the exception of array Two functions

may be overloaded, which means they have the same name, as long as they

differ in their parameter lists A function may call itself, directly or indirectly;

this is called recursion A function can also have default parameters, which

means that if the caller does not provide enough parameters, the missing parameters will be given the default values

A macro is a textual substitution performed by the preprocessor before the

compilation of the program Similar to functions, they may take parameters

We can also include the text of other files into our program Finally, we can

include and exclude certain parts of the code by conditional programming.

Ngày đăng: 12/08/2014, 21:20

TỪ KHÓA LIÊN QUAN