C++现在是我很常用的一门编程语言,不过使用也限于oj、leetcode等描述算法的方面,真正用于工程的时候较少,导致对C++的部分用法并不熟悉,下面就是我在用C++常常会有的疑惑及解答吧:(参考《C++ Primer Plus》第六版)

目录:

一、字符串

二、共用体

三、枚举

四、指针

一、字符串

疑惑:可能是Java最开始学的,导致在写算法时,用C++对字符串进行处理时用得太不熟悉

C++处理字符串的方式有两种。第一种来自C语言,常被成为C-风格字符串;另一种基于string类库

首先介绍第一种:

字符串是存储在内存的连续字节中的一系列字符,意味着可以将字符串存储在char数组中。C-风格字符串具有一种特殊的性质:以空字符结尾,空字符被写作\0,其ASCII码为0,用来标记字符串的结尾。

char dog[8] = {'b','e','a','u','x',' ','I','I'};  //不是一个字符串

char cat[8] = {'f','a','t','e','s','s','a','\0'}; //是一个字符串

将字符数组初始化为字符串的方法(隐式地包含结尾的空字符):

char bird[11]="Mr. Cheeps";(因此,这里只能到10,而不能到11,因为有隐含的空字符)

所以在确定存储字符串所需的最短数组时,别忘了将结尾的空字符包含在内

char fish[]="Bubbles";

下面这种情况是不被允许的:

char shirt_size="S";

"S"不是字符常量,它表示的是两个字符(字符S和\0)组成的字符串,更糟的是,"S"实际上表示的是字符串所在的内存地址

而用string类时,遍历string时,也不能使str[i]与""的进行比较,也只能与单引号进行比较,否则会报ISO C++ forbids comparison between pointer and integer [-fpermissive]错误,原因是一样的!!!

在数组中使用字符串:

#include <iostream>
#include<cstring>
using namespace std;int main()
{char bird[11];cin>>bird;cout << "Hello " <<bird<< endl;cout<<"Size of:"<<sizeof(bird)<<endl;cout<<"Length:"<<strlen(bird)<<endl;return 0;
}

注:sizeof()运算符指出整个数组的长度,而strlen()函数返回的是存储在数组中的字符串的长度,strlen()只计算可见的字符,不把空字符计算在内

存储在char数组中的字符串可以用下标方式来访问数组中的每个字符

探讨cin:

看下面的程序及输出:

#include <iostream>
#include<cstring>
using namespace std;int main()
{const int ArSize=20;char name[ArSize];char dessert[ArSize];cout<<"输入你的名字:"<<endl;cin>>name;cout<<"输入你最喜爱的点心的名字:"<<endl;cin>>dessert;cout<<"我有一些"<<dessert<<"给你:"<<name<<endl;
}

我们发现输入完名字后程序直接运行完毕,而Dreeb被当作点心的名字了

cin是如何确定已完成字符串输入呢?由于不能通过键盘输入空字符,因此cin需要用别的方法来确定字符串的结尾位置。cin使用空白(空格、制表符和换行符)来确定字符串的结尾位置。因此这个例子的实际结果就是,cin把Alistair放到name数组,被当作第一个字符串,将Dreeb留在输入队列中。

解决方案有:

1、cin.getline(数组名称,要读取的字符数)读取整行,以回车键输入的换行符确定结尾

如果要读取的字符数为20,则getline最多读取19个字符

2、cin.get()

一种格式是与getline一样的参数,一种是空的,可以用来处理多次读入之间的换行符的处理:

假设我们连续两次调用get:

cin.get(name,ArSize);

cin.get(dessert,ArSize);

由于第一次调用后,换行符留在输入队列中,因此第二次调用时看到的第一个字符便是换行符,因此get认为已经到达行尾,而没有任何可读取的内容。

解决方案是:

cin.get(name,ArSize);

cin.get();

cin.get(dessert,ArSize);

另一种解决方案是cin.get(name,ArSize).get();

介绍第二种:string类

要使用string类,必须#include<string>

基本使用:

string str1;

cin>>str1;

若想输入带空格的string,可用string类中的getline(cin,string)与上面的cin.getline()不同,注意使用的对象

从理论上说,可以将char数组视为一组用于存储一个字符串的char存储单元,而string类变量是一个表示字符串的实体

常用到的比如str.length(),string的遍历也可以像char数组一样根据下标来进行

最近在网上又看到了有关string字符串拼接效率的问题:

这里推荐大家看一下这位博主写的https://blog.csdn.net/xiaobaismiley/article/details/25962483

主要说的是不同操作对应的是对象的操作还是引用的操作,下面附上该博主所写的主要内容:

二、共用体

共用体(union)是一种数据格式,它能够存储不同的数据类型,但只能同时存储其中的一种类型。

例如:

union one4all{

int int_val;

long long_val;

double double_val;

};

可以使用one4all变量来存储int、long或double,条件是在不同的时间进行

one4all pail;

pail.int_val=15;

pail.double_val=1.38;此时int值已经丢失了

由于共用体每次只能存储一个值,因此它必须有足够的空间来存储最大的成员,因此它的长度为最大成员的长度。

共用体的用途之一是,当数据项使用两种或更多种格式(但不会同时使用)时,可节省空间。

匿名共用体:

struct widget{

char brand[20];

int type;

union{

long id_num;

char id_char[20];

};

}

widget prize

由于共用体是匿名的,因此id_num和id_char被视为prize的成员,它们的地址相同

三、枚举

见菜鸟教程https://www.runoob.com/w3cnote/cpp-enum-intro.html吧,因为一直好像没用过枚举类,不太懂其用途。

菜鸟教程上这段代码挺好的:

口袋中有红、黄、蓝、白、黑五种颜色的球若干个,每次从口袋中取三个不同颜色的球,统计并输出所有的取法。

分析:由于球只能是五种颜色之一,故可用枚举类型表示球的颜色。设取出的球为i、j、k,根据题意,i、j、k分别可以有五种取值,且i≠j≠k。可以用穷举法,逐个检验每一种可能的组合,从中找出符合要求的组合并输出。

#include<iostream>
#include<iomanip>
using namespace std;
int main(){enum color_set {red,yellow,blue,white,black}; //声明枚举类型colorcolor_set color; int i,j,k,counter=0,loop; //counter是累计不同颜色的组合数for(i=red;i<=black;i++) {for(j=red;j<=black;j++) {if(i!=j){                        //前两个球颜色不同for(k=red;k<=black;k++)if(k!=i&&k!=j){        //第三个球不同于前两个,满足要求counter++;if((counter)%22==0){ //每屏显示22行cout<<"请按回车键继续";cin.get();}cout<<setw(15)<<counter;/*下面输出每种取法,一行为一种取法的三个颜色*/for(loop=1;loop<=3;loop++){switch(loop){case 1: color=(color_set) i; break;    //第一个是icase 2: color=(color_set) j; break;    //第二个是jcase 3: color=(color_set) k; break;    //第三个是k}switch(color){case red:   cout<<setw(15)<<"red";   break;case yellow:cout<<setw(15)<<"yellow";break;case blue:  cout<<setw(15)<<"blue";  break;case white:    cout<<setw(15)<<"white"; break;case black: cout<<setw(15)<<"black"; break;}}cout<<endl;            //输出一种取法后换行}}}}cout<<"共有:"<<counter<<"种取法"<<endl;return 0;
}

在这里感觉枚举类是可以方便代替int表达更具体明了的含义的

四、指针

C++的指针一直都是很重要的!极具特色!

指针是一个变量。其存储的是值的地址,而不是值本身。

我们先介绍一下&(地址运算符)和*(间接值或解除引用运算符):

int home;&home是它的地址

将*用于指针,可以得到该地址处存储的的值

面向对象编程和过程性编程:

这俩的区别在于OOP强调在运行阶段进行决策,而过程性编程在编译阶段将需求与计划确定下来

1、声明和初始化指针

指针声明时必须指定指向的数据的类型:

char与double的地址看上去没什么区别,但char和double使用的字节数是不同的,它们存储值时使用的内部格式也不同

例:int * p;

* p的类型为int类型,因此我们可以把* p看作一个整体表示一个int值,而*被用于指针,因此p变量本身是指针(地址)是指向* p的地址

声明:

int higgens=5;

int * pt=&higgens;

在这种情况下,被初始化的是指针,而不是它指向的值。也就是说上面的语句将pt(而不是*pt)的值设置为&higgens

这种声明也可以:

int updates=6;

int *p;

p=&updates;

2、指针的危险

在C++中创建指针时,计算机将分配用来存储地址的内存,但不会分配用来存储指针所指向的数据的内存,为数据提供空间是一个独立的步骤。

例:

long *fellow;

*fellow=223323;

fellow是一个指针,上述代码没有将地址赋给fellow,而223323被存在哪里了我们也将不会知道,由于fellow没有被初始化,它可能指向任何值,并且程序都将它解释为存储223323的地址。

3、指针和数字

例:

int * pt;

pt=0XB8000000;

0XB8000000一看是地址格式,但这样赋值的话是不对的,

因为其实质上是整数,所以需要将数字转化为适当的地址类型:

pt=(int *)0XB8000000;

4、使用new来分配内存

在程序运行时分配内存

例:

int * pn=new int;

new int告诉程序,需要适合存储int的内存。new运算符根据类型来确定需要多少字节的内存。然后它找到这样的内存,并返回其地址。

声明和赋值:

int *pt=new int;

*pt=1001;

对于指针,需要指出的另一点是,new分配的内存块通常与常规变量声明分配的内存块不同,常规变量和指针所指向的值都存储在被称为栈的内存区域,而new从被称为堆或自由存储区的内存区域分配内存。

5、使用delete释放内存

delete释放的内存块最初是用new分配的

int * ps=new int;

delete ps;

这将释放ps指向的内存,但不会删除指针ps本身,可以将ps指向另一个新分配的内存块。

例如:

int test=10;
int *pt=new int;
*pt=10001;
delete pt;
pt=&test;
cout<<*pt;

根据上面这个例子我们就可以清晰地知道:

new其实就是找一块内存块给指针用,用来存地址,和前面的几种指针声明是一样的,只不过这个内存块在堆或自由存储区中,然后删除了这个内存块,指针(是一种指向)并没有被删除,然后又可以为其找到归宿。

1、一定要配对使用new和delete,否则将会发生内存泄漏;

2、不要尝试释放已经释放的内存块;

3、不能使用delete来释放声明变量所获得的内存(即不是new出来的);

6、使用new来创建动态数组

①使用new创建动态数组

int *psome=new int [10];

new元素返回第一个元素的地址,该地址被赋给指针psome

删除:delete [] psome;

方括号告诉程序,应释放整个数组,而不仅仅是指针指向的元素。

②使用动态数组

对于第i个元素,可以使用psome[i]

7、指针、数组

double wages[3] ={10000.0,20000.0,30000.0};

double * pw=wages;//这里的数组名表示数组首元素的地址

double * pw=&wages[0];

8、“->”和“.”的区别

对于访问结构体中的成员变量来说

举个例子:

struct p1{

int year;

};

1、若以这种方式创建变量:

p1 t1;

则访问year时只能是:

t1.year

2、而以这种方式创建变量:

p1 *t1=&temp;

则访问year时只能是t1->year

3、若创建了个数组变量

p1 t2[10];

则访问方式有:

①t2[0].year

②由于数组名是一个指针,则可以采用这种方式(t2+1)->year;(类似于t2[1].year)

不断更新!!!

C++疑惑解答总结(一)相关推荐

  1. [网摘]---有关int,Int32的疑惑解答

    有关int,Int32的疑惑解答 疑惑1:int.System.Int32和int32的区别 1. int32是IL中的基元类型(primary type),int和System.Int32是对int ...

  2. 有关int,Int32的疑惑解答

    疑惑1:int.System.Int32和int32的区别 1. int32是IL中的基元类型(primary type),int和System.Int32是对int32进行了封装. 2. int和S ...

  3. pd.get_dummies的使用和疑惑解答

    pd.get_dummies的使用 参考pandas官网 pandas.get_dummies(data, prefix=None, prefix_sep='_', dummy_na=False, c ...

  4. Comparator类中的compare(T o1,T o2)和compareTo()的使用与疑惑解答

    这几天做项目刚好遇到需要排序的需求,大概就是你查询一个list,然后list中保存的是map数据,你需要根据map中的若干个数据排序,比如说 List<Map<String, Object ...

  5. 栈与队列8——求最大子矩阵的大小

    题目 给定一个整形矩阵map,其中的值只有0和1,求其中全是1的所有矩形区域中,最大的矩形区域中1的数量,例如:1 1 1 0,其中最大的矩形区域有3个1,返回3. 再如: 1 0 1 1 1 1 1 ...

  6. 54. spring boot日志升级篇—logback【从零开始学Spring Boot】

    在<44. Spring Boot日志记录SLF4J>章节中有关相关的介绍,这里我们在深入的了解下logback框架. 为什么要使用logback ? --在开发中不建议使用System. ...

  7. Lucene教程具体解释

    注明:本文是由本人在开发有关基于lucene资源检索系统时的一点总结,当中一部分是自己依据开发过程自己总结的,也有部分是摘自网络,因无法获取当时摘文的地址,所以在此没有写源地址. 转载请声明出处 Lu ...

  8. 三菱fb功能块手册中文_技成周报33期 | 三菱、西门子全系列这34个问题值得一看!...

    私信小编 " 电工全套 " 获取 三菱+西门子+电工全套电子学习资料(软件.案例.文档.电子书)! 本周学员咨询的常见问题已经汇总好啦,快来看看你的疑惑解答了吗?如果你有其他解决方 ...

  9. Java程序员从笨鸟到菜鸟全部博客目录

    本文来自:曹胜欢博客专栏.转载请注明出处:http://blog.csdn.NET/csh624366188 欢迎关注微信账号:java那些事:csh624366188.每天一篇java相关的文章 大 ...

最新文章

  1. Oracle的分区操持
  2. 秘钥对使用_使用gitactions持续集成项目实例
  3. Kubernetes对象中的PersistentVolume、PersistentVolumeClaim和StorageClass的概念关系
  4. 为什么资本主义生产的一般趋势是资本有机构成的提高?2017-12-26
  5. 一直想说的,技术职业化
  6. 如何配置Smarty模板
  7. 【翻译】 Video Object Tracking using Improved Chamfer Matching and Condensation Particle Filter
  8. 组态王怎么做超级曲线_组态王显示数据并绘制曲线
  9. ai交互剧本_AI可以制作音乐,剧本和诗歌。 电影呢?
  10. AddressBook
  11. html图片查看代码实现,如何用HTML5实现图片预览和查看原图的功能
  12. spring boot新闻管理系统毕业设计源码211113
  13. Mac版本的夜神模拟器
  14. DOS命令:systeminfo
  15. word或wps的相关API脚本js操作
  16. mysql 1044_mysql重置密码和mysql error 1044(42000)错误
  17. 数独(SuDoku)介绍
  18. 除了编程语言本身,你如果还懂这 7 点,绝对可以在北上深杭拿到 15k
  19. 个人邮箱Outlook登录入口在哪?遇到登录邮箱服务器配置错误的解决办法
  20. 【图像重建】基于正交匹配追踪(OMP)算法结合小波变换是图像重建含Matlab源码

热门文章

  1. Android调用系统拨打电话
  2. 看10篇博文写点感受,不积跬步,无以至千里、不积细流,无以成江海
  3. Dockerfile RUN指令 语法解析
  4. C# VSTO(WORD) 参数设置
  5. 系统修改充电电量达到90%退出省电模式
  6. java支付宝支付Demo
  7. 寒假作业1打印沙漏总结
  8. Acwing第 61 场周赛【完结】
  9. 日语Google输入法学习
  10. repaint()函数