基本定义
数组
T[size]就是具有size个T类型元素的数组(类型)。
结构
数组是相同类型的元素的一个聚集。一个struct则是任意类型元素的一个聚集。struct address{
char* name;
char* street;
long zip;
};
结构对象常常通过指针用->运算符访问,如p->name 相当于(*p).name。
结构类型对象的大小未必是其成员的大小之和。
两个结构总是不同的类型,即使它们有相同的成员。
指针
T*就是到类型T的指针
对指针的操作就是间接引用,间接运算符也是*
int* pi;
char** ppc; //到字符的指针的指针
int* api[15]; //15个到int的指针的数组
int (*fp)(char*); //到函数的指针
int* f(char*); //返回int*的函数
常量
const实际上改变了类型,它限制了对象能够使用的方式。
引用
一个引用就是某对象的另一个名字。记法为X&表示到X的引用。
引用必须初始化。
引用最明显的实现方式是作为一个常量指针const*,每次使用的时候都间接访问。这样想象并没有问题,不过一个引用并不是一个对象,不能像指针那样操作。
const T&的初始值不一定是左值,也不一定是类型T的。(临时变量、强制转换)
以常量的引用作为函数参数是非常普遍的应用。
“特殊”指针:
字符串文字常量,如:"this is a example"其类型就是const char[18],最后一个字符是"\0"。
可以将字符串文字常量赋值给char*,不过不能通过指针进行修改。
空指针 0(尽量不要用NULL宏?或使用const int NULL=0;)。
void*:一个指向任何对象类型的指针都可以赋值给类型为void*的指针(反之则不然,必须显示转换)。最重要用途是需要向函数传递一个指针,而又不能对对象的类型做任何假设。还有就是从函数返回一个无类型的对象。要使用这样的对象,必须通过显示的类型转换。
复合情况
到数组的指针
int v[]={1,2,3,4,5,6};
int* p1=v;
int* p2=&v[0];
数组参数被隐式转换到指针后,这也意味着对被调用函数而言,数组的大小信息被丢失了。
常量指针
*const---》常量指针
const char* ccp; //到const char的指针
char const* ccp2; //到const char的指针
char*const cpc; //到char的const指针
--------------------------------------------------------------------------------------
习题:
1、写出如下声明
char* pc; //一个到字符的指针 int ia[10];//一个包含10个整数的数组 int (&ria)[10]=ia;//一个到包含10个整数的数组的引用 string (*ps)[10]//一个到字符串的数组的指针 char** ppc;//一个到字符的指针的指针 const int ci=100;//一个常量整数 const int *pci=PI; //一个到常量整数的指针,PI为const int int const* cpi=itest;//一个到整数的常量指针 int *pi[15]; //15个到整数的指针的数组
3、用typedef去定义如下类型
typedef unsigned char uc;//unsigned char, typedef const unsingned char cuc;//const unsigned char typedef int* ptoi;//到整数的指针 typedef char** ptoptoc;//到字符的指针的指针 typedef char *((*ptoptoca)[10]);//到字符指针的数组的指针 typedef int *ptoi[7];//7个到整数的指针的数组 typedef int *((*ptoi)[7])//到包含7个整数的指针的数组的指针 typedef int *test[7][8]//包含8个数组的数组,其中每个数组包含7个到整数的指针
参见教你如何理解复杂的声明,到现在还有点而晕乎乎的,似懂非懂
5、下面例子中,数组str的大小是多少?
char str[]="a short string"; sizeof(str)=15; //包括一个'\0' strlen(str)=14; //str的长度是多少?
6、如下哪些调用时合法的?哪些调用将导致编译器引进临时变量?
‘a’ | 49 | 3300 | c | uc | sc | |
f(char) | 合法 | 合法 | 非法 | 合法 | 合法? | 合法 |
g(char&) | 非法 | 非法 | 非法 | 合法 | 合法? | 合法 |
h(const char&) | 合法,引入临时变量 | 合法,引入临时变量 | 合法,引入临时变量 | 合法 | 合法 | 合法 |
unsigned char | signed char |
7、定义一个包含一年中各月份的名字和每个月的提案数的表格,分别用两个数组、结构实现。
#include<iostream> using namespace std; int main(){ char *Month[12]={"Jan","Feb","MAR","APR","MAY","JUN","JUL","AUG","SEP","OCT","NOV","DEC"}; int days[12]={31,28,31,30,31,30,31,31,30,31,30,31}; struct sMonth{ char *mon; int days; }; sMonth test[12]; for(int i=0,i<12,i++){ test[i].mon=Month[i]; test[i].days=days[i]; } for(int i=0,i<12,i++) cout<<Month[i]<<'\t'; cout<<endl; for(int i=0,i<12,i++) cout<<Days[i]<<'\t'; cout<<endl; for(int i=0,i<12,i++){ cout<<test[i].mon<<'\t'<<test[i].days<<endl; //数列 } return 0; }
9、找一个例子,其中将一个名字用于它自己的初始式是有意义的。
??不会
10、定义一个字符串的数组,其中的字符串保存的是月份的名字。将这些字符串传递给一个函数打印出来
#include<iostream> #include<string> using namespace std; void printstring(string s[],int n){ for int(i=0,i<n,i++) cout<<s[i]<<endl; } int main(){ string month[12]={"JAN","FEB","MAR",…}; printstring(month,3); return 0; }
11、从输入读一系列单词,使用Quit作为输入的结束单词。按照读入顺序打印出(重复值不打印)。排序后再打印。
//采用了标准库<string>/<vector>,自己写感觉还有点儿费劲 #include<iostream> #include<algorithm> #include<string> #include<vector> using namesapce std; bool ifExist(vector<string> vs,string s){ if(vs.size==0) return false; vector<string>::iterator it = find(vs.begin(), vs.end(), s); if (it != vs.end()) return ture; else return false; } void print(vector<string> vs){ for(int i=0,i<vs.size,i++) cout<<vs[i]<<'\t'; } int main(){ vector<string> vstest; string stest; cout<<"Please input the words and ends with Quit!"<<endl; cin>>stest; while(stest!="Quit"){ if(!ifExist(vstest,stest)) vstest.push_back(stest); //重复的数值不放入vector中 cin>>stest; } print(vstest); sort(vsteest.begin(),vstest.end()); //标准排序函数 print(vstest); return 0; }
12、写一个函数,它统计一个string中一对字母出现的次数。写另一个函数对char*做同样多的事情。
//C风格的字符串的程序未实现 //对于一对字母扩展为可变长度的字符串 #include<iostream> #include<string> using namespace std; int sCount(const string &string1,const string &string2){ int icount=0; int pos=0; while((pos=string1.find(string2,pos))!=string::npos){ icount+=1; cout<<"The position is at "<<pos<<endl; pos+=string2.size(); } return icount; } int main(){ string s1,s2; cout<<"Please input the source string and the substring."<<endl; cin>>s1>>s2; cout<<scount(s1,s2); return 0; }
13、定义一个struct Date以保存日期的轨迹。提供一些函数,从输入读Date,向输出写Date,以及用一个日期去初始化Date。
//此处省略所有对时间合理性的判断 #include <iostream> struct Date{ int year; int month; int day; }; void inputdate(Date &test,int x,int t,int z){ test.year=x; test.month=y; test.day=z; } void outputdate(const Date &test){ cout<<test.year<<'\t'<<test.month<<'\t'<<test.day<<endl; } int main(){ Date today=(1895,4,17);//签订马关条约的日期 output(today); return 0; }