居然要我这种水平的人来写一份C++入门教程,属实是有点抬举我了。
不妨先让你有一处宝地写代码?
请参见https://www.bilibili.com/video/BV12DYqzUEin/,安装一个简易的轻量化的C++编辑器及编译器的集成环境(C++ IDE)。此教程中略过不表。
从基本的顺序结构开始吧!
程序的运行起始于一个整型的主函数 (main()) 。在主函数中的代码会被逐行执行。你也可以在完整的代码文件中声明一些子函数,并在主函数中予以调用。声明主函数的办法为:
int main()
{
//在这个位置写你的代码
return 0;
}
从这一段代码来看,已经出现了多个问题。我在此试着逐行解释。
变量基本类型
不同于Python, C++在声明变量时严格要求要声明变量类型。声明为整数类型的变量不可以存放浮点数或小数,声明为字符型的变量不可以存放整数或小数。
我试着列一张表格,来展示你可能会用到的一些。
类型 | 名称 | 值域 / 精度 | 占用空间 (Byte) |
---|---|---|---|
bool | bool / 布尔值 | ${0,1}$ | 1 |
char | character / 字符型 | 所有字符 | 1 |
int | interger / 整数型 | $[-2^{31},2^{31}-1]$ | 4 |
float | float / 浮点数 | 一般保证小数点后8位精确 | 4 |
double | double / 双精度浮点数 | 一般保证小数点后16位精确 | 8 |
(Ref: Type - cppreference.com)
除此之外,对于int
类型,还有不同位宽的short int, long int,及是否留有符号位的signed int, unsigned int等多种子类型。至于其原理,详见:变量 - OI Wiki.
不同的变量将占用不同的内存空间,在写代码时请注意根据数据范围,尽可能地少使用内存空间。当然打比赛除外,打比赛要的就是冗余保证过过过就好了。
回到主函数上。当我们为一个函数赋予这样的类型,是对其返回值的类型存在要求。例如,当我们在主函数中调用一个子函数,我们可以决定子函数返回一个怎样的值。对于主函数,一般返回0,所以在代码块最后存在一个return 0。(这里具体向谁返回我也没太研究清楚,可能是操作系统?)
注释
C++的注释分为单行和多行注释,注释中的内容不会被执行,也不参与程序编译。你可以在注释里放一尊大佛,祈祷你的程序能够跑起来。或者骂骂人也行,但小心被发现。
int main()
{
//这是单行注释
/*
这是多行注释,以斜杠和星号开头,以星号和斜杠结尾。
注释中的内容都不会被执行。
*/
return 0;
}
好了!现在你已经可以声明变量,完成一些基本的运算,例如加减乘除。比方说:
int main()
{
int a,b,c; //C++中,声明同一类型的多个变量时,可以用逗号分隔开
a=1,b=2; //对多个变量赋值时,也可以用逗号
c=a+b;
return 0;
}
但是当你运行一下程序,你会发现你什么都得不到。这是怎么回事?
你突然发现,你只让程序完成了计算,但是并没有命令程序把答案告诉你。换言之,程序没有告诉你运算结果的义务。于是你打算动用你作为统治者的强权暴力手段,让它告诉你运算结果。
你又发现,你不能跟他讲“快把答案告诉我!”,并且你不知道怎么逼迫他告诉你答案。
输入/输出
C++有两种主要的输入输出方式,我们分别介绍。
(Ref. C++ 语法基础 - OI Wiki)
格式化输入输出 (scanf/printf)
int main()
{
int a,b,c;
scanf("%d%d%d",&a,&b,&c);
printf("%d %d %d",a,b,c);
return 0;
}
在scanf
的使用上,需要注意,必须在后面的变量前加一个&
。这是由于scanf
接收的参数是一个在内存中的地址。
在两行代码中通用的%d
,称为类型标识符,除了%d
之外,还有%s
,%c
,%lf
等等。详见上文中本部分的Reference。
printf中,如果你不想要输出一个变量,你只需直接在引号中写上你想要输出的内容即可。类型标识符占据的位置,会在字符串之外的逗号按顺序输出。例如,你可以使用:
int main()
{
int a=1,b=1;
printf("%d个人有%d个头",a,b);
}
输出结果为:
1个人有1个头
输入输出流 (cin/cout)
int main()
{
int a,b,c;
cin>>a>>b>>c;
cout<<a<<" "<<b<<" "<<c<<endl;
return 0;
}
相较于格式化输入输出,输入输出流要简单一些,它不需要指定输入输出的内容的类型。你只需要用<<
将输出的内容连接起来即可。变量与字符串之间需要一个<<
,如上面的代码所示。
cin
/cout
的速度要慢于scanf
/printf
,且使用endl
换行的速度要慢于\n
换行。在部分场景下可能会导致程序运行时间超时。
到这里,你可能会发现,我们的代码居然仍然无法运行。这是由于scanf
、printf
、cin
、cout
都是在C++库中的内容,我们需要通过引入头文件将他们引入到代码当中来。
头文件和命名空间
scanf
和printf
被包含在stdio.h
头文件中,你需要在代码的最开头加入
#include<stdio.h>
以在程序当中使用它们。
cin
和cout
被包含在iostream
头文件中,你需要在代码的最开头加入
#include<iostream>
以在程序当中使用它们。
命名空间,aka namespace,目的是在大型项目中防止重复名称的内容指代不清。上述的四个输入输出函数,均在std
命名空间中。想要调用他们,有两种使用方法:
-
在使用时,在前面加上
std::
;例如:
std::cout<<"abc"<<endl;
-
在程序的开头写上
using namespace std;
。此时,在后面使用上述四种函数时,你只需要直接cout<<"abc"<<endl;
即可。
第一种方式较为繁杂,但在大型工程中能更严谨地区分所指代的内容;第二种方式将整个std
库引入到程序中来,在较小的项目中影响不大且更加便捷。
(Ref: C++ namespace-CSDN博客,命名空间 - OI Wiki)
好了!接下来你可以开始体验每个程序员都将走的路了。你好,世界!
为进一步明确刚才的命名空间事项,我讲述两个写法。
写法一:
#include<bits/stdc++.h>
//<bits/stdc++.h>
//aka 万能头,包含了绝大多数C++的库
//不建议在大型工程中使用万能头
using namespace std;
int main()
{
cout<<"Hello, World!"<<endl;
return 0;
}
写法二:
#include<bits/stdc++.h>
int main()
{
std::cout<<"Hello, World!"<<endl;
return 0;
}