• c++指针,引用,日期,输入输出和数据结构


    1,指针

    指针是一个变量,其值为另一个变量的地址,即,内存位置的直接地址。就像其他变量或常量一样,您必须在使用指针存储其他变量地址之前,对其进行声明。指针变量声明的一般形式为:

    int    *ip;    /* 一个整型的指针 */
    double *dp;    /* 一个 double 型的指针 */
    float  *fp;    /* 一个浮点型的指针 */
    char   *ch;    /* 一个字符型的指针 */

    指针的大小是一样的,都是一个代表内存地址的长的十六进制数。不同数据类型的指针之间唯一的不同是,指针所指向的变量或常量的数据类型不同。

    指针使用实例:

    #include <iostream>
    using namespace std;
    int main ()
    {
    int var = 20; // 实际变量的声明
    int *ip; // 指针变量的声明,只声明未初始化
    ip = &var; // 初始化,在指针变量中存储 var 的地址
    cout << "Value of var variable: ";
    cout << var << endl;    //原变量的值是20
    // 输出在指针变量中存储的地址
    cout << "Address stored in ip variable: ";
    cout << ip << endl;    //输出的是存储的地址,是地址
    // 访问指针中地址的值
    cout << "Value of *ip variable: ";
    cout << *ip << endl;    //加×以后输出的是地址区域对应的内容是值,这叫指针
    return 0;
    }

    指针可以为空:

    在变量声明的时候,如果没有确切的地址可以赋值,为指针变量赋一个 NULL 值是一个良好的编程习惯。赋为 NULL 值的指针被称为指针。

    #include <iostream>
    
    using namespace std;
    
    int main ()
    {
       int  *ptr = NULL;
    
       cout << "ptr 的值是 " << ptr ;
     
       return 0;
    }

    指针的可变的:可加可减

    #include <iostream>
    using namespace std;
    const int MAX = 3;
    int main ()
    {
    int var[MAX] = {10, 100, 200};
    int *ptr;
    // 指针中的数组地址
    ptr = var;
    for (int i = 0; i < MAX; i++)
    {
    cout << "Address of var[" << i << "] = ";
    cout << ptr << endl;
    cout << "Value of var[" << i << "] = ";
    cout << *ptr << endl;
    // 移动到下一个位置
    ptr++;    //指针指向的内存地址是可以通过计算改变的,我估计用的是相似数据存储位置相近原理
    }
    return 0;
    }

    产生的结果如下:

    Address of var[0] = 0x7ffe3c8e3980
    Value of var[0] = 10
    Address of var[1] = 0x7ffe3c8e3984
    Value of var[1] = 100
    Address of var[2] = 0x7ffe3c8e3988
    Value of var[2] = 200

     指针可以比较大小:

    #include <iostream>
    using namespace std;
    const int MAX = 3;
    int main ()
    {
    int var[MAX] = {10, 100, 200};
    int *ptr;
    // 指针默认指向的是数组中的第一个元素,第一个元素的地址,而不是整个数组
    ptr = var;
    int i = 0;
    while ( ptr <= &var[MAX - 1] )    //指针只要比var[2]小就继续向下移动
    {
    cout << "Address of var[" << i << "] = ";
    cout << ptr << endl;
    cout << "Value of var[" << i << "] = ";
    cout << *ptr << endl;
    // 指向上一个位置
    ptr++;    //指针向下一个元素移动,数组中的内存地址是有讲究的,它们按顺序排列,所以可以通过++的方式获取下一个元素
    i++;
    }
    return 0;
    }

    指针数组:

    个人觉得指针数组有两种,一种是创建一个数组用以存储多个指针,如下:

    #include <iostream>
    using namespace std;
    const int MAX = 3;
    int main ()
    {
    int var[MAX] = {10, 100, 200};
    int *ptr[MAX];    //创建一个指针数组,长度为3
    for (int i = 0; i < MAX; i++)
    {
    ptr[i] = &var[i]; // 把指针数组中的元素挨个赋值为var数组中元素的地址
    }
    for (int i = 0; i < MAX; i++)    //遍历指针数组,取值输出
    {
    cout << "Value of var[" << i << "] = ";
    cout << *ptr[i] << endl;
    }
    return 0;
    }


    返回:
    Value of var[0] = 10
    Value of var[1] = 100
    Value of var[2] = 200
     

    另一个是创建一个数组不存储值,而是存储值存放的内存位置:

    #include <iostream>
    using namespace std;
    const int MAX = 4;
    int main ()
    {
    const char *names[MAX] = {    //声明并且初始化一个指针数组
    "Zara Ali",
    "Hina Ali",
    "Nuha Ali",
    "Sara Ali",
    };
    for (int i = 0; i < MAX; i++)
    {
    cout << "Value of names[" << i << "] = ";
    cout << names[i] << endl;    //此处要注意,上一个例子打印出内存地址对应的值用的是:*数组名[索引号],而此处不能这样用,原因不明,但是如果用*name[i]打印出来的将会是ZHNS,首字母,大约是因为指针指向数组的首个吧,但是name[i]为何能打印出值来,就不得而知了
    }
    return 0;
    }


    返回
    Value of names[0] = Zara Ali
    Value of names[1] = Hina Ali
    Value of names[2] = Nuha Ali
    Value of names[3] = Sara Ali

    指针可以指向指针:

    声明:

    int **var;

    实例:

    #include <iostream>
    using namespace std;
    int main ()
    {
    int var;
    int *ptr;
    int **pptr;
    var = 3000;
    // 获取 var 的地址
    ptr = &var;
    // 使用运算符 & 获取 ptr 的地址
    pptr = &ptr;
    // 使用 pptr 获取值
    cout << "var 值为 :" << var << endl;   //3000
    cout << "*ptr 值为:" << *ptr << endl;    //3000
    cout << "**pptr 值为:" << **pptr << endl;    //3000
    return 0;
    }

    指针传递给函数:

    只要声明函数的时候说明是指针就可以了

    #include <iostream>
    #include <ctime>
    using namespace std;
    void getSeconds(unsigned long *par);    //声明了是无符号常整型的指针,也可以传递数组,
    int main ()
    {
    unsigned long sec;
    getSeconds( &sec );    //用的时候传递进去的是地址
    // 输出实际值
    cout << "Number of seconds :" << sec << endl;
    return 0;
    }
    void getSeconds(unsigned long *par)
    {
    // 获取当前的秒数
    *par = time( NULL );    //实际参数会被改变
    return;
    }

    返回:
    Number of seconds :1294450468

    从函数返回指针:

    首先要定义一个返回指针的函数,其次要知道,c++不支持返回纯局部变量,除非局部变量为static

    #include <iostream>
    #include <ctime>
    #include <cstdlib>
     
    using namespace std;
     
    // 要生成和返回随机数的函数
    int * getRandom( )
    {
      static int  r[10];
     
      // 设置种子
      srand( (unsigned)time( NULL ) );
      for (int i = 0; i < 10; ++i)    //数组是长度为10的int数组
      {
        r[i] = rand();
        cout << r[i] << endl;
      }
     
      return r;
    }
     
    // 要调用上面定义函数的主函数
    int main ()
    {
       // 一个指向整数的指针,因为返回的是指针所以返回的值也必须由指针存储
       int *p;
     
       p = getRandom();
       for ( int i = 0; i < 10; i++ )    //数组打印出第一个来就行了
       {
           cout << "*(p + " << i << ") : ";
           cout << *(p + i) << endl;    
       }
     
       return 0;
    }

    2,引用

    引用约等于浅拷贝,是原来的变量的别名,所以引用不能为空,引用不能改变,引用必须在创建的时候被初始化,函数不能返回一个局部变量的引用,static例外

    比如:

    int i = 17;
    int&  r = i;
    //r 是一个初始化为 i 的整型引用

    实例:

    #include <iostream>
    using namespace std;
    int main ()
    {
    // 声明简单的变量
    int i;
    double d;
    // 声明引用变量,引用不可为空说的是引用必须是某个变量的别名
    int& r = i;
    double& s = d;
    i = 5;   
    cout << "Value of i : " << i << endl;
    cout << "Value of i reference : " << r << endl;
    d = 11.7;
    cout << "Value of d : " << d << endl;
    cout << "Value of d reference : " << s << endl;
    return 0;
    }

    函数返回一个引用实例:

    #include <iostream>
    using namespace std;
    double vals[] = {10.1, 12.6, 33.1, 24.1, 50.0};
    double& setValues( int i )    //从函数的声明和初始化就能看出来这个函数要返回的是个引用
    {
    return vals[i]; // 返回第 i 个元素的引用
    }
    // 要调用上面定义函数的主函数
    int main ()
    {
    cout << "改变前的值" << endl;
    for ( int i = 0; i < 5; i++ )
    {
    cout << "vals[" << i << "] = ";
    cout << vals[i] << endl;
    }
    setValues(1) = 20.23; // 改变第 2 个元素
    setValues(3) = 70.8; // 改变第 4 个元素
    cout << "改变后的值" << endl;
    for ( int i = 0; i < 5; i++ )
    {
    cout << "vals[" << i << "] = ";
    cout << vals[i] << endl;
    }
    return 0;
    }

    返回:
    改变前的值
    vals[0] = 10.1
    vals[1] = 12.6
    vals[2] = 33.1
    vals[3] = 24.1
    vals[4] = 50
    改变后的值
    vals[0] = 10.1
    vals[1] = 20.23
    vals[2] = 33.1
    vals[3] = 70.8
    vals[4] = 50

    引用也可以作为参数:

    声明函数的时候这样做就可以了:

    void swap(int& x, int& y);

    3,日期和时间

    c++比c多了处理日期和时间的相关函数和结构,可引用<ctime>,有四个与时间相关的类型:clock_t、time_t、size_t 和 tm

    序号函数 & 描述
    1 time_t time(time_t *time);
    该函数返回系统的当前日历时间,自 1970 年 1 月 1 日以来经过的秒数。如果系统没有时间,则返回 .1。
    2 char *ctime(const time_t *time);
    该返回一个表示当地时间的字符串指针,字符串形式 day month year hours:minutes:seconds year
    3 struct tm *localtime(const time_t *time);
    该函数返回一个指向表示本地时间的 tm 结构的指针。
    4 clock_t clock(void);
    该函数返回程序执行起(一般为程序的开头),处理器时钟所使用的时间。如果时间不可用,则返回 .1。
    5 char * asctime ( const struct tm * time );
    该函数返回一个指向字符串的指针,字符串包含了 time 所指向结构中存储的信息,返回形式为:day month date hours:minutes:seconds year 。
    6 struct tm *gmtime(const time_t *time);
    该函数返回一个指向 time 的指针,time 为 tm 结构,用协调世界时(UTC)也被称为格林尼治标准时间(GMT)表示。
    7 time_t mktime(struct tm *time);
    该函数返回日历时间,相当于 time 所指向结构中存储的时间。
    8 double difftime ( time_t time2, time_t time1 );
    该函数返回 time1 和 time2 之间相差的秒数。
    9 size_t strftime();
    该函数可用于格式化日期和时间为指定的格式。

    实例来一波:

    #include <iostream>
    #include <ctime>
     
    using namespace std;
     
    int main( )
    {
       // 基于当前系统的当前日期/时间,time_t是ctime中类似于数据类型的一种结构,而time()返回的是1990年至今有多少秒
       time_t now = time(0);
       
       // 把 now 转换为字符串形式,字符串dt是对时间now的一种引用
       char* dt = ctime(&now);
     
       cout << "本地日期和时间:" << dt << endl;
     
       // 把 now 转换为 tm 结构
       tm *gmtm = gmtime(&now);    //这个看起来是指针,函数返回一个指向time的指针
       dt = asctime(gmtm);    //据说是格林尼治的时间
       cout << "UTC 日期和时间:"<< dt << endl;
    }

    输出格式化的当前时间:

    //这个完全看不懂
    
    #include <iostream>
    #include <ctime>
    #include <stdlib.h>
    #include <stdio.h>
    
    using namespace std;
    
    string  Get_Current_Date();
    
    int main( )
    {
        // 将当前日期以 20** - ** - ** 格式输出
        cout << Get_Current_Date().c_str() << endl;
    
        getchar();
        return 0;
    }
    
    string  Get_Current_Date()
    {
        time_t nowtime;  
        nowtime = time(NULL); //获取日历时间   
        char tmp[64];   
        strftime(tmp,sizeof(tmp),"%Y-%m-%d %H:%M:%S",localtime(&nowtime));   
        return tmp;
    }

     4,输入和输出

    I/O库重要的头文件:

    头文件函数和描述
    <iostream> 该文件定义了 cin、cout、cerr 和 clog 对象,分别对应于标准输入流、标准输出流、非缓冲标准错误流和缓冲标准错误流。
    <iomanip> 该文件通过所谓的参数化的流操纵器(比如 setw 和 setprecision),来声明对执行标准化 I/O 有用的服务。
    <fstream> 该文件为用户控制的文件处理声明服务。我们将在文件和流的相关章节讨论它的细节。

    标准输出流:cout

    #include <iostream>
    using namespace std;
    int main( )
    {
    char str[] = "Hello C++";
    cout << "Value of str is : " << str << endl;
    }

    标准输入流:

    #include <iostream>
    using namespace std;
    int main( )
    {
    char name[50];
    cout << "请输入您的名称: ";
    cin >> name;    //用户的输入赋值给name,类似于python的input
    cout << "您的名称是: " << name << endl;
    }

    标准错误流:cerr 对象是非缓冲的,且每个流插入到 cerr 都会立即输出。不大明白用法,且先看吧

    #include <iostream>
    using namespace std;
    int main( )
    {
    char str[] = "Unable to read....";
    cerr << "Error message : " << str << endl;
    }

    标准日志流:clog 对象是缓冲的。这意味着每个流插入到 clog 都会先存储在缓冲在,直到缓冲填满或者缓冲区刷新时才会输出。

    #include <iostream>
    using namespace std;
    int main( )
    {
    char str[] = "Unable to read....";
    clog << "Error message : " << str << endl;
    }

    良好的编程实践告诉我们,使用 cerr 流来显示错误消息,而其他的日志消息则使用 clog 流来输出。

    5,数据结构

    C/C++ 数组允许定义可存储相同类型数据项的变量,但是结构是 C++ 中另一种用户自定义的可用的数据类型,它允许您存储不同类型的数据项。

    可用struct定义结构,以下是结构实例:

    struct Books
    {
    char title[50];
    char author[50];
    char subject[100];
    int book_id;
    } book;
    //声明一个结构体类型 Books,变量为 book:

    用英文点号访问结构成员,

    #include <iostream>
    #include <cstring>
    using namespace std;
    // 声明一个结构体类型 Books 
    struct Books
    {
    char title[50];
    char author[50];
    char subject[100];
    int book_id;
    };
    int main( )
    {
    Books Book1; // 定义结构体类型 Books 的变量 Book1
    Books Book2; // 定义结构体类型 Books 的变量 Book2
    // Book1 详述
    strcpy( Book1.title, "C++ 教程");    //strcpy字符串拷贝命令,把第二个字符串的值赋值给第一个,相当于给books结构的book1实例的第一个属性----title赋值为‘c++教程’
    strcpy( Book1.author, "Runoob");
    strcpy( Book1.subject, "编程语言");
    Book1.book_id = 12345;
    // Book2 详述
    strcpy( Book2.title, "CSS 教程");
    strcpy( Book2.author, "Runoob");
    strcpy( Book2.subject, "前端技术");
    Book2.book_id = 12346;
    // 输出 Book1 信息
    cout << "第一本书标题 : " << Book1.title <<endl;    //输出的时候基本格式是实例加.加结构内容
    cout << "第一本书作者 : " << Book1.author <<endl;
    cout << "第一本书类目 : " << Book1.subject <<endl;
    cout << "第一本书 ID : " << Book1.book_id <<endl;
    // 输出 Book2 信息
    cout << "第二本书标题 : " << Book2.title <<endl;
    cout << "第二本书作者 : " << Book2.author <<endl;
    cout << "第二本书类目 : " << Book2.subject <<endl;
    cout << "第二本书 ID : " << Book2.book_id <<endl;
    return 0;
    }

    结构作为函数的参数:

    #include <iostream>
    #include <cstring>
    using namespace std;
    void printBook( struct Books book );    //声明一个函数,参数是结构
    // 声明一个结构体类型 Books 
    struct Books    
    {
    char title[50];
    char author[50];
    char subject[100];
    int book_id;
    };
    int main( )
    {
    Books Book1; // 定义结构体类型 Books 的变量 Book1
    Books Book2; // 定义结构体类型 Books 的变量 Book2
    // Book1 内容赋值
    strcpy( Book1.title, "C++ 教程");
    strcpy( Book1.author, "Runoob");
    strcpy( Book1.subject, "编程语言");
    Book1.book_id = 12345;
    // Book2 内容赋值
    strcpy( Book2.title, "CSS 教程");
    strcpy( Book2.author, "Runoob");
    strcpy( Book2.subject, "前端技术");
    Book2.book_id = 12346;
    // 输出 Book1 信息
    printBook( Book1 );    //直接把结构传递进去就行了,不用加struct
    // 输出 Book2 信息
    printBook( Book2 );
    return 0;
    }
    void printBook( struct Books book )    //函数实现
    {
    cout << "书标题 : " << book.title <<endl;
    cout << "书作者 : " << book.author <<endl;
    cout << "书类目 : " << book.subject <<endl;
    cout << "书 ID : " << book.book_id <<endl;
    }

    指向结构的指针:

    #include <iostream>
    #include <cstring>
    using namespace std;
    void printBook( struct Books *book );    //函数声明,声明需要一个结构的实例的指针
    struct Books    //预定义结构的内容
    {
    char title[50];
    char author[50];
    char subject[100];
    int book_id;
    };
    int main( )
    {
    Books Book1; // 定义结构体类型 Books 的变量 Book1
    Books Book2; // 定义结构体类型 Books 的变量 Book2
    // Book1 详述
    strcpy( Book1.title, "C++ 教程");
    strcpy( Book1.author, "Runoob");
    strcpy( Book1.subject, "编程语言");
    Book1.book_id = 12345;
    // Book2 详述
    strcpy( Book2.title, "CSS 教程");
    strcpy( Book2.author, "Runoob");
    strcpy( Book2.subject, "前端技术");
    Book2.book_id = 12346;
    // 通过传 Book1 的地址来输出 Book1 信息
    printBook( &Book1 );    //因为需要的是指针,所以要把book1 book2 的内存地址放进去
    // 通过传 Book2 的地址来输出 Book2 信息
    printBook( &Book2 );
    return 0;
    }
    // 该函数以结构指针作为参数
    void printBook( struct Books *book )
    {
    cout << "书标题 : " << book->title <<endl;    //此处要特别注意,访问指针指向的实例中的结构内容的话,不能继续用点号了,要用->号,不用问为啥,因为是规定
    cout << "书作者 : " << book->author <<endl;
    cout << "书类目 : " << book->subject <<endl;
    cout << "书 ID : " << book->book_id <<endl;
    }

    补充typedef:

    typedef为C语言的关键字,作用是为一种数据类型定义一个新名字。这里的数据类型包括内部数据类型(int,char等)和自定义的数据类型(struct等)。在编程中使用typedef目的一般有两个,一个是给变量一个易记且意义明确的新名字,另一个是简化一些比较复杂的类型声明。

    //(1)用typedef声明一个新类型名来代替已有的类型名。如
    typedef int Status  //指定标识符Status代表int类型
    typedef double DATE  //指定标识符DATE代表double类型
    int i; Status i;    //等价的
    
    //(2)用typedef对数组类型起新名:
    typedef int NUM[100];//声明NUM为整数数组类型,可以包含100个元素
    NUM n;//定义n为包含100个整数元素的数组,n就是数组名
    
    //(3)对一个结构体类型声明一个新名字:
    typedef struct  //在struct之前用了关键字typedef,表示是声明新类型名
    {
        int month;
        int day;
        int year;  
    } TIME; //TIME是新类型名,但不是新类型,也不是结构体变量名,这样就可以用TIME定义该结构体变量,如:
    TIME birthday;
    //不用typeof的时候:
    struct Books    //Books是结构体类型
    {
    char title[50];
    char author[50];
    char subject[100];
    int book_id;
    } book;    //book是结构变量
  • 相关阅读:
    第十一章 表单与验证
    第十章 日期与时间
    第九章 正则表达式
    第八章 字符串处理
    纯C实现面向对象之接口编程
    csharp 面向对象编程
    cpp面向对象编程
    javascriptMVC框架面向对象编程
    堆栈的区别
    Java堆栈简介
  • 原文地址:https://www.cnblogs.com/0-lingdu/p/10671459.html
Copyright © 2020-2023  润新知