C++ Programming_CHA5:指针、数组和结构

基本定义

数组

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;
}











猜你喜欢

转载自blog.csdn.net/ttt95101/article/details/80377584