C++中的字符串(1)

 更新时间:2021年11月03日 10:58:15   作者:梁唐  
这篇文章主要简单介绍C++中的字符串,字符串就是连续的一连串字符,在C++当中, 处理字符串的方式有两种类型。一种来自于C语言,也被称为C风格字符串。另外一种是基于string类库,下面来看文章学校内容

1、字符串

1.1 字符串定义

字符串就是连续的一连串字符,在C++当中, 处理字符串的方式有两种类型。一种来自于C语言,也被称为C风格字符串。另外一种是基于string类库。

C风格的字符串其实就是字符存储在char数组当中。不过它和一般的数组有一些区别,拥有一些特殊的性质。比如一空字符\0结尾,它的ascii码是0,用来标记字符串的结尾。

char str[5] = {'h', 'e', 'l', 'l', 'o'};
char str2[5] = {'h', 'e', 'l', 'l', '\0'};


对于上面的两个例子,第一个例子虽然也是char数组,但是由于它的结尾不是\0,所以它不能看成是字符串。因为很多算法都是以\0的位置为标记的,比如计算字符串长度的算法,以及cout等等。

上面我们采用的是数组常规的初始化方式,这当然是可以的,不过这样会很不方便。一个是需要一位一位地填写字符,会非常地麻烦。另外还需要手动填充\0,也容易忘记,

所以对于字符串而言我们还有更好的初始化方式:

char hello[6] = "hello";
char world[] = "world";


用引号括起来的字符串隐式地包含了结尾的\0,需要注意的是,我们在确定数组长度的时候需要将结尾的\0也计算在内。

这里要提醒大家注意引号的区别, 在C++当中单引号表示单个字符,而双引号表示字符串。所以下面这种写法是错误的:

char c = "S";


并且“S”其实表示的是字符串所在的内存地址,当我们把一个内存地址赋值给一个char类型的时候自然就会报错了。

咦,不是说好的是字符串么,怎么又扯到地址了?不要急,等后面讲到指针的地方就明白了。

1.2 字符串的读入

直接用字符串常量来初始化字符数组只是一种方式,另外一种常用的方式是只定义字符数组的长度,从外部读入数据,

如:

char str[100];

scanf("%s", str);
cin >> str;

无论是使用scanf还是cin,都是一样的效果。

但是没有这么简单,比如我们再来看一段代码:

char name[100];
char level[100];

scanf("%s", name);
scanf("%s", level);


在这段代码当中,我们定义了name和level两个字符串变量。当我们执行的时候,就会发现问题:

我刚输入完名字,还没来得及输level就结束了。如果我们把namelevel分别输出的话就会发现,name的值是lianglevel的值是tang

这说明了什么?说明了我们读入字符串的时候它并不是按行读入的,而是按照空格分隔的!它不像是隔壁的Pythoninput默认就是读入一行,C++的读入默认都是按照空格分隔的。

那问题来了,假如我们需要读入一行应该怎么办呢?也有办法,我们可以使用cin.getline代替之前的scanf或者是cin

我们来看下它的函数签名:

istream& getline ( istream& is, string& str, char delim );
istream& getline ( istream& is, string& str );


C++允许参数列表不同的同名函数重载,这两个签名都是OK的。两者的差别在于第三个参数,但三个参数表示分隔符,如果不传的话,默认是'\n'。第二个参数表示字符串的长度,所以如果要按照行来读入字符串的话,刚刚的代码应该写成:

cin.getline(name, 100);
cin.getline(level, 100);


除了可以使用getline之外,还可以使用getget有好几种变体,一种变体是读入一个字符,它有一种变体也可以读入一行字符串。不过唯一的区别是,get函数不会处理行尾的换行符。如果我们要读入两行字符的话,需要手动将这个换行符处理掉。

cin.get(name, 100); // 读入一行数据
cin.get();   // 读入换行符
cin.get(level, 100);// 读入第二行数据


写成三行看起来有些繁琐,我们还可以进行简化,简化成一行:

cin.get(name, 100).get().get(level, 100);


看起来很像是Java8的流式编程,能够这样做的原因是getgetline函数会返回一个cin的对象。所以我们可以这样连续调用。

相信有些同学已经注意到了,同样的函数名,根据我们传入的参数不同执行了不同的逻辑。这在C++当中叫做函数重载,是一个非常重要的概念。

1.3 排坑

关于getline有一个比较大的坑,当我们同时使用cingetline的时候,有时候会出现问题。

比如下面这段代码:

int a;
char name[100];
cin >> a;
cin.getline(name, 100);

cout << "a = " << a << endl;
cout << "name = " << name << endl;


这段代码很简单,我们定义了两个变量。一个是int型的a,一个是字符串name。我们使用cin读入a,使用getline读入name

这看起来一点问题也没有,但是当我们运行的时候就会出现问题。

会发现我都没有来得及输入name,程序就结束了,而name读到了一个空。

这并不是C++有bug,而是我们在输入32的时候,敲了一个回车。所以在使用getline读入一行的时候,看到了回车,直接退出了,读入了一个空行,这就是为什么我们没有机会输入name的原因。

要解决这个问题怎么办呢?其实也很简单,我们额外读入一个字符,把换行符给读取掉就行了。

int a;
char name[100];
cin >> a;
cin.get(); // getchar() C语言版本
cin.getline(name, 100);

cout << "a = " << a << endl;
cout << "name = " << name << endl;

类似的问题在竞赛的题目当中很常见,我们经常要同时读入字符串和数字,很容易遇到这样的问题。遇到了不要紧张,仔细检查一下数据和逻辑,看看是不是读入到了换行符。

到此这篇关于C++中的字符串(1)的文章就介绍到这了,更多相关C++字符串内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

注:文章转自微信公众号:Coder梁(ID:Coder_LT)

相关文章

  • C++ 名称空间详情

    C++ 名称空间详情

    当一个项目变得大型之后,我们会引入很多的库,这么一来两个库很可能会定义List、Tree、Node同名的类,编译器要是不考虑这情况的话,程序员调用时就会出现冲突问题。C++提供了名称空间工具,以更好的控制名称的作用域,本文就来谈谈C++ 名称空间,需要的朋友可以参考一下
    2021-09-09
  • C++ 详细讲解stack与queue的模拟实现

    C++ 详细讲解stack与queue的模拟实现

    C++ Stack(堆栈) 是一个容器类的改编,为程序员提供了堆栈的全部功能,也就是说实现了一个先进后出(FILO)的数据结构,许多程序都使用了 queue 容器。queue 容器可以用来表示超市的结账队列或服务器上等待执行的数据库事务队列
    2022-04-04
  • C++中的自定义函数返回类型

    C++中的自定义函数返回类型

    这篇文章主要介绍了C++中的自定义函数返回类型,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2022-11-11
  • C语言 自定义类型全面系统理解

    C语言 自定义类型全面系统理解

    在C语言中自定义类型主要有结构体类型、位段、枚举类型、联合体类型,自定义类型是面试常会碰到的内容,本篇文章带你彻底解决自定义类型
    2022-02-02
  • c++ 成员函数与非成员函数的抉择

    c++ 成员函数与非成员函数的抉择

    尽量用类的非成员函数以及友元函数替换类的成员函数 例如一个类来模拟人People
    2013-01-01
  • C++中利用cout和fstream采用非科学计数法输出

    C++中利用cout和fstream采用非科学计数法输出

    这篇文章主要介绍了C++中利用cout和fstream采用非科学计数法输出方式,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2022-11-11
  • C语言实现飞机游戏(进阶版)的示例代码

    C语言实现飞机游戏(进阶版)的示例代码

    在前文中,已经带大家利用C语言实现了简单的飞机游戏,但它还存在一些缺陷。因此,本文将给大家带来进阶版的飞机游戏,需要的可以参考一下
    2022-10-10
  • C语言详解strcmp函数的分析及实现

    C语言详解strcmp函数的分析及实现

    strcmp函数语法为“int strcmp(char *str1,char *str2)”,其作用是比较字符串str1和str2是否相同,如果相同则返回0,如果不同,前者大于后者则返回1,否则返回-1
    2022-05-05
  • C++实现LeetCode(15.三数之和)

    C++实现LeetCode(15.三数之和)

    这篇文章主要介绍了C++实现LeetCode(三数之和),本篇文章通过简要的案例,讲解了该项技术的了解与使用,以下就是详细内容,需要的朋友可以参考下
    2021-07-07
  • 从零开始的Socket编程学习

    从零开始的Socket编程学习

    我们每天打开浏览器浏览网页时,浏览器的进程怎么与web服务器通信的?QQ进程怎么与服务器或你好友所在的QQ进程通信?这些都得靠socket?那什么是socket?socket的类型有哪些?还有socket的基本函数,下面小编带大家了解下
    2019-05-05

最新评论