Ubuntu中学习C++ 笔记

参考B站视频教程:零基础学习Linux编程之ubuntu系统下C++编译器安装_哔哩哔哩_bilibili

Chapter 1 开发环境搭建

1. 常用编译器:

  • 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

2. CMake常用指令

  • 常用流程

    • 上文中的过程太简单,且生成的文件比较乱,这里介绍的才是常用流程:

      1. 创建项目文件夹:hello_project

      2. 在项目文件夹中创建基本文件夹和文件:

        • 文件夹: build

        • 文件: CMakeLists.txt

          #CMakeLists.txt    #文件名称
          cmake_minimum_required (VERSION 3.10.2)    
          #规定最低版本
          PROJECT(hello_project)    #项目名称
          ADD_SUBDIRECTORY(src)    #添加子目录
        • 文件夹: src,其中包含文件:

          • 代码文件:test001.cpp

          • CMakeList.txt

            #CMakeLists.txt
            ADD_EXECUTABLE(hello test001.cpp)
      3. 在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

3. 开发工具-vscode

  • 安装步骤省略

  • 命令行打开:

    $ code
  • 要安装C/C++、CMake插件

  • 可以在vscode 的终端中用上述同样的办法进行编译

4. 安装Qt5

(过程省略)

5. 代码的注释与断点调试运行

(视频里讲的都是clion里的操作)

6. 开发文档

C++ 标准库参考 | Microsoft Docs

C 运行时库参考 | Microsoft Docs

Chapter 2 C++基本语法

1. 类和方法的定义与调用

  • 在同一个文件夹中,写一个.h文件用于声明,写一个同名.cpp用来实现.h文件中的方法

  • 示例:

    • demo.h文件:

      //定义类Demo
      class Demo
      {
          public:    // 公开访问
              void Hello(const char *);
              //定义方法Hello,void代表没有返回值
      };//注意这里有个分号
    • demo.cpp文件:

      #include "demo.h"
      #include <iostream>
      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

2. 非类方法编写与变量定义

(即常用的写方法的流程,直接在程序文件中写即可,不用写在单独的文件中)

3. 变量-声明与初始化

  • 方法内写的变量为局部变量,写在方法外的是全局变量

4. 用GDB调用C++程序进行调试

  • # 生成可执行文件时,要加个-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

5. cin/getline/stringstream

C++中的cin以及stringstream_flow_specter的博客-CSDN博客

使用分隔符表示一个输入的结束。cin读取成功后,字符后面的分隔符留在缓冲区中,cin>>不对其进行处理
分隔符有:

  1. 空格(space)
  2. tab(tab)
  3. 换行(new-line character)
    但是,如果缓冲区中的第一个字符是分隔符时,cin会将其忽略并清除
// i/o example

#include <iostream>
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 <iostream>
#include <string>
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

标准头文件<sstream>定义了一种称为stringstream的类型,该类型允许将字符串视为流,从而允许以与在cin和cout上执行的方式相同的方式从字符串中提取或插入字符串。

此功能对于将字符串以及数值之间的相互转换非常有用,即,可以间接的从标准输入中获取数值。比如字符串到数值的转换:

string mystr ("1204");
int myint;
stringstream(mystr) >> myint;

再比如:

// stringstreams
#include <iostream>
#include <string>
#include <sstream>
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(); // 用来等待回车(或任意键)

6. 使用vscode进行断点调试

  • 要安装插件C/C++

7. sleep() 在头文件 unistd.h 里

  • linux里,括号里单位为秒

8. goto语句(无条件转移)

> #include<stdio.h>
> 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;
> }

猜你喜欢

转载自blog.csdn.net/aniclever/article/details/123224997