【C++】前言和C++入门(上)

1.什么是C++?

  • C++是从C语言中生长出来的,C/C++不分家。
  • C++是一种计算机高级程序设计语言,由C语言扩展升级而产生 ,最早于1979年由本贾尼·斯特劳斯特卢普(C++语言之父)在AT&T贝尔工作室研发。
  • C++既可以进行C语言的过程化程序设计,又可以进行以抽象数据类型为特点的基于对象的程序设计,还可以进行以继承和多态为特点的面向对象的程序设计。
  • C++擅长面向对象程序设计的同时,还可以进行基于过程的程序设计。
  • C++几乎可以创建任何类型的程序:游戏、设备驱动程序、HPC、云、桌面、嵌入式和移动应用等。
    总的来说,c++是c语言的升级版,更加实用。在众多编程语言中,c++不是最简单的,但是确实数一数二的非常实用的。

2.如何学习C++?

以下引用自2010年8月号《程序员》刊登的拙文《C++强大背后》最后一段

  • 第一个层次,C++基础 (平平常常)
    挑选一本入门书籍,如《C++ Primer》、《C++大学教程》或Stroustrup撰写的经典《C++程序设计语言》或他一年半前的新作《C++程序设计原理与实践》,而一般C++课程也止于此,另外《C++ 标准程序库》《The C++ Standard Library Extensions》可供参考;
  • 第二个层次,正确高效的使用C++ (驾轻就熟)
    此层次开始必须自修,阅读过《(More)Effective C++》、《(More)Exceptional C++》、《Effective STL》及《C++编程规范》等,才适宜踏入专业C++开发之路;
  • 第三个层次,深入解读C++ (出神入化)
    关于全局问题可读《深入探索C++对象模型》、《Imperfect C++》、《C++沉思录》、《STL源码剖析》,要挑战智商,可看关于模版及模版元编程的书籍如《C++Templates》、《C++设计新思维》、《C++模版元编程》;
  • 第四个层次,研究C++ (返璞归真)
    阅读《C++语言的设计和演化》、《编程的本质》(含STL设计背后的数学根基)、C++标准文件《ISO/IEC 14882:2003》、C++标准委员会的提案书和报告书、关于C++的学术文献。由于我主要是应用C++,大约只停留于第二、三个层次。然而,C++只是软件开发的一环而已,单凭语言并不能应付业务和工程上的问题。建议读者不要强求几年内“彻底学会C++的知
    识”,到达第二层左右便从工作实战中汲取经验,有兴趣才慢慢继续学习更高层次的知识。

大部分的我们学到第二、三层次已经超级超级厉害了,胜任大部分工作没问题。只有像C语言之父、C++编译器这种佬才能胜任第四个层次,可以说自己可以开发语言了。
还是那句话:道阻且长,行则将至!!!
知识是枯燥乏味的,但我们的未来是光明的‘power’


书籍推荐
1.入门阶段,随便找一本简单的书快速入门,《高质量程序设计指南—C++/C语言》就挺适合的,可以简单快速了解C++的语法特性。
2.当C++学习过半之后,大概继承和多态学完,建议《Effective C++》,该书以建议的方式告诉你如何写出更好的C++程序,看和不看差别非常大。《C++ Prime》可以当成工具书对待,当字典使用,有不清楚的语法特性可以快速去查。
3.中后期:《STL源码剖析》将六大组件逐一剖析,看完之后对STL的设计框架以及内部实现原理有更深的认识,面试时可以游刃有余和面试官交锋。有一定难度,如果基础知识掌握不扎实,不建议看,强烈建议好好把基础知识打扎实。


3.C++关键字

ps:C++(C++98)总计63个关键字,C语言32个关键字。详细内容见博客
在这里插入图片描述
注意:false和true并不是C语言的关键字,是C++关键字。

4.命名空间

看如下代码,出现报错

报错原因:<stdlib.h>是C 标准库中的一个头文件,提供了许多通用工具函数,其中就包含了rand()函数且存在于全局作用域。这些变量、函数和类的名称有可能与我们自己对变量、函数和类的命名产生冲突。
同时,仅依靠C语言无法解决该问题,本贾尼·斯特劳斯特卢普就引入了C++中的namespace关键字。

使用命名空间的目的是对标识符的名称进行本地化,以避免命名冲突或名字污染。

4.1命名空间定义

使用到namespace关键字,后面跟命名空间的名字(自定义),然后接一对{}即可,与结构体不同在于}后无;符号。{}中即为命名空间的成员。
注意:一个命名空间就定义了一个新的作用域叫做命名空间域,命名空间中的所有内容都局限于该命名空间中。在编译器查找时,先在局部域(自家菜地),接着到全局域(野地),默认不会到命名空间(张爷爷的菜地)去找。

这就需要自己限定作用域,引入 域作用限定符

namespace namee
{
	// 命名空间中可以定义变量/函数/类型/命名空间(即可嵌套)
 	rand = 1;	//调用时 namee::rand
 	int Add(int left, int right)	//调用时 namee::Add()
		{
			return left + right;
		}
	struct Node		//调用时 struct namee::Node node
		{
			struct Node* next;
			int data;
		};
	namespace nameee
	{
		int printf = 1;		//调用时 namee::nameee::printf
	}
}

同一个工程中允许存在多个相同名称的命名空间,编译器最后会合成同一个命名空间中。
ps:一个工程中的test.h和test.cpp中两个相同名称的命名空间会被合并成一个
当然,如果这多个相同名称的命名空间内部命名冲突,解决办法一:人为修改。解决办法二:嵌套。

4.2命名空间的使用
namespace namee
{
	// 命名空间中可以定义变量/函数/类型/命名空间
	int a = 0;
	int b = 1;
	int Add(int left, int right)
	{
		return left + right;
	}
	struct Node
	{
		struct Node* next;
		int data;
	};
	namespace nameee
	{
		int printf = 1;		
	}
}
  • 加命名空间名称及作用域限定符
int main()
{
	struct namee::Node N;
    printf("%d\n", namee::a);
    printf("%d\n", namee::Add(1,1));
    printf("%d\n", namee::nameee::printf);
    return 0;    
}
  • 使用using namespace 命名空间名称 展开
using namespce namee;
int main()
{
   printf("%d\n", b);
   Add(10, 20);
   return 0;    
}

这里的展开和头文件的展开不一样,这里是指在编译器默认查找时,先在局部域(自家菜地),接着到全局域(野地),后又会到命名空间域(张爷爷的菜地)去找。
这就有了展开命名空间的坏处------容易发生冲突,所以尽可能不要随意展开。

  • 使用using将命名空间中某个成员引入
using namee::b;
//假设b经常被使用,a不经常使用
int main()
{
   printf("%d\n", namee::a);
   printf("%d\n", b);
   printf("%d\n", b+1);
   printf("%d\n", b+2);
   return 0;    
}

5.C++输入&输出

C++输入
#include<iostream>
using namespace std;
//要使用 cin 和 cout 就必须要加上以上两条语句

1.使用cout标准输出对象(控制台)和cin标准输入对象(键盘)时,必须包含< iostream >头文件以及按命名空间使用方法使用std。即+std的方式。
3.是<stdio.h>的进阶版,scanf和printf仍能使用。
4.<<是流插入运算符,>>是流提取运算符。可以简单理解为输出时使用<<,输入时使用>>。
5.endl是特殊的C++符号,表示换行输出,他们都包含在包含头文件中。换行还可以(‘\n’),且比endl快。
6.使用C++输入输出更方便,不需要像printf/scanf输入输出时那样,需要手动控制格式(%d、%c、%s)。C++的输入输出可以自动识别变量类型。

std命名空间的使用惯例:
std是C++标准库的命名空间,如何展开std使用更合理呢?

  1. 在日常练习中,建议直接using namespace std即可,这样就很方便。
  2. using namespace std展开,标准库就全部暴露出来了,如果我们定义跟库重名的类型/对
    象/函数,就存在冲突问题。该问题在日常练习中很少出现,但是项目开发中代码较多、规模
    大,就很容易出现。所以建议在项目开发中使用,像std::cout这样使用时指定命名空间 +
    using std::cout展开常用的库对象/类型等方式。
1.cin >>

cin对空白字符的处理与scanf一致。即:跳过开头空白字符,遇到空白字符停止读取,且空白字符(包括换行符)残留在缓冲区。
不能用cin语句把空格字符和回车换行符作为字符输入给字符变量,它们将被跳过。
接受一个字符串,遇“空格”、“TAB”、“回车”都结束。
如果想将空格字符或回车换行符(或任何其他键盘上的字符)输入给字符变量,可以用一些函数,下面有讲。

一个cin语句可以分写成若干行。如 cin>>a>>b>>c>>d;
可以写成
   cin>>a 	//注意行末尾无分号
   >>b 		//这样写可能看起来清晰些
   >>c
   >>d;
也可以写成
   cin>>a;
   cin>>b;
   cin>>c;
   cin>>d;
以上3种情况均可以从键盘输入: 1(空格)2(空格)3(空格)4 ↙
也可以分多行输入数据:
   12(空格)3↙
   4↙
在用cin输入时,系统会根据变量的类型从输入流中提取相应长度的字节。
所以可以如下输入
   char c1,c2;
   int a;
   float b;
   cin>>c1>>c2>>a>>b;
在键盘上输入:1(空格)2(空格)34(空格)56.78↙
//cin >> a, b, c 这种写法错误
2.cin.get()

用法1: cin.get(字符变量名)可以用来接收字符

用法2:cin.get(字符数组名,接收字符数目)用来接收一行字符串(不能接收回车),可以接收空格

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

cin.getline()实际上有三个参数,cin.getline(接受字符串,接受个数,结束字符),当第三个参数省略时,系统默认为’\0’。当然,也可以是其他自定义字符。

4.getline() // 接受一个字符串,可以接收空格并输出,需包含string头文件
5.gets() // 接受一个字符串,可以接收空格并输出,需包含string头文件
6.getchar() //接受一个字符,需包含string头文件

getchar()是C语言的函数,C++也可以兼容,但是尽量不用或少用;

C++输出
一个cout语句可以分写成若干行。如 cout<<"This is a simple C++ program."<<endl;
可以写成
   cout<<"This is "  //注意行末尾无分号
   <<"a C++ "
   <<"program."
   <<endl; //语句最后有分号
也可写成多个cout语句,即
   cout<<"This is "; //语句末尾有分号
   cout <<"a C++ ";
   cout <<"program.";
   cout<<endl;
以上3种情况的输出均为
This is a simple C++ program.
在用cout输出时,用户不必通知计算机按何种类型输出,系统会自动判别输出数据的类型,使输出的数据按相应的类型输出。
// cout << a,b,c;这种写法错误
进制输出
#include <iostream>
#include <iomanip>//新库
using namespace std;
int main(){
	int i = 90;
	cout << i << endl;
	cout << dec << i << endl;//十进制(效果和默认一样)
	cout << oct << i << endl;//八进制输出
	cout << hex << i << endl;//十六进制输出(字母默认是小写字母)
	cout << setiosflags(ios::uppercase);//将字母大写输出
	cout << hex << i << endl;//十六进制输出(大写字母)
	cout << setbase(8) << i << endl;
}
//结果:90 90 132 5a 5A 132

std::oct 、 std::dec 、 std::hex ,这三个控制符包含在库 < iostream > 中
setbase(n) 表示以 n 进制显示,包含在库 < iomanip > 中,n 只能取 8, 10, 16 三个值。
setiosflags(ios::uppercase) 表示将字母大写输出,包含在库 < iomanip > 中。

输出数字位数的控制
#include <iostream>
#include <iomanip>//新库
using namespace std;
int main(){
	double i = 3333.1415926;
	cout << i << endl;//3333.14(默认6位)
	cout << setprecision(9) << i << endl;//3333.14159
	cout << setiosflags(ios::fixed);
	cout << i << endl;//3333.141592600这是因为double的精度比较高
	cout << fixed << setprecision(3) << i << endl;//3333.142
	cout << setprecision(9) << fixed <<  i << endl;//3333.141592600
}

可以看出,C++默认浮点数输出有效位数是 6 位
1.使用 setprecision(n) 即可设置浮点数输出的有效位数(若前面整数位数大于 n 位,使用科学计数法输出)
2.使用 setiosflags(ios::fixed) 或 fixed,表示对小数点后面数字的输出精度进行控制
所以,和 setprecision(n) 结合使用即可设置浮点数小数点后面数字的输出精度,位数不足的补零。

因为C++与C是兼容的,如果你感觉使用printf控制输出格式顺手的话没问题!

输入输出这里参考的博客:
https://blog.csdn.net/Dr_Myst/article/details/123164599
https://blog.csdn.net/qq_35481167/article/details/82792103(强制显示小数点和正负号、设置宽度和对齐方式)
https://www.cnblogs.com/shikamaru/p/5826117.html

6.缺省参数

6.1 缺省参数概念

缺省参数是声明或定义函数时为函数的参数指定一个缺省值(可以缺少、省略)。在调用该函数时,如果没有指定实参则采用该形参的缺省值,否则使用指定的实参。

void Func(int a = 0)
{
	cout<<a<<endl;
}
int main()
{
	Func();     // 没有传参时,使用参数的默认值
	Func(10);   // 传参时,使用指定的实参
	return 0;
}
6.2 缺省参数分类
  • 全缺省参数
void Func(int a = 10, int b = 20, int c = 30)
{
    cout<<"a = "<<a<<endl;
    cout<<"b = "<<b<<endl;
    cout<<"c = "<<c<<endl;
}
int main()
{
 Func(1,2,3);//1 2 3
 Func(1,2);//1 2 30
 Func(1);//1 20 30
 Func();//10 20 30
 Func(1, ,3)//这是错误的,必须顺序传,不能跳跃,与下面的半缺省参数必须从右往左依次来给出相协调、呼应。
 }
  • 半缺省参数
void Func(int a, int b = 10, int c = 20)
{
    cout<<"a = "<<a<<endl;
    cout<<"b = "<<b<<endl;
    cout<<"c = "<<c<<endl;
}
  1. 半缺省参数必须从右往左依次来给出,不能间隔着给。就不能void Func(int a=10, int b = 10, int c )
  2. 缺省参数不能在函数声明和定义中同时出现。如果声明与定义位置同时出现,恰巧两个位置提供的值不同,那编译器就无法确定到底该用那个缺省值。
  3. 缺省值必须是常量或者全局变量
  4. C语言不支持(编译器不支持)

今天就到这了!
持续更新中…
有帮助的收藏一下吧!

  • 20
    点赞
  • 21
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值