C++学习——字符串

1.C 风格字符串

字符串实际上是使用 null 字符 \0 终止的一维字符数组。因此,一个以 null 结尾的字符串,包含了组成字符串的字符。
示例:下面的声明和初始化创建了一个 RUNOOB 字符串。由于在数组的末尾存储了空字符,所以字符数组的大小比单词 RUNOOB 的字符数多一个。

char site[7] = {'R', 'U', 'N', 'O', 'O', 'B', '\0'};

依据数组初始化规则,您可以把上面的语句写成以下语句:

char site[] = "RUNOOB";
image.png

C++ 编译器会在初始化数组时,自动把 \0 放在字符串的末尾。让我们尝试输出上面的字符串:

#include <iostream>

using namespace std;

int main ()
{
   char site[7] = {'R', 'U', 'N', 'O',         'O', 'B', '\0'};

   cout << "菜鸟教程: ";
   cout << site << endl;

   return 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 的第一次出现的位置。
  • append() -- 在字符串的末尾添加字符
  • find() -- 在字符串中查找字符串
  • insert() -- 插入字符
  • length() -- 返回字符串的长度
  • replace() -- 替换字符串
  • substr() -- 返回某个子字符串
#include <iostream>
#include <cstring>

using namespace std;

int main ()
{
 char str1[13] = "runoob";
 char str2[13] = "google";
 char str3[13];
 int  len ;

 // 复制 str1 到 str3
 strcpy( str3, str1);
 cout << "strcpy( str3, str1) : " <<     str3 << endl;

 // 连接 str1 和 str2
 strcat( str1, str2);
 cout << "strcat( str1, str2): " <<           str1 << endl;

 // 连接后,str1 的总长度
 len = strlen(str1);
 cout << "strlen(str1) : " << len <<   endl;

 return 0;
}

2.string类

C++ 标准库提供了 string 类类型,支持上述所有的操作,另外还增加了其他更多的功能。我们将学习 C++ 标准库中的这个类,现在让我们先来看看下面这个实例:

#include <iostream>
#include <string>

using namespace std;

int main ()
{
   string str1 = "runoob";
   string str2 = "google";
   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;
}

3.sizeof和strlen区别

  • sizeof 操作符的结果类型是 size_t,它在头文件中 typedef 为 unsigned int 类型。该类型保证能容纳实现所建立的最大对象的字节大小。
  • sizeof 是运算符,strlen 是函数。
  • sizeof 可以用类型做参数,strlen 只能用 char* 做参数,且必须是以 \0 结尾的。

sizeof 还可以用函数做参数,比如:

short f();
printf("%d\n", sizeof(f()));
  • 数组做 sizeof 的参数不退化,传递给 strlen 就退化为指针了。

  • 大部分编译程序在编译的时候就把 sizeof 计算过了,是类型或是变量的长度,这就是 sizeof(x) 可以用来定义数组维数的原因。

  • strlen 的结果要在运行的时候才能计算出来,是用来计算字符串的长度,不是类型占内存的大小。

  • sizeof 后如果是类型必须加括弧,如果是变量名可以不加括弧。这是因为 sizeof 是个操作符不是个函数。

  • 当适用一个结构类型或变量时, sizeof 返回实际的大小;当适用一静态地空间数组, sizeof 归还全部数组的尺寸;sizeof 操作符不能返回动态地被分派了的数组
    数组作为参数传给函数时传的是指针而不是数组,传递的是数组的首地址,所以给strlen(函数)传递的首地址

4.字符数组和字符串数组(重要区别)

范例:

int a[10] = {1,2,3,6,7};
char b[6] = {'h','a','p','p','y','\0'};
char c[] = "happy";
cout<<a<<endl;
cout<<b<<endl;
cout<<c<<endl; 

输出结果为:

0x22fe6c
happy
happy

从以上范例可以看出,普通数组中以数组名用cout来输出,只会得到一串地址;用字符数组则会输出数组中的内容。
那为什么会这样呢?

答案:因为 char 型数组中的每一个元素都是一字节,所以每一个字符之间的地址都是 +1 的是连续的,所以当 cout 输出时读到字符数组中的 \0 便停止输出; 而 int 数组每个元素占 4 个字节所以数个数组中每个元素地址的间隔是 4,但其实它也是连续的,出现乱码是因没找到结束符。

5.几种字符串输入方式

  1. cin>>
  • 用法一:最常用、最基本的用法,输入一个数字:

    int a,b;
    cin>>a>>b;
    
  • 用法二:接受一个字符串,遇“空格”、“Tab”、“回车”都结束

    char a[20];
    cin>>a;
    cout<<a<<endl;
    
  1. cin.get()
  • 用法一:cin.get(字符变量名)可以用来接收字符

     char ch;
     ch=cin.get(); //或者cin.get(ch);只能获取一个字符
     cout<<ch<<endl;
    
  • 用法二:cin.get(字符数组名,接收字符数)用来接收一行字符串,可以接收空格

    char a[20];
    cin.get(a,20); //有些类似getline。可以输入多个单词,中间空格隔开。
    cout<<a<<endl;

  • 用法三:cin.get(无参数)没有参数主要是用于舍弃输入流中的不需要的字符, 或者舍弃回车, 弥补cin.get(字符数组名,接收字符数目)的不足.??

    char arr[10];
     cin.get(arr,10);
     cin.get();//用于吃掉回车,相当于getchar();
     cout<<arr<<endl;
    

//输入abcdefghi
//输出abcdefghi

  1. cin.getline()
    cin.getline(): 接受一个字符串,可以接收空格并输出

     char m[20];
     cin.getline(m,5); //与上面基本相同。
     cout<<m<<endl;
    

注意:接受5个字符到m中,其中最后一个为'\0',所以只看到4个字符输出;

  1. getline()
    getline() :接受一个字符串,可以接收空格并输出,需包含

     #include<string>。
     #include<iostream>
     #include<string>
     using namespace std;
     int main ()
     {
       string str;
     getline(cin,str);
     cout<<str<<endl;
     }
    
  2. gets()
    gets(): 接受一个字符串,可以接收空格并输出,需包含 #include<string>。

    char m[20];
    gets(m); //不能写成m=gets();
    cout<<m<<endl;
    
  3. getchar()
    getchar() :接受一个字符,需包含 #include<string>。

     #include<iostream>
     using namespace std;
     int main ()
     {
         char ch;
       ch=getchar(); //不能写成                getchar(ch);
         cout<<ch<<endl;
     }
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 199,636评论 5 468
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 83,890评论 2 376
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 146,680评论 0 330
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 53,766评论 1 271
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 62,665评论 5 359
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,045评论 1 276
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,515评论 3 390
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,182评论 0 254
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,334评论 1 294
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,274评论 2 317
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,319评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,002评论 3 315
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,599评论 3 303
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,675评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 30,917评论 1 255
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,309评论 2 345
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 41,885评论 2 341

推荐阅读更多精彩内容