C++系列4:数据类型和变量

1. 字符串

1.1 古老版本

C 风格的字符串起源于 C 语言,并在 C++ 中继续得到支持。字符串实际上是使用null字符\0终止的一维字符数组。因此,一个以 null 结尾的字符串,包含了组成字符串的字符。
下面的声明和初始化创建了一个RUNOOB字符串。由于在数组的末尾存储了空字符,所以字符数组的大小比单词RUNOOB的字符数多一个。
char site[7] = {‘R’, ‘U’, ‘N’, ‘O’, ‘O’, ‘B’, ‘\0’};
依据数组初始化规则,您可以把上面的语句写成以下语句:
char site[] = “RUNOOB”;
在这里插入图片描述

1.2 使用string

string类提供了一系列针对字符串的操作,比如:

  1. append() – 在字符串的末尾添加字符
  2. find() – 在字符串中查找字符串
  3. insert() – 插入字符
  4. length() – 返回字符串的长度
  5. replace() – 替换字符串
  6. substr() – 返回某个子字符串

下面是一些例子:

#include <iostream>
#include <string>
using namespace std;

int main()
{
    //定义一个string类对象
    string http = "www.runoob.com";

   //打印字符串长度
   cout<<http.length()<<endl;

    //拼接
    http.append("/C++");
    cout<<http<<endl; //打印结果为:www.runoob.com/C++

    //删除
    int pos = http.find("/C++"); //查找"C++"在字符串中的位置
    cout<<pos<<endl;
    http.replace(pos, 4, "");   //从位置pos开始,之后的4个字符替换为空,即删除
    cout<<http<<endl;

    //找子串runoob
    int first = http.find_first_of("."); //从头开始寻找字符'.'的位置
    int last = http.find_last_of(".");   //从尾开始寻找字符'.'的位置
    cout<<http.substr(first+1, last-first-1)<<endl; //提取"runoob"子串并打印

    return 0;
}

1.3 输出格式

#include <iostream>
#include <iomanip>
using namespace std;
int main()
{
    cout<<setiosflags(ios::left|ios::showpoint);  // 设左对齐,以一般实数方式显示
    cout.precision(5);       // 设置除小数点外有五位有效数字 
    cout<<123.456789<<endl;
    cout.width(10);          // 设置显示域宽10 
    cout.fill('*');          // 在显示区域空白处用*填充
    cout<<resetiosflags(ios::left);  // 清除状态左对齐
    cout<<setiosflags(ios::right);   // 设置右对齐
    cout<<123.456789<<endl;
    cout<<setiosflags(ios::left|ios::fixed);    // 设左对齐,以固定小数位显示
    cout.precision(3);    // 设置实数显示三位小数
    cout<<999.123456<<endl; 
    cout<<resetiosflags(ios::left|ios::fixed);  //清除状态左对齐和定点格式
    cout<<setiosflags(ios::left|ios::scientific);    //设置左对齐,以科学技术法显示 
    cout.precision(3);   //设置保留三位小数
    cout<<123.45678<<endl;
    return 0; 
}

使用setw也可以设置输出格式:
在这里插入图片描述

2. 时间

C++ 标准库没有提供所谓的日期类型。C++ 继承了 C 语言用于日期和时间操作的结构和函数。为了使用日期和时间相关的函数和结构,需要在 C++ 程序中引用 头文件。
有四个与时间相关的类型:clock_t、time_t、size_t和tm。类型 clock_t、size_t 和 time_t 能够把系统时间和日期表示为某种整数。
结构类型tm把日期和时间以 C 结构的形式保存,tm 结构的定义如下:

struct tm {
  int tm_sec;   // 秒,正常范围从 0 到 59,但允许至 61
  int tm_min;   // 分,范围从 0 到 59
  int tm_hour;  // 小时,范围从 0 到 23
  int tm_mday;  // 一月中的第几天,范围从 1 到 31
  int tm_mon;   // 月,范围从 0 到 11
  int tm_year;  // 自 1900 年起的年数
  int tm_wday;  // 一周中的第几天,范围从 0 到 6,从星期日算起
  int tm_yday;  // 一年中的第几天,范围从 0 到 365,从 1 月 1 日算起
  int tm_isdst; // 夏令时
};

下面是使用的代码:

#include <iostream>
#include <ctime>
 
using namespace std;
 
int main( )
{
   // 基于当前系统的当前日期/时间
   time_t now = time(0);
 
   cout << "1970 到目前经过秒数:" << now << endl;
 
   tm *ltm = localtime(&now);
 
   // 输出 tm 结构的各个组成部分
   cout << "年: "<< 1900 + ltm->tm_year << endl;
   cout << "月: "<< 1 + ltm->tm_mon<< endl;
   cout << "日: "<<  ltm->tm_mday << endl;
   cout << "时间: "<< ltm->tm_hour << ":";
   cout << ltm->tm_min << ":";
   cout << ltm->tm_sec << endl;
}

3. 变量

3.1 变量声明:extern、using

您可以使用extern关键字在任何地方声明一个变量。虽然您可以在 C++ 程序中多次声明一个变量,但变量只能在某个文件、函数或代码块中被定义一次。

extern int d = 3, f = 5;    // d 和 f 的声明 
int d = 3, f = 5;           // 定义并初始化 d 和 f
byte z = 22;                // 定义并初始化 z
char x = 'x';               // 变量 x 的值为 'x'

typedef 可以声明各种类型名,但不能用来定义变量。用 typedef 可以声明数组类型、字符串类型,使用比较方便,例如typedef unsigned int UINT;typedef int * pint;
因为 typedef 是定义了一种类型的新别名,不是简单的字符串替换,所以它比宏来得稳健

如果要声明一个指向返回 void,有一个 int 参数的函数的函数指针呢?
或许可以使用typedef:
typedef void(*f1)(int);
可以看到,可读性很低,那使用 using 呢?
using f1=void(*)(int);
使用 using 明显更好理解:
所以,始终优先使用 using。

3.2 左右值,右值引用string&&

C++ 中有两种类型的表达式:
左值(lvalue):指向内存位置的表达式被称为左值(lvalue)表达式。左值可以出现在赋值号的左边或右边。
右值(rvalue):术语右值(rvalue)指的是存储在内存中某些地址的数值。右值是不能对其进行赋值的表达式,也就是说,右值可以出现在赋值号的右边,但不能出现在赋值号的左边。

string&&是C++11中的特性,叫做“右值引用”。它只能绑定到右值,即临时对象或将销毁的对象。因此可以把String&&所引用的资源强制拿来使用,且不用重新分配空间。即把String&&所引用对象的资源复制给*this

std::move 并不会真正地移动对象,std::move 只是将参数转换为右值引用而已(相当于一个 static_cast)。注意下面两者的区别,一个使用的是auto,一个使用的是string&&
在这里插入图片描述

static 修饰类的成员变量
1). 静态成员变量是先于类的对象而存在
2). 这个类的所有对象共用一个静态成员
3). 如果静态成员是公有的,那么可以直接通过类名调用
4). 静态成员数据在声明时候类外初始化
静态局部变量与全局变量共享全局数据区,但静态局部变量只在定义它的函数中可见。静态局部变量与局部变量在存储位置上不同,使得其存在的时限也不同,导致对这两者操作 的运行结果也不同。

#include <iostream>

using namespace std;
class Data
{
public:
    Data(){}
    ~Data(){}
    void show()
    {
        cout<<this->data<<" "<<number<<endl;
    }

    static void showData()//先于类的对象而存在
    {
        //这方法调用的时候不包含this指针
        cout<<" "<<number<<endl;
    }

private:
    int data;
public:
    static int number; //静态数据在声明时候类外初始化
};
int Data::number=0;//静态成员初始化

int main()
{
    Data::showData();//通过类名直接调用


    Data::number = 100;//通过类名直接使用
    Data d;
    d.show();
    d.showData();//通过对象调用

    cout << "Hello World!" << endl;
    return 0;
}

3.3 函数参数

在函数声明中,参数的名称并不重要,只有参数的类型是必需的,因此下面也是有效的声明:
int max(int, int);
在这里插入图片描述

在 C++ 里参数传递数组永远都是传递指向数组首元素的指针,编译器不知道数组的大小。
如果想在函数内知道数组的大小, 需要这样做:
进入函数后用memcpy拷贝出来,长度由另一个形参传进去

fun(unsiged char *p1, int len)
{
    unsigned char* buf = new unsigned char[len+1]
    memcpy(buf, p1, len);
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值