4.1-c++-基础知识

189 阅读15分钟

helloworld

//导入系统输入输出头文件 iostream
#include <iostream>

//使用标准命名空间 std
using namespace std;

int main() {
    //将 Hello, World! 打印在屏幕上,并且进行换行
    cout << "Hello, World!" << endl;
    return 0;
}

其中:

  1. Include不属于c++函数所以没有;头文件可以参考这篇博客: 头文件不可以定义,只声明函数和变量

  2. using namespace可以为命名空间规范确定的名字。防止重复命名的功能模块,可能大型项目里会用到,期待。

其中使用namespace时,.h的头文件是用户自己命名的头文件,与此不同的是标准库文件 使用标准库的时候可以不用namespace。

也可以using具体的命名空间里的东西

多文件编译的时候使用#pragma once可以防止重复调用 .cpp最后变成.exe以及.out

第一部分是把include的东西全部复制进来,叫做编译预处理,生成.c文件
第二部分是把cpp翻译成汇编语言,叫做编译,生成.s
第三部分是把汇编语言翻译成二进制文件,生成.o或者.obj文件
第四部分是将其他第三方编译好的程序链接起来,生成.exe或者.o文件,链接也分动态链接和静态链接

因为本质上C++是C语言加了一些封装的实现,实现了面向对象的特性。

  1. 不同于python,有且仅有一个main()函数,程序在运行时会自动调用main()函数。
  2. 双斜杠"//"一直表示注释内容一直到行末。

变量和常量

变量背景

  • 内存中每个基本存储单元可以存放一个字节的数据
    • 一个字节byte存储8个比特bit
    • 内存单元地址唯一,16进制数表示

变量使用

  1. 数据类型 变量名
  2. 一个变量名唯一对应一个空间

变量命名规则:

  • 字母数字和下划线,而且区分大小写,W和w不是一个。
  • 数字不可以在首字母。
  • 关键字也就是语言特定功能的字母不可以表示变量名,因此需要确定关键字具体,参考资料
  • 关键字和函数名最好能够体现功能模块的具体。
  • 变量在初始化时应该根据数据类型进行赋值,否则将会发生错误.

python VS C++

与python不同的是需要先定义类型并且赋值 另一个不同是需要每行后面加;

常量和变量之间的关系

每个内存盒子可以存贮数据的地方叫做变量 那么存储的数据就是字面量,表示固定值。

  1. 整数字面量没有小数点和指数部分。其中十进制和八进制和十六进制。
  2. 浮点字面量表示小数,可以直接是小数点的数,或者10为底数的幂数。其中eE 都可以表示
    • eE的左侧必须要有数字
    • eE的右侧为幂次的数值,必须为整数
    • 小数可以等价表示为:6.6E-1 => 0.6630.0e0 => 30.00.01415926E3 => 14.15
  3. 字符字面量 使用单引号,'mmm'
  4. 转义符字面量
    • 也是使用单引号,'\n'而且需要是右划线,不同于注释使用/左划线
    • 所有字符都采用ASCII编码,共有128个字符。每个字符都对应着一个0~127之间的整数

A02-2-p-1.png

A02-2-p-2.png 5. 字符串字面量""

  • 使用双引号,里面也可以包含转义字符。

  • 字符串除了存储所包含的字符外,还额外包含一个结束标志'\0'

    '\0':结束符; ASCII编码对应数值为0的字符

一次尝试

 c++
 #include<iostream> 
using namespace std; 
int main() { 
    // TODO 输出三行内容,每行为4个*和一个换行符
    cout << "****" << endl;
    cout << "****" << endl;
    cout << "****" << endl;
    //两种方式打印不需要添加额外的引号。
    // cout << "****\n";
    // cout << "****\n";

    return 0;
} 
  1. 常量字符量
    • const int 或者int const都可以,且此时就需要对常量进行初始化了,后来的程序也不会改变此值。
    • 符号常量命名时参照Google 开源项目风格指南,以 “k” 开头,大小写混合

数据类型:

  • 原来基本类型就是整数浮点数这种,复合类型就是数组字符串这种带有数据结构的数据类型。

数值整数类型

  1. 整数类型分为数值整数类型字符类型
    • 数值整数用来表示没有小数部分的数字。

    • 数值整数可以按照占用内存大小分为shortintlong以及long long这四种,占用内存越大的类型能表示的数值范围就更大。

    • 同时又可以按照是否表示负值分为有符号版本和无符号版本  

    • 字符类型则专门用来存储计算机中的基本符号:英文字母、数字以及标点等。

      • short-2byte-16bit

      • int- 4byte - 32bit

      • long-至少4byte>=int,一般是4byte

      • long long=long*2

      • 一个字节8bit可以表示256个整数。

  2. 无符号只能表示正数,有符号为默认版本。也就是使用了一个Bit表示符号也就是表示的数字变小了
    • 默认状态下short等四个整数类型都是符号类型,这使得它们能够表示的最大数值减小了一半左右。  
    • 在确定变量的数值不会是负数的情况下,我们可以利用unsigned关键字,加在原有数据类型之前,创建无符号的整数类型。

字符整数类型

字符其实就是整数对应ASCII,声明char 后初始化可以赋值字符也可以赋值数字

// 用字符常量初始化一个 char 类型 char size_1 = 'L'; 
// 用整数常量初始化一个 char 类型,字符L的ASCII编码值为76 char size_2 = 76;

浮点数

  • 可以表示小数,也可以表示数值大的可以用幂级数表示的大的数字。
  • 表示float/double/long double/精度不同:有效位数和指数范围(幂次大小)。
    • 有效位数用来描述浮点数值的刻画精确程度

      例如:3.14的有效位数是3位,3.1415926的有效位数是8位。 3.14与3.140000有效位数一样,其中0表示占位符。

    • float类型通常占用4个字节,有效位数为6位

    • double类型占用的空间是float类型的两倍,即8个字节,有效位数为15位

    • long double类型一般占用16个字节的空间`

  • c++四舍五入使用的是就近一位不是所有位数

输入输出:

c中使用printf()函数和scanf()函数进行格式化的输出输入C++语言兼容C语言中的基本语句语法。

1. 库文件和命名空间
  • 格式化的意义是按指定的格式输入输出值,就是两个函数关键字的最末一个字母f(format)。

  • 标准化输入输出数据库:cstdio,而且使用标准命名空间std。好记的方法就是c-std-io。

  • #include <头文件>,这是编译预处理预处理指令include意思是找到后面跟随的文件,并且加载文件内容到程序中。在编译预处理之后,源代码文件将和头文件组合起来,在编译的下一阶段使用。

  • 命名空间是C++中的一项特性,目的是让大型程序在组合多个厂商的代码时,便于管理重复命名的功能模块。也就是处理陕西苹果和安徽苹果的命名空间。

2. 输出的格式
  • printf(格式字符串,待打印项) 数量要等于格式化字符串中待填充的空的数量,可以是变量或者常量,也可以是表达式

A02-4-p-1.png

  • 输出也可以加入修饰符具体使用如下:

A02-4-p-2.png

3. 输入的格式:
  • 程序将键盘获取的字符构成的字符串转换成对应整数类型的数值。 将输入的字符串转换成指定的数据类型printf()函数不同,scanf()函数中的地址项是变量对应的内存地址,用来装载对应的输入数据。

  • 使用scanf()函数读取基本变量类型的值,在变量名前加上一个&;使用scanf()函数将字符串读到字符数组中,则不要使用&

c++中输入输出

  1. 标准函数库iostream中提供了输入输出(I/O)功能。需要使用预处理指令include加载对应的头文件<iostream>,并且使用标准命名空间 stdcincoutiostream类的对象 cout能够识别C++中所有的基本类型,cin`能够识别C++中的字符型、整型以及浮点型数据类型。

  2. cout 输出主要是console output,以字符串的形式输出。 cout 的<<在iostream中重新定义为插入运算符,用来识别类型的。 但是在其他文件中是定义为左位移运算符。 因此,当使用iostream时,含义会变化。

  • 多个输出语句的内容之间默认进行换行,需要借助转义字符'\n'或之前学习的endl执行换行操作。

  • 使用cout进行数据输出时,我们并没有指定相应的输出格式符,系统会自动判断数据的类型并进行转化。

  • 单纯的cout输出并不具备控制输出格式的选项,不同类型数据的输出格式如下:

    • 对于char值,如果代表可打印的字符,则将作为一个字符显示在宽度为一个字符的字段中
    • 对于整型数值,将以十进制方式显示在一个刚好容纳该数字以及负号(如果有)的字段中
    • 浮点类型被显示为6位,末尾的0不显示,最终显示位数与精度无关
    • 浮点数显示,当指数大于6或者小于等于-5时,将使用科学记数法显示;字段宽度恰好容纳数字以及负号(如果有);
    • 字符串被显示在宽度等于该字符串长度的字段中。
    //字符转换为数字
    char c;
    cin >> c;
    int b = c;
    
    // printf("%d", c);
    cout << b;
    return 0;
    
  • 输出的字符串占m列,如果字符串本身大于m,则突破m的限制,将字符串全部输出;若串长小于m,则左补空格。

  1. cin输入 cin的内存存储单元可以是变量引用或者之后讲到的结构的成员 与cout对应被重定义为抽取运算符,输入功能。
  • 抽取运算符">>"从流中提取数据时,通常会跳过输人流中的空格制表符换行符等空白字符。只有在输入完数据再按回车键后,这一行数据才会形成输入流,提取进而被运算符提取。同时支持支持连续的输入,输入之间以回车键分割。如果输入的内容与存储单元定义的类型不同,那么系统返回0。也就是初始化为0。

算术运算符

  • Tips:单一的常量,也可以看作是一个简单表达式
  • 赋值的行为都是从右往左进行的
  • 左边项必须引用一个存储位置,如一个变量名
  • /和注释符号一样,如果都是整数那么也返回整数。如果是浮点数,那么结果也是浮点数。
  • %其中必须都是整数,才可以找到整数的余数
  • 算术运算符的结合律都是从左到右的
  • 表达式juice = cookie = 0;的计算顺序等价于表达式juice = (cookie = 0);
  • 赋值运算符的结合律是从右到左的

自增自减运算:

  • 前缀模式的变量将先于赋值运算符进行递增
  • 后缀模式时的变量将后于赋值运算符进行递增
  • 自增运算符需要作用在一个确定的变量上,对于由变量构成的表达式应用++,例如:(coffee + milk)++会使得程序报错,因为计算机无法找到一个明确的位置去存储递增计算之后的结果。

计算且赋值运算符

A05-1-p-1.png

位运算符与表达式

  • 每8位(bit)构成一个字节(byte)

  • 按位与运算符&

  • 按位或运算符|

  • 异或运算符^

  • 按位取反运算符~ 取反规则是0110。 对二进制码操作以后,会对二进制码取补码,也就是先取反以后+1。

  • 左移运算符<<

  • 右移运算符>> 左移相当于* 2

按位运算符只能对字符整型以及数值整型数据类型的常量变量使用,不能对浮点类型数据进行计算。 在输出时,需要加()

分支结构程序设计

  1. 关系运算符与python一样。运算符的对象可以是字符或数字,但不能是字符串。 返回布尔量:成立为1(true)代表真,不成立为0(false)代表假。 浮点数一般不会用 == 或者 != 来判断,因为可能产生表示误差
  • 比较两个浮点数是否相等,需要看两个数的差值是否小于一定的精度,比如:
    • 对于浮点数ab,如果(a - b) < 1e-6 如果值为真,就判断两个浮点数相等
  1. 逻辑表达式:
  • C++使用逻辑运算符连接多个关系表达式,从而构建逻辑表达式。

6-2.png

  1. 运算符顺序:

6-1.png 为了代码的可读性,我们在编写时一般都选择把括号加上** 逻辑表达式最后,运算符先行。 赋值-<逻辑-<关系-<算术

++a || ++b && ++c;为啥不报错

顺序条件结构

if 语句三种语法:

if if else if else if 注意点1:如果省略大括号,else默认会匹配到最近的那一个if。嵌套时一般跟上大括号。

cin >> a >> b;先给a

  • 如果if(判断条件式子是0),那么该式子的逻辑表达式为0不满足If条件,也就是说if 默认判断()条件是否为真(bool != 0),0为假。

万能头文件:bits/stdc++.h几乎包含所有的可用到的C++库函数。以后写代码就可以直接引用这一个头文件了,不需要在写一大堆vector、string、map、stack……

switch语句根据某个变量不同的值进行不同的操作

switch (变量名) { 
    case 变量可能的情况1: 执行语句1; break; 
    case 变量可能的情况2: 执行语句2; break;
    ... // 可以有任意数量的 case 语句 
    default: 执行语句n;
}
  • switch 后面的变量名:整型变量(比如int或者char),或者值为整型的表达式。

  • 可以放bool量和逻辑表达式,因此可以和if一样用

  • !case不可以像赋值语句一样一下赋值很多

  • break用于跳出语句。没有的话就会顺序执行所有语句。如果走到最后一个case,如果没有break,下一个default会执行吗。会继续执行default,所以一定要写break。 代码:

#include <bits/stdc++.h>
using namespace std; 

int max(int a, int b){
  return a > b ? a : b;
}

int main() {
  // 请补全代码,实现题目功能
  bool check, right, isosceles, equilateral, normal;
  int a, b, c, large;
  cin >> a >> b >> c;
  check = (a + b >c) && (b+ c > a) && (c+a >b);
  large = max(a,max(b,c));
  right = (a*a +b*b == large *large) || (b*b + c*c == large*large) || (c*c+ a*a ==large*large);
  isosceles = (a==b)|| (b == c)||(c == a);
  if (a == b && b == c){
      cout << "equilateral";
  }else if (check){
      if (right){
          cout << "right";
      }else if (isosceles){
          cout << "isosceles";
      }else{
          cout << "normal";
      }
  }else {
      cout << "no";
  }

  return 0;
}

循环结构:

for语法:

for (循环变量赋初始值;循环条件;更新循环变量) { 循环体 }

  • 赋初值或者函数里面都需要给变量指定类型,和Python不同。

  • 使用;和python不同。

  • 也就是更新变量以后或者赋值以后都会判断是否满足循环条件,不满足直接退出循环。 for ( ; ; ) ,这表示不用给循环变量赋初始值,也不用在每次执行后更新循环变量,同时循环的条件始终为真,也就是说每次都会选择进入循环体。

    • 如果循环体只有一句话,可以不用大括号括起来。
    • cout字符串输出数字不用"",直接输出。

break和continue:

break跳出整个模块。 continue跳出当前循环,并进入下一个循环。

#include <bits/stdc++.h>
using namespace std; 

int check(int year){
    return (year %400 == 0) || ((year % 4 == 0) && (year % 100 != 0));
}

int main() {
    // 请补全代码,实现题目功能
    int inyear;
    int sign = 0;
    cin >> inyear;
    if (inyear < 2001 || inyear > 2100){
        cout << "Invalid year!";
    }else{
        for (int i = 2004; i <= 2100;  i=i+4){
            if (i > inyear){
                break;
            }

            if (check(i) == 1){
                cout << i << endl;
                sign = 1;
            }
        }
        if (sign == 0){
            cout << "None";
        }
    }
    return 0;
}

while语句:

while (循环成立条件) { 循环体 }直到循环成立条件为假退出循环。

//不需要额外的库
    srand((unsigned)time(NULL));
    // 随机生成一个1-100的数字
    num = rand() % 100 + 1;
do while

do { 循环体 } while (循环成立条件); 至少执行一次。 while和for 都是先判断循环条件。 while(i)i 和0比较而不是大于小于0。

判断素数

#include <bits/stdc++.h>
using namespace std; 

int main() {
    // 请补全代码,实现题目功能
    int num;
    cin >> num;
    int i = 2;
    int sign = 0;
    if (num == 1){
        cout << "no";
        sign = 1;
    }
//1不是素数,2是素数。
    while(i < num){
        if (num % i == 0){
            cout << "no";
            sign = 1;
            break;
        }
        i += 1;
    }
    if (sign == 0)
        cout << "yes";

    return 0;
}

多重循环:

  • 在嵌套操作中都需要使用缩进,以增强代码可读性
  • forforforwhilewhileforwhilewhile都可以 a--先给出a的值,在把a= a -1赋值。
#include <bits/stdc++.h>
using namespace std; 

int main() {
    // 请补全代码,实现题目功能
    //由于不可以使用数组,所以使用for进行cin。
    int num;
    long int res = 1; 
    //数据过于长;
    cin >> num;
    for (int i = 1; i <= num; i++){
        int c = 1;
        cin >> c;
        for (int j = 1; j <= c; j++){
            res = res*j;
        }
        cout << res << endl;
        //输出以后再初始化!
        res = 1;
    }
    return 0;
}
  • break语句只用于循环体内和switch语句中。
#include <bits/stdc++.h>
using namespace std; 

int main() {
    // 请补全代码,实现题目功能
    int one;
    cin >> one;
    int three;
    cin >> three;
    int five;
    cin >> five;
    int ten;
    cin >> ten;
    int N;
    cin >> N;
    int res = 0;

    for (int o = 0; o <= one; o++){
        for (int t =0; t <= three; t++){
            for (int f = 0; f <= five; f++){
                for (int te = 0; te <= ten; te++){
                    if (o + t*3 + f*5 + te*10 == N){
                        res += 1;
                        break;
                    }
                    // continue;
                }
            }
        }
    }
    if (res != 0){
        cout << res;
    }else{
        cout << "no";
    }
    return 0;
}

数组:

数组的声明与定义:

  • 创建后的数组大小固定
  • 同一数组中的元素类型相同
  • 是一系列数据顺序集 元素类型 数组名称[数组长度];
  • 数组长度代表数组容纳元素的数量,必须是一个固定的整型常量,不能是变量
  • 数组名其实表示的就是第一个元素的起始地址

数组的索引: 从0开始到n-1。

  • C++数组越界时,程序一般不会产生运行错误,但是可能会导致其他后果,比如修改了无关变量的值。- 把这个元素的值赋给另一个变量: int a = sales[0];

初始化-给数组赋值:

  1. 在声明的同时,使用大括号包含对应数值,直接对整个数组初始化
  2. 在声明之后,逐个访问数组元素进行一一初始化赋值
  3. 初始化时数组长度必须确定给出。const int n =10;int a[n];可行。
  4. 对数组或者结构体赋值,使用花括号{} 5. 不可以直接copy数组使用=
int main() {
    // 请补全代码,实现题目功能
    //数组定义时长度固定,因此我们需要计算结果的长度们在输入的时候就确定。
    //否则使用删除元素的方法,目前还没找到这样的库函数
    int N, M;
    cin >> N;

    int num[N];
    for (int i = 0; i<N; i ++){
        int n = 0;
        cin >> n;
        num[i] = n;
    }
    cin >> M;
    //数字到这里才给出。所以方法一不可行。
    int sign = 0;
 
    for (int i = 0;i < N; i++){
        if (num[i] != M){
            sign += 1;
            cout << num[i] <<" ";
        }
    }

    int res[sign];
    int j = 0;
    for (int i =0; i<N; i++){
        if (num[i] != M){
            res[j] = num[i];
            j += 1;
        }
    }

    for (int j = 0; j< sign; j++){
        cout << res[j] << " ";
    }

    return 0;
}
int sales[6] = {1, 3, 5, 7, 9, 11}
int sales[] = {1, 3, 5, 7, 9, 11}

output &input:

  • 在C++中,普通的一维数组只能对单个元素进行输入输出。与python不同。 for (int i = 0; i < 12; i ++) sales[i] = 2*sales[i - 1];
#include <bits/stdc++.h>
using namespace std; 

int main() {
   // 请补全代码,实现题目功能
   long int num;
   cin >> num;
   long int ru[num + 1] ;
   for (long int i =0; i < num; i++){
       cin >> ru[i];
   }
   long int runum;
   cin >> runum;
   // long int res[num+1];
   // int sign = 0;
   for (long int j=0;j<num;j++){
       // if (sign == 0)
       //     res[j] = ru[j];
           // cout << "ru[j]"<<" ";
       if (runum>ru[j-1]&&runum<ru[j]){
           // sign = 1;
           // res[j] = ru[j];
           // continue;
           cout << runum<<" ";
       }
       cout << ru[j]<<" ";
       // else{
       //     res[j+1] =ru[j];
       // }
   }rn 0; }
//从后向前赋值数组最后留有空位子

二维数组:

int scores[5][3]; 二维数组最后一维必须有值;

访问形式是数组名称[行索引][列索引] 从 0 到 维度长度-1 元素之间使用,隔开{,}多层大括号,或者一个一维直接赋值。 int scores[5][3] = {8, 4, 6, 5, 6, 3, 3, 2, 4, 8, 7, 6, 7, 9, 8};

  • 单个元素输入输出,不同于Python。如果给出的元素数量少于本身的数量,那么后面的会被默认初始化为0与python不同的是,python是库函数读取,c++是按照cin读取。 翻转行列-先按照行列读取的顺序给数组赋值,然后找到方法读取数组。
 int hang;
   int lie;
   cin >> hang >> lie;

   int string[lie][hang];
   for (int i = 0; i< hang; i++){
       for (int j = 0; j < lie; j++){
           cin >> string[j][i];
           //数组存储的就是改变过的数组
       }
   }
   // int chstring[lie][hang];
   for (int j = 0; j < lie; j++){
       for(int i = 0;i < hang; i++){
           cout << string[j][i] <<" ";
       }
       cout << endl;
   }

字符串数组

char username[11] = {,} 使用数组还存储单个字符char;

  • ""双括号和'\0'作为结束符,所以地址储存空间长度+1。前面8个元素分别是:- 'L''a''o''W''a''n''g''\0'。。空字符串就是一个字节存贮了'\0',用""表示。

  • 字符的声明长度需要+1存贮结束符

  • 字符和字符串不同,cout是字符串形式。 'a' 和 "a" 是不一样的,前者是一个字符常量,在内存中占 11 字节,后者是一个字符串,占 22 字节的空间,第 11 个字节储存了字母 a 的内码值,第二个字节储存了 '\0'

字符数组的初始化

  • 初始化可以使用''单个字符赋值,也可以""字符串格式赋值。
    1. char userName[11] = {"LaoWang"}; // 大括号可以省略
    2. char userName[11] = "LaoWang";
    3. char userName[11] = {'L', 'a', 'o', 'W', 'a', 'n', 'g', '\0'};
    4. char userName[11] = {'L', 'a', 'o', 'W', 'a', 'n', 'g'}; // 和普通数组一样,元素个数可以省略,c++会自动识别长度为8 char userName[] = {'L', 'a', 'o', 'W', 'a', 'n', 'g', '\0'};

字符数组的cin,cout

  1. cin >> ch;
  • 输入的时候,使用cin语句,会不断的读入字符串,直到遇到一个空白字符(空格、回车或者制表符)就结束读入
  • cin向计算机输入一串字符时,输入的字符的数量应该少于已定义的字符数组的长度,否则会出现问题
  • 如果输入的字符的数量小于字符数组长度时,剩下的部分会默认补上'\0'
  1. cout << ch;
  • 从字符数组的第一个字符开始输出,直到遇到 '\0'(不会输出 '\0'

  • 如果一个字符数组中包含一个以上'\0',则遇第一个'\0'cout输出就结束

  • 字符的输入用 scanf("%c", &变量名),而输入一个字符串用 scanf("%s", 数组名)

  • scanf里,数组前不需要加&只有变量名字需要加&. printf("%c", &变量名),而输出一个字符串用 printf("%s", 数组名)

字符数组的操作:

  • 头文件#include<cstring>
    1. 连接字符串使用 strcat(s1, s2)
    2. strlen()长度,不带\0
    3. strcmp()返回字典序,s1小就小于0。
    4. strcpy。复制字符串数组不可=
    s1存的是{q, w, e, r, \0}s2存的是{a, s, \0},那么使用strcpy(s1, s2)后,s1前五位应该是{a, s, \0, r, \0}
int main() {
   // 请补全代码,实现题目功能
   char str1[100], str2[100], str3[100];
   cin >> str1 >> str2 >> str3;

   cout << str3 <<" "<< str2 <<" "<< str1;

   return 0;
}

//使用多维数组
int main() { 
   char words[3][101]; 
   for (int i=0; i<3; i++) scanf("%s", words[i]); 
   printf("%s %s %s", words[2], words[1], words[0]);
   return 0;
}

由于输入比较少可以单个输入,或者可以使用多维数组存储。

string变量类型非数组

数组必须给定长度因此可能越界。 标准模版库(Standard Template Library,STL)。

string 类型是直接把字符串当作一个整体,可以像整型变量、字符变量一样使用。

  1. # include <string>
  2. // 声明 string a; // 声明与初始化 string b = "yes";
  3. 输入输出使用cin和cout直接,遇到'\0'就停止。
  4. string也可以作为数组使用。
# include <iostream> 
# include <string> 
using namespace std; 
int main() { 
    string words[3]; 
    //string产生一个string数组
    for (int i=0; i<3; i++) 
        cin >> words[i]; 
    cout << words[2] << " " << words[1] << " " << words[0]; 
    return 0; 
}

   // 我写的
    string str1, str2, str3;
    cin >> str1>> str2 >>str3;
    cout << str3 <<" "<<str2 <<" "<< str1;

string库函数

  1. +
  2. 使用 s1.size() 或者 s1.length() 返回字符串 s1 的字符数。注意()
  3. 直接关系运算符,==, <,>
  4. 赋值= 和整形变量啥的一样

1.png

2.png

3.png

  • str.replace(3,2,str)也就是replace自己时,他会保存str原本的值,然后replace以后付给str/

函数声明/定义和调用:

必须有一个主要的函数,叫做main()函数,作为执行整个程序的入口。你可以在main()函数中去调用其他函数,同样地,其它函数之间也可以互相调用。

声明:

  • 参数是可选的,函数可能不包含参数,也可以包含很多个参数

  • 函数实参的个数,是定义该函数时传进函数的参数的个数。

  • 不返回参数,参数类型为void int MyMax(int a, int b);

定义:

声明以后定义。 如果我们函数的定义在调用前进行的话,也可以省略函数的声明这一步。

调用执行函数:

传入实际参数:

  • 全局变量,所有函数,包括main()函数都可以访问。
  • 局部变量,只有在这个函数里能访问到这个变量

参数传递 在引用传递过程中,被调函数的形式参数虽然也作为局部变量开辟了内存空间,但是这时存放的是由主调函数放进来的实参变量的地址。 // 传值传递void swap2(int &x, int &y) {--// 引用传递 void swap2(int &x, int &y)

  • 变量相关,所以传递的参数实际上是数组的地址- 在函数中修改数组里的某一个值,会在内存中直接修改这个数组。

  • 函数定义时,我们可以给函数的参数设置默认值 因此默认值可以不传递被忽略,但是也可以直接赋值就更改了。

递归函数:

递归关系(return)和递归条件(n??): 函数的函数体中又调用了它自己,这就叫做“递归函数”。

递归函数的写法有两个基本要素:

  • 递归关系

    • 比如计算某个数字的阶乘,我们知道,递归的关系就是:数字n的阶乘 = 数字n * 数字n-1的阶乘。
  • 递归的终止条件

    • 只知道递归关系是不够的,我们需要有一个递归终止的条件。在计算阶乘这个例子中,递归终止的条件是计算到数字1的阶乘的时候,函数可以直接返回数字1的阶乘就是1。更严谨的,我们可以在n小于1的时候,输出错误操作。
    int factorial(int n) { 
        if (n < 1) { 
            cout << "错误操作" << endl; 
            return -1; 
        } 
        if (n == 1) return 1; 
        else return n * factorial(n-1); 
    }

//汉诺塔递归函数
#include <iostream> 
using namespace std; 
void hanoi(int N, char source, char relay, char destination) { 
    if(N == 1) 
        cout << source << " -> " << destination << endl; 
     else {
         hanoi(N-1, source, destination, relay); 
         cout << source << " -> " << destination << endl; 
         hanoi(N-1, relay, source, destination); 
       } 
 } 
 int main() {
     int n; 
     cin >> n; 
     hanoi(n, 'A' , 'B' , 'C'); 
     return 0; 
 }

结构体:

使用结构体将一组不同类型的数据聚合成一个整体

  • 使用struct关键字
  • 每个结构体都有自己的名称
  • 注意大括号后面需要有分号;
  • 因为内存对齐的存在,结构体类型的变量的字节数不等于各成员字节数之和。
c++ 
struct Student{ int number, birth_year; string name; };

声明:

声明结构体变量的方式和声明普通变量是一样的,在声明结构体变量的时候,系统就会为它们在内存上分配空间了。此时先创建一个类别,然后声明产生该类别的具体对象要给她赋名字,并为其分配空间。

//先定义后声明,可以单个变量也可以数组批量声明对象。
struct Student{ int number, birth_year; string name; }; // 声明三个学生 Student zhang_san, li_si, wang_mazi;Student students[500];
//必须要声明Students

struct Student{ int number, birth_year; string name; } zhang_san, li_si, wang_mazi;
//定义以后不加;直接跟变量。!!

初始化:名字最好统一方便调用处理。

  1. 初始化列表和数组的初始化类似,会根据给出的元素依次初始化结构体中的每个成员。
  • 如果给出的元素小于成员数量,排在后面的就会保持没有被初始化,也无法跳过它给后面的成员初始化。 使用{}花括号。
struct Student{ int number, birth_year; string name; }; 
// 初始化一个学号为1,2000年出生,名叫 ZhangSan的学生 
Student zhang_san = {1, 2000, "ZhangSan"};

构造函数初始化。

  • 可以先在结构体内部完成一个构造函数,再调用这个构造函数来初始化结构体变量。
  • 可以在创建一个结构体变量而不向其传递某些成员变量的值时,提供默认值 函数使用()圆括号 构造函数好像必须和原结构体名字相同。

构造函数好像属于结构体内的局部变量。

  • 可以传值也可以引用传递。传值会占用额外的空间。

外界函数引用结构体变量

  • 常量引用传递。如果不想让函数更改任何成员变量值,那么可以将结构体变量作为一个常量引用传递给函数。需要在参数类型前加上const关键字。
  • 也就是引用传递了,但是不改变原来的对象的属性。 函数对该结构体的引用对象可以随意取名字,为局部变量。
#include <iostream>
using namespace std;

struct Student{    
    int number, birth_year;
    string name;
};

// TODO 完成该函数,展示学生的学号、姓名和出生年份
void showStudent(const Student& CYIN) {
    cout << "Student Number : " << CYIN.number<< endl;
    cout << "Name : " << CYIN.name << endl;
    cout << "Birth Year : " << CYIN.birth_year<< endl;
}

int main() {
    Student zhang_san = {1, 2000, "ZhangSan"};
    
    // 调用函数
    showStudent(zhang_san);
    return 0;
}

结构体定义和使用如下:

struct Student{ int number, birth_year; string name; 
// 在结构体里定义构造函数 
// 在初始化时所有学生的出生年份都被设置为2000 
// 可以传入两个参数,分别代表学号和姓名,如果不传入参数,默认学号为0,姓名为"" 
    Student (int num=0, string n="") { number = num; birth_year = 2000; name = n; } 
}; 
// 初始化时只用传递两个参数即可 
Student li_si(2, "LiSi");

调用函数:已经确定了一个对象以后,该对象拥有了该结构下的所有属性。直接.

#include <bits/stdc++.h>
using namespace std; 

struct Student{
    string name;
    char sex;
    int age;
};

int main() {
    // 请补全代码,实现题目功能
    int n;
    cin >> n;
    Student stu[n];
    Student temp,res;
// same time;

    cin >> temp.name;
    cin >>temp.sex;
    cin >> temp.age;
    // res.name = temp.name;
    // res.sex = temp.sex;
    // res.age = temp.age;
    res = temp;

    for (int i = 2; i <= n; i++){
        cin >> temp.name;
        cin >> temp.sex;
        cin >> temp.age;
        if (temp.age > res.age){
            // res.name = temp.name;
            // res.sex = temp.sex;
            // res.age = temp.age;
            res = temp;
        }
    }
    cout << res.name <<" ";
    cout << res.sex << " ";
    cout << res.age;
    return 0;
}
//use tuple's index to save and output
#include <iostream> 
#include <string> using namespace std; 
struct Student { string name; char gender; int age; };
int main() { 
    int num, max_age, max_age_idx; 
    cin >> num;
    string n; 
    char g;
    int a;
    Student students[11];
    for (int i=0; i<num; i++) { 
        cin >> n >> g >> a;
        students[i] = {n, g, a};
    } 
    max_age = 0;
    max_age_idx = 0; 
    for (int i=0; i<num; i++) {
        if (students[i].age > max_age) { 
            max_age = students[i].age; max_age_idx = i; 
        } 
    } 
        cout << students[max_age_idx].name << " " << students[max_age_idx].gender << " " << students[max_age_idx].age; 
    return 0; 
}