参考B站视频教程:零基础学习Linux编程之ubuntu系统下C++编译器安装_哔哩哔哩_bilibili
g++
$ g++ test001.cpp -o hello # -o to name the file as hello
$ ./hello
gcc
注意使用时若要用来编译c++文件,用到std库时应该写为:
$ gcc test001.cpp -lstdc++ -o hello
clang
$ clang++ test001.cpp -o hello
# 或:
$ clang test001.cpp -lstdc++ -o hello
注意clang的版本问题,建议不要使用默认的6.0版本
cmake
使用cmake首先要创建一个文件夹,本例子中为hello_project
$ mkdir hello_project
$ cd hello_project/
./hello_project$ touch CMakeLists.txt
在CMakeLists.txt里编辑如下:
#CMakeLists.txt //filename
PROJECT(hello_project) // project name
ADD_EXECUTABLE(hello test001.cpp) //exe name and the cpp name
然后在终端里输入:
./hello_project$ cmake . # . 表示当前目录
./hello_project$ make
./hello_project$ ./hello
若不想写命令号,也可以GUI里写
$ cmake-gui
常用流程
上文中的过程太简单,且生成的文件比较乱,这里介绍的才是常用流程:
创建项目文件夹:hello_project
在项目文件夹中创建基本文件夹和文件:
文件夹: build
文件: CMakeLists.txt
#CMakeLists.txt #文件名称 cmake_minimum_required (VERSION 3.10.2) #规定最低版本 PROJECT(hello_project) #项目名称 ADD_SUBDIRECTORY(src) #添加子目录
- Cmake命令之cmake_minimum_required介绍 - 简书
文件夹: src,其中包含文件:
代码文件:test001.cpp
CMakeList.txt
#CMakeLists.txt ADD_EXECUTABLE(hello test001.cpp)
在build文件夹中打开终端:
$ cmake .. # .. 表示CMakeLists.txt文件在上一层目录 $ make
此时,build中的src文件夹内出现hello 可执行文件
$ ./hello
另一种写CMakeLists.txt的方式:只写项目文件夹中的那一个CMakeLists.txt:
#CMakeLists.txt #文件名称 cmake_minimum_required (VERSION 3.10.2) #规定最低版本 PROJECT(hello_project) #项目名称 #include_directories(./src) # 包含src文件夹,这句有没有都可以 aux_source_directory(./src SRCS) # 将src目录下所有源文件添加到SRCS变量中 ADD_EXECUTABLE(hello ${SRCS}) # 将SRCS中的文件编译成一个可执行文件
- 注意,在复制上述内容时,每行结尾会有空格,若直接编译会出现下面的错误:
Parse error. Expected a command name, got unquoted argument with textu
写好该文件后,在build文件夹里输入:
$ cmake .. $ make $ ./hello
安装步骤省略
命令行打开:
$ code
要安装C/C++、CMake插件
可以在vscode 的终端中用上述同样的办法进行编译
(过程省略)
(视频里讲的都是clion里的操作)
C++ 标准库参考 | Microsoft Docs
C 运行时库参考 | Microsoft Docs
在同一个文件夹中,写一个.h文件用于声明,写一个同名.cpp用来实现.h文件中的方法
示例:
demo.h文件:
//定义类Demo class Demo { public: // 公开访问 void Hello(const char *); //定义方法Hello,void代表没有返回值 };//注意这里有个分号
demo.cpp文件:
#include "demo.h" #include
using namespace std; void Demo::Hello(const char *str) { cout << "Hello, Demo " << str << "\n"; } 在程序demo_test.cpp中调用该类:
# include "demo.h" //包含类头文件 int main(int argc, char *argv[]){ Demo objDemo; //定义Demo对象 objDemo.Hello("world"); //调用成员函数Hello,传入参数world return 0; }
使用g++编译:
$ g++ demo_test.cpp demo.cpp -o demo $ ./demo
(即常用的写方法的流程,直接在程序文件中写即可,不用写在单独的文件中)
# 生成可执行文件时,要加个-g
$ g++ -g demo_test.cpp demo.cpp -o demo
$ gdb demo # 使用gdb运行一下
$ # 显示reading symbols from demo 表示可以正常读取程序的索引符号
$ (gdb) b 14 # 在14行设置断点
$ (gdb) b 15 # 在15行设置断点
$ (gdb) r # 启动程序,此时会停在断点14行
$ (gdb) s # 进入当前类的方法里
$ (gdb) print(str) #在当前类的位置打印变量值
指令含义:
命令 | 解释 | 示例 |
---|---|---|
file <文件名> | 加载被调试的可执行程序文件。因为一般都在被调试程序所在目录下执行GDB,因而文本名不需要带路径 | (gdb) file gdb-sample |
r | Run的简写,运行被调试的程序。如果此前没有下过断点,则执行完整个程序;如果有断点,则程序暂停在第一个可用断点处。 | (gdb) r |
c | Continue的简写,继续执行被调试程序,直至下一个断点或程序结束 | (gdb) c |
b <行号> b <函数名称> b *<函数名称> b *<代码地址> |
b: Breakpoint的简写,设置断点。两可以使用“行号”“函数名称”“执行地址”等方式指定断点位置。 其中在函数名称前面加“*”符号表示将断点设置在“由编译器生成的prolog代码处”。 如果不了解汇编,可以不予理会此用法。 |
(gdb) b 8 |
(gdb) b main |
||
(gdb) b *main |
||
(gdb) b *0x804835c |
||
d [编号] | d: Delete breakpoint的简写,删除指定编号的某个断点,或删除所有断点。断点编号从1开始递增。 | (gdb) d |
s,n | s: 执行一行源程序代码,如果此行代码中有函数调用,则进入该函数; | |
n: 执行一行源程序代码,此行代码中的函数调用也一并执行。 |
||
s 相当于其它调试器中的“Step Into (单步跟踪进入)”; |
||
n 相当于其它调试器中的“Step Over (单步跟踪)”。 |
||
这两个命令必须在有源代码调试信息的情况下才可以使用(GCC编译时使用“-g”参数)。 |
(gdb) s | |
(gdb) n |
||
si,ni | si命令类似于s命令,ni命令类似于n命令。所不同的是,这两个命令(si/ni)所针对的是汇编指令,而s/n针对的是源代码。 | (gdb) si |
(gdb) ni |
||
p | Print的简写,显示指定变量(临时变量或全局变量)的值。 | (gdb) p i |
(gdb) p nGlobalVar |
||
display ... | ||
undisplay <编号> | display,设置程序中断后欲显示的数据及其格式。 | |
例如,如果希望每次程序中断后可以看到即将被执行的下一条汇编指令,可以使用命令 |
||
“display /i pc”其中pc 代表当前汇编指令,/i 表示以十六进行显示。当需要关心汇编代码时,此命令相当有用。 | ||
undispaly,取消先前的display设置,编号从1开始递增。 | (gdb) display /i $pc | |
(gdb) undisplay 1 |
||
i | Info的简写,用于显示各类信息,详情请查阅“help i”。 | (gdb) i r |
q | Quit的简写,退出GDB调试环境。 | (gdb) q |
help [命令名称] | GDB帮助命令,提供对GDB名种命令的解释说明。 | |
如果指定了“命令名称”参数,则显示该命令的详细说明;如果没有指定参数,则分类显示所有GDB命令,供用户进一步浏览和查询。 |
(gdb) help display |
C++中的cin以及stringstream_flow_specter的博客-CSDN博客
使用分隔符表示一个输入的结束。
cin
读取成功后,字符后面的分隔符留在缓冲区中,cin>>
不对其进行处理
分隔符有:
- 空格(space)
- tab(tab)
- 换行(new-line character)
但是,如果缓冲区中的第一个字符是分隔符时,cin
会将其忽略并清除// i/o example #include
using namespace std; int main () { int i; cout << "Please enter an integer value: "; cin >> i; cout << "The value you entered is " << i; cout << " and its double is " << i*2 << ".\n"; return 0; } 输出为:
Please enter an integer value: 702 The value you entered is 702 and its double is 1404.
但是,如果键盘输入的i不是int类型呢?那么就会导致错误,导致i没有被正确的赋值。
stringstreams
则会更好的处理这种情况。notes: Most programs are expected to behave in an expected manner no matter what the user types, handling invalid values appropriately.
cin>>a>>b
等价于:
cin >> a; cin >> b;
cin and strings
cin
也可以用来读取string
:string mystring; cin >> mystring;
但是,我们知道
cin
经常会处理分隔符,因此在此就限制了string只能是连续的word,而不能是phrase 或者sentence。为了进一步的能够通过
cin
输入一段phrase或者sentence,引入了一个新的函数:getline
,该函数接收两个参数,第一个参数为cin
,第二个参数则为string
变量,见以下示例:#include
#include using namespace std; int main () { string mystr; cout << "What's your name? "; getline (cin, mystr); //第一个变量是cin,第二个是string变量 cout << "Hello " << mystr << ".\n"; cout << "What is your favorite team? "; getline (cin, mystr); // 在第二次使用getline的时候,程序只是简单的replace the previous content with the new one that is introduced. cout << "I like " << mystr << " too!\n"; return 0; } 输出为:
What's your name? Homer Simpson Hello Homer Simpson. What is your favorite team? The Isotopes I like The Isotopes too!
此时,逐行的换行通过 press ENTER(or RETURN)来实现。
notes: Unless you have a strong reason not to, you should always use getline to get input in your console programs instead of extracting from cin.
stringstream
标准头文件
定义了一种称为stringstream的类型,该类型允许将字符串视为流,从而允许以与在cin和cout上执行的方式相同的方式从字符串中提取或插入字符串。
此功能对于将字符串以及数值之间的相互转换非常有用,即,可以间接的从标准输入中获取数值。比如字符串到数值的转换:
string mystr ("1204"); int myint; stringstream(mystr) >> myint;
再比如:
// stringstreams #include
#include #include using namespace std; int main () { string mystr; float price=0; int quantity=0; cout << "Enter price: "; getline (cin,mystr); stringstream(mystr) >> price; cout << "Enter quantity: "; getline (cin,mystr); stringstream(mystr) >> quantity; cout << "Total price: " << price*quantity << endl; return 0; } 输出为:
Enter price: 22.25 Enter quantity: 7 Total price: 155.75
这相对于直接用
cin
输入数值的好处就是:
通过这种获取整行并提取其内容的方法,将获取用户输入的过程与将其赋给数值变量的两步操作分开。
cin/getline/getchar 用法与区别
int a = 0;
string b = {0};
string c = "";
printf("请输入一个字符(getchar):\n");
a = getchar();
printf(“你输入的是:%d\n”,a-48);
getchar(); // 用来等待回车(或任意键)
printf("请输入一个字符(getline):\n"); getline(cin,b); printf(“你输入的是:%s\n”, b.c_str()); //b.c_str() getchar(); // 用来等待回车(或任意键)
printf("请输入一个字符(cin):\n"); cin >> c; printf(“你输入的是:%s\n”,c); getchar(); // 用来等待回车(或任意键)
> #include
> int main (void){
> int n;
> pos_1:
> printf("请输入一个正整数:");
> scanf("%d",&n);
> if(n<0)
> {
> printf("输入错误!\n");
> goto pos_1;
> }
> printf("成功输入正整数:%d\n",n);
> return 0;
> }