6.3c++primeplus总结(p62-p91)

6.3c++primeplus总结(p62-p91)字符串是定义在内存的连续字节中的一系列字符 字符串有两种风格 1 字符串越界问题学过 c 的都知道 当我们需要存储一个字符串的时候 一般会这样定义 首先 我们定义的是 14 个字符空间 而 iamastudent 一共也是 14 个字符 但是运行程序会发现 该字符串的长度是 54 并且输出字符串 iamastudent 烫烫烫烫烫烫烫烫烫烫烫烫烫烫烫烫烫 峫 会出现这种情况的原因是什么 答案是 在初始化 str 字符串的时候结尾没有赋予字符串结束字符 0 在计算机内部 处理字符串是这样的 从数组开头

1.字符串(string)

字符串是定义在内存的连续字节中的一系列字符。字符串有两种风格:

  1. c语言风格的字符串
  2. c++风格的字符串

(1)c语言风格的字符串

1.字符串越界问题


学过c的都知道,当我们需要存储一个字符串的时候,一般会这样定义:

#include<cstdio> #include<cstring> int main() { 
    char str[14] = { 
    'i',' ','a','m', ' ','a',' ','s','t','u','d','e','n','t' }; printf("该数组有%d元素\n", strlen(str)); printf("输出该字符串:\n%s", str); return 0; } 

首先,我们定义的是14个字符空间,而“i am a student”一共也是14个字符,但是运行程序会发现,该字符串的长度是54,并且输出字符串:i am a student烫烫烫烫烫烫烫烫烫烫烫烫烫烫烫烫烫?峫?

解决方案

1.在数组末尾加一个’\0’,当然定义的14个空间要扩大一个字节变15

char str[15] = { ‘i’,’ ‘,‘a’,‘m’, ’ ‘,‘a’,’ ‘,‘s’,‘t’,‘u’,‘d’,‘e’,‘n’,‘t’,’\0’ };

2.定义数组的时候预留多一点空间,让计算机自动添加结束符

3.不定义数组空间,让系统自己分配,你只管初始化

实际上用一个单引号初始化字符串很费力,直接用双引号也可以.

char str[100] =“i am a student!”; 字符串结束符会自动添加到后面,只是没有显示看到

2. sizeof和strlen()
sizeof运算符指出整个数组长度,而strlen()函数返回的是存储在数组的字符串的长度,而不是数组本身的长度,注意,strlen()函数不计算空字符。

3.字符串输入
先看一个小程序

#include<iostream> using namespace std; const int ArSize = 20; char name[ArSize]; char dessert[ArSize]; int main() { 
    cout <<" Enter your name : \n"; cin >> name; cout << "Enter your favorite dessert:\n"; cin >> dessert; cout << "I have some delicious " << dessert; cout << " for you, " << name << ".\n"; return 0; } 

解决方案
通常,我们输出字符串都是由空格的,那么这个cin又不能有空格,那么我们也不可能每次都重新初始化数组吧,这样太麻烦。
我尝试了半天,发现方法都不理想,只要字符串有空格,制表符这些都会中断输入,?




istream类提供了一些面向行的类成员函数:getline()和get().这两个函数都读取一行输入,直到到达换行符。然而,getline()将丢弃换行符,而get()将换行符保留下来。

可以发现,getline函数有两个重载函数,第一个函数只有两个参数,这也是用的做多的。而第二个重载函数有三个参数。

#include<iostream> using namespace std; const int ArSize = 20; char name[ArSize]; char dessert[ArSize]; int main() { 
    cin.getline(name,20); cout << name << endl; cin.getline(dessert, 20); cout << dessert << endl; return 0; } 

这个程序,当输入完一个字符串后按回车结束输入,getline()函数将字符串存储到数组,但是注意,换行符不会放进去,会被丢弃,即不再缓冲区也不在数组里面,然后数组末尾添加一个’\0’。

这里不得不提一下用cin.getline和cin.get的区别了,有一个大大的不同哦?

同时使用两次cin.getline和同时使用两次cin.get

会有区别吗?当然会,因为前面说到,cin.getline()读取换行符且丢弃,这样输入队列(缓冲区)里面就没有了换行符。这样的话,下一次再次调用cin.getline(),由于输入队列里面没有换行符了,那么系统会等待用户输入。这样很好。

但是cin.get()不会读取且丢掉换行符,这样会怎么样?第二次用cin.get()的时候,会发现输入队列有一个换行符,那么cin.get()函数认为到字符串末尾,将不再读取字符。这。。。。你一开始就结束,那下次还是这样,因为你换行符原地罚站,有点尴尬,这样会陷入一个死循环。

解决方法:

cin.get(name,20); cin.get(); cin.get(dessert,20); 

这个cin.get()的作用就是读取输入队列一个字符。注意,这个不带参数的get()是它的一个重载,不是所有函数都适用的。除法你自己定义了或着头文件的类包含了这个函数的重载。

cin.get(name,20).get();

疑难杂症
1.当cin.get(name.20)和cin.getline(name,20)读取空行的时候,将设置失效位(failbit),这意味着接下来的输入将被阻断,这时候就要用cin.clear()语句恢复环境。
也许读起来费解,给一个测试小程序




#include<iostream> using namespace std; const int ArSize = 20; char name[ArSize]; char dessert[ArSize]; int main() { 
    cin.get(name,20); //尝试直接输入换行 //是不是发现直接退出程序了?下面的操作都被阻断 //这个时候要用cin.clear()来恢复 cin.clear(); //尝试不加这句话,看看和加了有什么区别 cin.get(); //记得吃掉刚刚输入的回车 cin.get(dessert,20); cout<<dessert; return 0; } 

2.
上面提到了如果用cin.get()和cin.getline()进行输入,那么一定要控制好字符串长度,首先:
必须预留一个字节存放’\0’,比如cin.get(name,20),那么只能输入19个字符,最后一个空间将由系统自动填充一个’\0’,代表字符串结束。
那么如果说,一不小心输入的字符串长度超过限制怎么办?首先,多余的字符不会放进数组,然后,getline()和get()将设置失效位,阻断后面的输入.






(2)c++风格的字符串

首先,肯定的是,string能干的事情,通过字符数组也可以干。只是string将字符串的功能和特性归纳为在一起,在使用字符串的时候更加智能化
下面都是等价的:

cout<
cout<

1.拼接,复制.
string类简化了字符串合并的操作,可以直接用+将两个string类对象接在一起。甚至可以用+=。毫无疑问这是对+的重载.

拼接

赋值

2.strlen().
string类提供两种函数计算字符串里面的字符个数;

  1. size()
  2. length()

通过一个小程序来说明两个函数的用法

#include<iostream> using namespace std; #include<cstring> int main() { 
    string str1="i am a boy!"; string str2="i am a girl!"; int len1=str1.size(); > 这里是引用 int len2=str2.size(); //int len1=str1.length(); //结果和上面一样的 //int len2=str2.length(); cout<<len1<<endl; cout<<len2<<endl; return 0; } 

很可惜,strlen()函数只能接受一个指向字符常量的指针,没有从std::string到const char*的转换函数。那么既然不能转换,那就强制转换一下。

const char *p=str1.c_str();

说明一下,string类的函数c_str()返回string字符串的首地址,且类型为const char*

#include<iostream> using namespace std; #include<cstring> int main() { 
    string str1 = "i am a boy!"; string str2 = "i am a girl!"; const char* p = str1.c_str(); cout << p << endl; p = str2.c_str(); cout << p; cout << endl << strlen(p); } 

3.string的各种常用函数.
1.insert(pos,string)

这说明insert里面的1是指从下标1开始进行插入,后面的元素自动向右移动。很方便。

2.共用体(union)和枚举(enum)

(1)共用体(union)

union one4all { 
    int int_val; long long_val; double double_val; }; 

上面是一个共用体,它的名称是one4all,它可以用来存储int,long,double类型的数据,但是有一个前提,就是,一次只能存储一个类型。比如说,它存储int,就不能存储double

one4all pail; pail.int_val=15; cout<<pail.int_val; pail.double_val=1.39; cout<<pail.double_val; 
struct widget { 
    char brand[20]; int type; union id { 
    long id_num; char id_char[20]; }id_val; }; widget prize; if(prize.type==1) cin>>prize.id_val.id_num; else cin>>prize.id_val,id_char; 

由此可以看出共用体和结构体的区别,共用体变量只能在它包含的数据类型中选择一个作为自己唯一的类型,而结构体变量同时存储多个类型.

(2) 枚举(enum)

C++的enum工具提供一种方便的方式创建符号常量,这种方式可以代替const。它还运行定义新类型,但是必须按严格的限制完成。

enum spectrum{red, orange, yellow, green, blue};

上面这条语句的意思是:

  1. 让spectrum成为新类型的名称;
  2. 其中的red,blue这些都变成了符号常量,等价于const red,const blue。
  3. 如果不显示的赋值,那么这些符号常量的初始值从0开始,依次增加1(red=0,orange=1,yellow=2,green=3,blue=4)

设置枚举的值
1.初始化的时候赋值

enum spectrum{red=100,orange,yellow=40,green,blue=0};

  1. red的值为100,yellow的值为40,blue的值为0
  2. 没有显示初始化的是多少呢?还是严格按照默认的递增加1规则。那么,orange=101,green=41.

找到枚举范围,然后就可以用强制转换类型转换赋值了。

注意;ff=9,像这种赋值是不允许的,不存在有int型转换为bits型的转换函数,所以要用强制转换规则赋值

3.指针

指针在之前的博客写了,就不多加复习,挑一些之前不注意的地方复习一下

1.指针初始化值

int *p; *p=1234; 
int *p=NULL; int a=1234; p=&a; 

2.new运算符

在C里面,我们通常用malloc分配内存空间。在C++里,增加了新的分配方式,new运算符.

int *p=new int;

意思是,让p指向一个int型的内存空间。new运算符根据类型来确定需要多少字节的内存。然后,它找到这样的内存,并返回其地址。接下来,将地址赋给p,所以p就是地址,*p就是地址存储的值。

动态创建数组
分配一个数组空间,大小为10个int

int *psome=new int [10]

同时,要用delete释放

delete [] psome;

3.指针算术

#include<iostream> using namespace std; int main() { 
    double wages[3]={ 
   10000.0,20000.0,30000.0}; short stacks[3]={ 
   3,2,1}; double *pw=wages; //将数组的地址给pw short *ps=&stacks[0]; //同理 cout<<"pw= "<<pw<<", *pw= "<<endl; pw=pw+1; //注意这个+1是什么意思 cout<<"add 1 to pw:\n"; cout<<"pw= "<<pw<<", *pw= "<<*pw<<endl; cout<<"ps= "<<ps<<", *ps="<<*ps<<endl; ps=ps+1; cout<<"add 1 to the ps:\n"; cout<<"ps= "<<ps<<", *ps= "<<*ps<<"\n\n"; return 0; } 

上面的程序通过对指针+1,发现,实际上并不是地址简单的加1,而是加了8个字节,说明,在这里指针不是整型,虽然可以用整型相加,但是这个加数代表的意思不是单纯的int类型,应该代表的是“1个单位的指针空间”,在这里就是8个字节,一个单位double的大小。

4.数组的地址
有意思的是,在我们对数组取地址的时候,数组名不会被解释为其地址。
比如:




int tell[10]; cout<<tell<<endl; cout<<&tell<<endl; 

好了,今天的学习,到这里。明天继续复习C++。

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请联系我们举报,一经查实,本站将立刻删除。

发布者:全栈程序员-站长,转载请注明出处:https://javaforall.net/219669.html原文链接:https://javaforall.net

(0)
上一篇 2026年3月17日 下午10:10
下一篇 2026年3月17日 下午10:10


相关推荐

  • [Mvel]Mvel2.0使用指南一 基础

    [Mvel]Mvel2.0使用指南一 基础MVEL 在很大程度上受到 Java 语法的启发 作为一个表达式语言 也有一些根本的区别 旨在更高的效率 例如 直接支持集合 数组和字符串匹配等操作以及正则表达式 MVEL 用于执行使用 Java 语法编写的表达式 除了表达语言之外 MVEL 还可用作配置和字符串构造的模板语言 MVEL2 x 表达式包含以下部分的内容 属性表达式布尔表达式方法调用变量赋值函数定义 1 基本语法 MVEL 是一种基于 Java 语法

    2026年3月19日
    2
  • 阿里面试真题:Dubbo的SPI机制

    阿里面试真题:Dubbo的SPI机制被问懵逼了

    2026年3月26日
    2
  • 池化层的作用[通俗易懂]

    maxpooling是CNN当中的最大值池化操作,其实用法和卷积很类似tf.nn.max_pool(value,ksize,strides,padding,name=None)参数是四个,和卷积很类似:第一个参数value:需要池化的输入,一般池化层接在卷积层后面,所以输入通常是featuremap,依然是[batch,height,width,channels]这样的shape第二个参数ksize:池化窗口的大小,取一个四维向量,一般是[1,height,width,1],

    2022年4月10日
    53
  • java校验json格式_json格式校验

    java校验json格式_json格式校验C语言json格式校验最近用到json格式数据传输信息,在C语言中使用cjson解析json字符串,若json格式不正确,会使整个进程直接挂掉。想到能否在解析前先进行格式校验,通过后再解析,查找资料,网上有现成源码,网址:http://www.json.org/JSON_checker/主要用到两个文件JSON_checker.c和JSON_checker.h,具体用法可以参考main.c。这里参考了博客:C语言如何检测json格式的数据合法性中的用法,并加以改进。在官网中提供了json检查的测试文

    2025年8月1日
    4
  • C语言判断回文字符串(指针)

    C语言判断回文字符串(指针)东北大学在线编程社区problem1678题目描述:编写函数:intfun(char*p),功能是判断一个字符串是否是回文字符串(提示:回文字符串是指正读和反读都一样的字符串),要求从主函数中由键盘输入字符串,调用函数fun后,根据函数fun的返回值,主函数输出是否为回文字符串的判断。输入样例:haah输出样例:是回文串//该代码使用MicrosoftVisualStudio2019编写#define_CRT_SECURE_NO_WARNINGS#include<stdio.

    2022年5月4日
    51
  • PostgreSql安装过程

    PostgreSql安装过程安装环境 Win7 x64 安装包对应版本 postgresql 10 20 1 windows x64 exepgadmin4 4 30 x64 exe 最开始是参考菜鸟教程上的安装教程开始安装菜鸟教程 https www runoob com postgresql windows install postgresql html 然后安装完成后运行报错 ThepgAdmin4s 百度这个问题 说要独立安装 pgAdmin4 之后就重新

    2026年3月18日
    2

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

关注全栈程序员社区公众号