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\n\0
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\n\0。
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是结构变量

 

posted @ 2019-07-07 22:26  0点0度  阅读(765)  评论(0编辑  收藏  举报