for 语句,while 语句 与 C语言相同,略
递增(++)/(- -)递减运算符这两个运算符都有两个变体,如:x++;++x . 两个版本对 *** 作数的影响是一样的,但影响的时间不同。就像先付款后到货 ;先到货后付款一样。
下面看一个简单的程序:
#includeint main() { using std :: cout; int a = 20; int b = 20; cout << "a = " << a << ": b = " << b << "n"; cout << "a++ = " << a++ << ": ++b = " << ++b << "n"; cout << "a = " << a << ": b = " << b << "n"; return 0; }
运行结果:
a = 20: b = 20
a++ = 20: ++b = 21
a = 21: b = 21
粗略的讲,a++ 意味着使用 a 的当前值计算表达式,然后将 a 的值加 1 ; 而 ++b 的意思是先将 b 的值加 1 ,然后使用新的值来计算表达式。
例如,有下面的关系:
int x = 5; int y = ++x; // change x, then assign to y // y is 6 , x is 6 int z = 5; int y = z++; //assign to y, then change z // y is 5 , z is 6递增/递减运算符和指针
将递增运算符用于指针时,将把指针的值增加其指向的数据类型占用的字节数,这种规则适用于对指针的递增和递减:
double arr[5] = {21.1,32.8,23.4,45.2,37.4}; double *pt = arr; // pt points to arr[0] ,i.e. to 21.1 ++pt; // pt poionts to arr[1] ,i.e. to 32.8
也可以结合使用这些运算符和 *运算符来修改指针指向的值。将* 和 ++ 同时用于指针时提出了这样的问题:将什么解除引用,将什么递增。这取决于运算符的位置和优先级。前缀~和解除引用运算符的优先级相同,以从右到左的方式进行结合。后缀~比解除引用优先级高,以从左到右的方式进行结合。
所以 *++pt 的含义如下:先将 ++ 应用于pt (因为 ++ 位于 * 的右边),然后将 * 应用于被递增后的pt :(下面的语句都是根据上面的程序独立进行)
double x = *++pt; // arr[1] or 32.8
另一方面, ++*pt 意味着先取得 pt 指向的值,然后将这个值加1 :
double x = ++*pt; // arr[0]+1
圆括号对指针解除引用,然后得到21.1,然后值加1 得 22.1:
double x = (*pt)++ ; // arr[0]+1
最后看这个组合:
#includeint main() { using namespace std; double arr[5] = {21.1,32.8,23.4,45.2,37.4}; double *pt = arr; // pt points to arr[0] ,i.e. to 21.1 // pt poionts to arr[1] ,i.e. to 32.8 double x = *pt++ ; // arr[0]+1 cout << x<< " " << *pt < 后缀运算符 ++ 用于 pt 而不是 *pt。
用while 语句 编写延时循环:// waiting.cpp #include#include // describes clock() function int main() { using namespace std; cout << "Enter the delay time , in seconds: "; float secs; cin >>secs; clock_t delay = secs * CLOCKS_PER_SEC; cout << "Startingan"; clock_t start = clock(); while (clock() - start < delay); cout << "donean"; return 0; } do-while循环与C语言相同,略。
第五章 分支语句和逻辑运算符 字符函数库 cctype这玩意能有多方便呢?
例如之前判断 ch 是不是字符的时候 :
if((ch >= 'a' && ch <= 'z') || (ch >= 'A' && ch <= 'Z'))现在:
if(isalpha(ch))是不是感觉之前学了个寂寞...Hhhhhhhh
cctype中的字符函数:isalnum()如果参数是字母或数字,返回true isalpha()如果参数是字母,返回true iscntrl()如果参数是控制字符,返回true isdigit()如果参数是数字(0-9) , 返回true isgraph()如果参数是除空格之外的打印字符,返回true islower~~小写字母,返回true isprint()~~打印字符(包括空格),返回true ispunct() ~~标点符号,~~
isspace() ~~空白字符,~~
isupper()~~大写字母,~~ isxdigit()十六进制数字,~~ tolower()如果参数是大写字符,则返回小写,否则返回原参数 toupper()如果参数是小写字符,则返回大写,否则返回原参数 ?: 运算符 通用格式: expression1 ? expression2 : expression3
如果 expression1 为 true ,则整个条件表达式的值是 expression2 的值,否则为expression3的值
int c = a > b ? a : b; // 与下面语句等效 int c; if (a > b){ c = a; }else{ c = b; }break 与continue 语句与C语言相同,略。
第六章 函数——C++ 的编程模块 复习函数的基本知识
函数参数和按值传递
C++ 通常按值传递参数。用于接收传递值的变量被称为形参,传递给函数的值被称为实参。
如果在main()中声明了一个名为 num的变量,同时在另一个函数也声明一个名为 num的变量,他们却完全不同。
下面看一个程序:
// twoarg.cpp #includeusing namespace std; void nchars(char,int); int main() { int times; char ch; cout << "Enter a character: "; cin >> ch; while(ch != 'q') { cout << "Enter a integer: "; cin >> times; nchars(ch,times); cout << "nEnter another character or " << "press the q-key to quit: "; cin >> ch; } cout << "The value of times is " << times << ".n"; cout << "Bye.n"; return 0; } void nchars(char c,int n) { while(n-- > 0) { cout << c; } } 说明在函数中修改形参的值不会影响调用程序中的数据。
函数和数组函数是处理更复杂的数据类型(如数组和结构)的关键。首先,考虑函数接口所涉及的内容。函数需要知道要对哪个数组进行累计,因此需要将数组作为参数传递给它。为使函数通用,而不限于特定长度的数组,还需要传递数组长度。这里唯一的新内容是:需要将一个形参声明为数名。 下面来看看一个函数头及其它部分:
int arr(int sum[],int n);这看起来合理,但方括号指出 sum是一个数组,而方括号则表明,可以将任何长度的数组传递给该函数。但实际情况并非如此:sum实际上不是数组,而是指针。 所以可以用 int *sum 代替 int sum[ ] .
函数如何使用指针来处理数组在大多数情况下,C++将数组名视为指针。数组名解释为其第一个元素的地址:
sum == &sum[ 0 ] ;
该规则有些例外。首先,数组声明使用数组名来标记存储位置;其次,对数组名使用 sizeof 将得到整个数组的长度(以字节为单位);将地址运算符& 作用于数组名时,将返回整个数组的地址。
如果像我一样傻傻分不清,可以记这两个:
sum[i] == *(sum + i) ; &sum[i] == sum+i ; //将指针包括数组名 加 1,实际上是加上一个与指针指向的类型的长度(以字节为单位)相等的值。 //对于遍历数组而言,使用指针加法和数组下标是等效的。注意:为将数组类型和元素数量告诉数组处理函数,请通过两个不同的参数来传递他们:
void fabbonain(int arr[],int size);而不要试图使用方括号表示法来传递数组长度:
void fabbonain(int arr[size]);用 const 保护数组使用普通参数时,函数使用的是数据的副本,不会意外地修改普通参数的原始数据;然鹅,接受数组名的函数将使用原始数据,为防止原始数据被无意修改,可这么做:
void fabbonain(const int arr[],int size);个人的理解是:这就是我们在各种网络平台遇到的 " 只读 "。
使用数组区间的函数除了上面所说的用两个参数向函数传递数据,还有另一种给函数提供所需信息的方法,即指定元素区间(range),这可以通过传递两个指针来完成:一个指针标识数组的开头,另一个指针标识数组的尾部。
例如,假设有这样的声明: double sum[ 20 ] ;
则指针 sum 和 sum + 20 定义了区间。首先,数组名 sum 指向第一个元素。表达式 sum + 19 指向最后一个元素(即 sum [19 ]),因此,sum + 20 指向数组结尾后面的一个位置。
指针和const函数和二维数组
例如,假设有如下代码:
int data [3][4] = {{1,2,3,4},{5,6,7,8},{9,10,11,12}}; int total = sum(data,3);则sum()的原型是什么样的呢?函数为何将行数(3)作为参数,而不是列数(4)呢?
data 是一个数组名,该数组有 3 个元素。第一个元素本身是一个数组,由 4 个int 值组成。因此 data 的类型是指向由 4个 int组成的数组的指针,因此正确的原型如下:
int sum(int (*ar2)[4], int size); int sum(int ar2[][4], int size); // 第二种格式更容易理解 // sum()在声明参数ar2时,没有使用const,因为这只能用于基本类型的指针 // 而ar2是指向指针的指针数组表示法和指针表示法互换:
ar2[x][y] = *(*(ar2+x)+y);函数和C风格字符串 将 C风格字符串作为参数的函数(1)char 数组 ;
(2)用引号括起的字符串常量 ;
(3)被设置为字符串的地址的 char 指针 ;
但上述三种选择的类型都是 char 指针,因此可以将其作为字符串处理函数的参数:
#include#include using namespace std; int main() { char ghost[15] = "galloping"; char *str = "galloping"; int n1 = strlen(ghost); int n2 = strlen(str); int n3 = strlen("galloping"); cout << n1 << endl; cout << n2 << endl; cout << n3 << endl; return 0; } // n1,n2,n3 都是 9 C风格字符串与 char 数组之间的一个重要区别是,字符串有内置的结束字符,不以空字符结尾的char数组只是数组,而不是字符串。
返回C风格字符串的函数函数无法返回一个字符串,但可以返回字符串地点地址,这样做效率更高。
下面的程序定义了一个名为 buildstr () 的函数,该函数返回一个指针。该函数接受两个参数:一个字符和一个数字。函数使用 new 创建一个长度与数字参数相等的字符串,将每个元素都初始化为该字符。然后,返回指向新字符串的指针:
#include函数和结构char * buildstr(char c, int n); int main() { using namespace std; int times; char ch; cout << "Enter a character: "; cin >> ch; cout << "Enter a integer: "; cin >> times; char *ps = buildstr(ch,times); cout << ps << endl; delete []ps; ps = buildstr('+', 20); cout << ps << "-Done-" << ps << endl; delete []ps; return 0; } char * buildstr(char c, int n) { char *pstr = new char[n + 1]; pstr[n] = ''; while(n-- > 0) { pstr[n] = c; } return pstr; } // 运行结果: // Enter a character: h // Enter a integer: 10 // hhhhhhhhhh // ++++++++++++++++++++-Done-++++++++++++++++++++ 涉及函数时,结构变量的行为更接近于基本的单值变量,所以为结构编写函数更简单。
下面是一个示例:
#include传递结构的地址struct travel_time { int hours; int mins; }; const int Min_hr = 60; travel_time sum(travel_time t1,travel_time t2); void show_time(travel_time t); int main() { using namespace std; travel_time day1 = {5, 45}; // 5 hours,45 min travel_time day2 = {4, 55}; // 4 hours,55 min travel_time trip = sum(day1, day2); cout << "Two-day total: "; show_time(trip); travel_time day3 = {4, 32}; cout << "Three-day total: "; show_time(sum(trip, day3)); return 0; } travel_time sum(travel_time t1,travel_time t2) { travel_time total; total.mins = (t1.mins + t2.mins) % Min_hr; total.hours = t1.hours + t2.hours + (t1.mins + t2.mins)/Min_hr; return total; } void show_time(travel_time t) { using namespace std; cout << t.hours << " hours, " << t.mins << " minutesn"; } // 运行结果 // Two-day total: 10 hours, 40 minutes // Three-day total: 15 hours, 12 minutes 下面是一个示例:
#include函数和string对象#include struct polar { double distance; double angle; }; struct rect { double x; double y; }; void rect_to_polar(const rect *pxy, polar * pda); void show_polar(const polar * pda); int main() { using namespace std; rect rplace; polar pplace; cout << "Enter the x and y values: "; while (cin >> rplace.x >> rplace.y) { rect_to_polar(&rplace, &pplace); show_polar(&pplace); cout << "Next two numbers (q to quit): "; } cout << "Done.n"; return 0; } void show_polar(const polar * pda) { using namespace std; const double Rad_to_deg = 57.29577951; cout << "distance = " << pda->distance; cout << ", angle = " << pda->angle * Rad_to_deg; cout << " degreesn"; } void rect_to_polar(const rect *pxy,polar * pda) { using namespace std; pda->distance = sqrt(pxy->x * pxy->x + pxy->y * pxy->y); pda->angle = atan2(pxy->y,pxy->x); } // 运算符 -> 是重中之重 如果需要多个字符串,可以声明一个 string 对象数组,并将该数组传递给一个函数以显示其内容。
下面是一个示例:
#include#include using namespace std; const int SIZE = 5; void display(const string sa[], int n); int main() { int i; // 如果需要使用 string 数组,只需使用通常的数组声明格式即可 string list[SIZE]; cout << "Enter your " << SIZE << " favorite astronomical sights:n"; for(i=0; i 函数指针 与数据项相似,函数也有地址。函数的地址是存储其机器语言代码的内存的开始地址。通常,这些地址对用户而言不重要,但对程序却很重要。例如,可以编写将另一个函数的地址作为参数的函数。这样第一个函数将能够找到第二个函数,并运行它。与直接调用另一个函数相比。这很笨拙,但它允许在不同时间传递不同函数的地址,这意味着可以在不同时间使用不同函数。
获取函数的地址:获取函数地址很简单,只使用函数名(后面不跟参数)即可。
例如:
// 有函数process() 和 think() process(think); // 传递的是think()函数的地址 process(think()); // 传递的是think()函数的返回值声明函数指针:声明函数指针应指定函数的返回类型以及函数的特征标(参数列表)。
例如:
double pam(int); double (*pf)(int); // pam 替换为 (*pf) // 由于 pam是函数,因此(*pf)也是函数 // 所以 pf 就是函数指针两者的返回类型和特征标必须相同!
另外,由于括号优先级比 * 高 ,所以:
double (*pf)(int); // pf 是指向函数的指针 double *pf(int); // pf() 是一个返回指针的函数在使用函数指针时,比较棘手的是编写原型。
下面是一个示例:
#include深入探讨函数指针double betsy(int lns) { return 0.05 * lns; } double pam(int lns) { return 0.03 * lns + 0.0004 * lns * lns; } void estimate(int lines, double (*pf)(int)) { using namespace std; cout << lines << " lines will take "; cout << (*pf)(lines) << " hour(s)n"; } int main() { using namespace std; int code; cout << "How many lines of code do you need? "; cin >> code; cout << "Here is Betsy's estimate:n"; estimate(code,betsy); cout << "Here is Pam's estimate:n"; estimate(code,pam); return 0; } 下面通过一个示例演示使用函数指针时面临的一些挑战:
const double * f1(const double ar[],int n); const double * f2(const double [],int); const double * f3(const double *, int); // 这三个函数的特征标实际上是相同的! // ar[] 可简化为 [] // * ar 可简化为 *
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)