C++学习开始就夭折系列:基本语法5

上一文我们介绍到了 C++ 数组,本文从 C++ 字符串开始,抓住时间的尾巴,继续学习,不能这么早就夭折

字符串

C++ 提供了以下两种类型的字符串表示形式:

  • C 风格字符串
  • C++ 引入的 string 类类型 

C 风格字符串

C 风格的字符串起源于 C 语言,字符串实际上是使用 null 字符 '\0' 终止的一维字符数组。因此,一个以 null 结尾的字符串,包含了组成字符串的字符。

对于使用 “ ”(字符串常量)来初始化字符串数组时,不需要把 null 字符放在末尾,C++ 编译器会自动把 '\0' 放在字符串的末尾。

char greeting[] = "Hello";

而对于使用 { } 或 数组下标来初始化字符串数组时是需要将  null 字符 '\0' 字符放在末尾的,且字符数组的大小的设置= 字符串长度+1

char greeting[6] = {'H', 'e', 'l', 'l', 'o', '\0'};

C++ 中可以用来操作以 null 结尾的字符串的函数

函数描述
strcpy(s1, s2); 复制字符串 s2 到字符串 s1。
strcat(s1, s2); 连接字符串 s2 到字符串 s1 的末尾。
strlen(s1); 返回字符串 s1 的长度。
strcmp(s1, s2); 如果 s1 和 s2 是相同的,则返回 0;如果 s1<s2 则返回值小于 0;如果 s1>s2 则返回值大于 0。
strchr(s1, ch); 返回一个指针,指向字符串 s1 中字符 ch 的第一次出现的位置。
strstr(s1, s2); 返回一个指针,指向字符串 s1 中字符串 s2 的第一次出现的位置。

C++ 中的 String 类

C++ 标准库提供了 string 类类型,支持上述所有的操作。

#include <iostream>
#include <string>
 
using namespace std;
 
int main ()
{
   string str1 = "hello,";
   string str2 = "world";
   string str3;
   int  len ;
 
   // 复制 str1 到 str3
   str3 = str1;
   cout << "str3 : " << str3 << endl;
 
   // 连接 str1 和 str2
   str3 = str1 + str2;
   cout << "str1 + str2 : " << str3 << endl;
 
   // 连接后,str3 的总长度
   len = str3.size();
   cout << "str3.size() :  " << len << endl;
 
   return 0;
}

指针

首先我们明确,每一个变量都有一个内存位置,每一个内存位置都定义了可使用连字号(&)运算符访问的地址,它表示了在内存中的一个地址。

指针是一个变量,其值为另一个变量的地址,即,内存位置的直接地址。

指针变量声明的一般形式为:

type *var-name;

type 是指针的基类型,它必须是一个有效的 C++ 数据类型,var-name 是指针变量的名称。用来声明指针的星号 * 是用来指定一个变量是指针。

使用指针

使用过程中的频繁操作:

  1. 定义一个指针变量
  2. 把变量地址赋值给指针
  3. 访问指针变量中可用地址的值

这些是通过使用一元运算符 *来返回位于操作数所指定地址的变量的值:

#include <iostream>

using namespace std;
 
int main ()
{
   int  var = 20;   // 实际变量的声明
   int  *ip;        // 指针变量的声明
 
   ip = &var;       // 在指针变量中存储 var 的地址
 
   cout << "Value of var variable: " << var << endl;
 
   // 输出在指针变量中存储的地址
   cout << "Address stored in ip variable: " << ip << endl;
 
   // 访问指针中地址的值
   cout << "Value of *ip variable: " << *ip << endl;
 
   return 0;
}

Null 指针

变量声明时,如果没有确切的地址可以赋值,要为指针变量赋为 NULL 值。该指针被称为指针。NULL 指针是一个定义在标准库中的值为零的常量:

define NULL 0

大多数的操作系统上,程序不允许访问地址为 0 的内存,因为该内存是操作系统保留的。然而,内存地址 0 的指针表明不指向一个可访问的内存位置。所以,如果指针包含空值(零值),则假定它不指向任何东西。

因此,如果所有未使用的指针都被赋予空值,同时避免使用空指针,就可以防止误用一个未初始化的指针,可以防止出现垃圾值。

指针的算术运算

指针支持四种算术运算:++、--、+、- 。

变量指针可以递增递减,而数组不能递增递减,因为数组名是指向数组开头的常量指针,因为数组是一个常量指针。对指针进行递增递减运算,即把值加上减去其数据类型的字节数,指针指向下一或上一内存位置。

指针还可以用关系运算符进行比较,如 ==、< 和 >:

#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] ){
      cout << "Address of var[" << i << "] = " << ptr << endl;
      cout << "Value of var[" << i << "] = " << *ptr << endl;
 
      // 指向上一个位置
      ptr++;
      i++;
   }
   return 0;
}

指针数组

指针数组的声明:

type *arrName[capacity]

指针数组中的每一个元素是指向 type 类型值的指针。用一个指向字符的指针数组来存储一个字符串列表:

#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 << "] = " << names[i] << endl;
   }
   return 0;
}

指向指针的指针

这是一种多级间接寻址的形式,或者说是一个指针链。当我们定义一个指向指针的指针时,第一个指针包含了第二个指针的地址,第二个指针指向包含实际值的位置。指向指针的指针变量声明:

type **pointer;

 通过查看 var,ptr,*pptr 的地址可以更加清晰的理解多级间接寻址的寻址过程:

#include <iostream>
 
using namespace std;

int main ()
{
    int var = 3000,*ptr,**pptr;
    // 获取 var 的地址
    ptr = &var;
    // 使用运算符 & 获取 ptr 的地址
    pptr = &ptr;

    // 使用 pptr 获取值
    cout << "var 值为 :" << var << endl;
    cout << "*ptr 值为:" << *ptr << endl;
    cout << "**pptr 值为:" << **pptr << endl;
    cout << "var 地址为 :" << &var << endl;
    cout << "ptr=&var 值为var的地址:" << ptr << endl;
    cout << "ptr地址为:" << &ptr << endl;
    cout << "*pptr=ptr=&var  值为var的地址:" << *pptr << endl;
    cout << "pptr 地址为:" << &pptr << endl;
    return 0;
}

传递指针给函数

简单地声明函数参数为指针类型即可传递指针给函数,调用函数时,将变量地址传递作为参数传入。因此,能接受指针作为参数的函数,也能接受数组作为参数(数组名就是地址)。

从函数返回指针

C++ 允许声明一个返回指针的函数。C++ 不支持在函数外返回局部变量的地址,而返回局部变量指针相当于返回局部变量的地址,此时需要定义为 static 局部变量如下所示:

int * myFunction(){...}

引用

引用变量是一个别名。一旦把引用初始化为某个变量,就可以使用该引用名称或变量名称来指向变量。

引用 vs 指针

区别如下:

  • 不存在空引用。引用必须连接到一块合法的内存。
  • 一旦引用被初始化为一个对象,就不能被指向到另一个对象。指针可以在任何时候指向到另一个对象。
  • 引用必须在创建时被初始化。指针可以在任何时间被初始化。 

创建引用

变量名称是变量附属在内存位置中的标签,引用当成是变量附属在内存位置中的第二个标签。可以通过原始变量名称或引用来访问变量的内容。创建方式:

type& quoteName = varName;

& 读作引用。因此,可以读作 "quoteName 是一个初始化为 varName 的 type 型引用" ,引用通常用于函数参数列表和函数返回值。

C++ 支持把引用作为参数传给函数,这比传一般的参数更安全。

C++ 支持函数返回一个引用(一个指向返回值的隐式指针)。这样,函数就可以放在赋值语句的左边。

#include <iostream>
 
using namespace std;
 
double vals[] = {10.1, 12.6};
 
double& setValues( int i ){
  return vals[i];   // 返回第 i 个元素的引用
}
 
// 要调用上面定义函数的主函数
int main ()
{
 
   cout << "改变前的值" << endl;
   for ( int i = 0; i < 2; i++ ){
       cout << "vals[" << i << "] = " << vals[i] << endl;
   }
 
   setValues(1) = 20.23; // 改变第 2 个元素
 
   cout << "改变后的值" << endl;
   for ( int i = 0; i < 2; i++ ){
       cout << "vals[" << i << "] = " << vals[i] << endl;
   }
   return 0;
}

注意:被引用的对象不能超出作用域。

所以返回一个对局部变量的引用是不合法的,但是,可以返回一个对静态变量的引用。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值