C/C++基础语法

C/C++基础语法

文章目录

  • C/C++基础语法
    • 头文件
    • 经典问题
      • 链表
        • 链表基础操作
      • 秒数转换
      • 闰年
      • 斐波那契数列
      • 打印n阶菱形
        • 曼哈顿距离
        • 菱形图案的定义
        • 大数计算
    • 输入输出
      • 格式化输入输出
      • `getline()`函数解决`cin`只读入一个单词的问题
      • fgets读入整行
      • 输出字符数组(两种方式puts和printf)
    • 运算符
      • 赋值运算符
    • Switch
    • 循环
      • 处理未知数量输入的几种常见方法
      • for-each
    • 字符
      • 字符数组的常用操作
    • 字符串String
      • 基本概念
      • 其他数据类型转变为字符串`to_string()`
      • 字符串连接
      • 字符串判空
      • 字符串长度
      • 字符串输入输出
      • string的比较:
      • 为string对象赋值:
      • 两个string对象相加:
      • 字面值和string对象相加:
      • 遍历数组
    • 数组
      • 初始化memset
        • 函数原型
        • 参数
        • 返回值
        • 使用示例
        • 注意事项
      • 数组复制memcpy
        • 函数原型
        • 参数
        • 返回值
        • 使用示例
        • 注意事项
    • 函数
      • 多维数组形参的写法
    • 类与结构体
      • 类与结构体的定义与使用
      • 构造函数
    • 指针和引用
    • STL

参考资料:

  • AcWing
  • https://www.w3schools.com/cpp/
  • https://cui-jiacai.gitbook.io/c+±stl-tutorial/
  • https://www.youtube.com/watch?v=RRVYpIET_RU
  • https://takeuforward.org/c/c-stl-tutorial-most-frequent-used-stl-containers/

头文件

#include <cmath>

经典问题

链表

#include <iostream>

using namespace std;

struct Node
{
    int val;
    Node *next;

    Node(int _val) : val(_val), next(NULL) {} // 空指针
};

int main()
{
    Node node = Node(1); // 定义了一个node类型的变量
    Node *p = &node;//定义完之后用指针指向
}

C++中可以直接生成一个结构体,然后把这个结构体放到指针p中

 Node *p = new Node(1); // 我定义了一个Node类型的变量,他的返回值是这个变量的地址

在这里插入图片描述

#include <iostream>

using namespace std;

struct Node
{
    int val;
    Node *next;

    Node(int _val) : val(_val), next(NULL) {} // 空指针
};

int main()
{

    Node *p = new Node(1); // 我定义了一个Node类型的变量,他的返回值是这个变量的地址
    auto q = new Node(2);

    p->next=q;
}

头节点:第一个节点的地址,而不是他的值

链表基础操作

遍历,头插,删除


在这里插入图片描述

运行结果:

秒数转换

输入一个整数,表示时间,单位是秒。输出一个字符串,用”时:分:秒”的形式表示这个时间。

#include <iostream>
#include <cstdio>

using namespace std;

int main()
{
    int t;

    cin >> t;

    int hours = t / 3600;
    int minutes = t % 3600 / 60;
    int seconds = t % 60;

    printf("%d:%d:%d\n", hours, minutes, seconds);

    return 0;
}
  • int hours = t / 3600; 计算总秒数 t 包含多少完整的小时。因为1小时 = 3600秒,所以使用整数除法 t / 3600 可以得到完整小时数。整数除法的结果是去掉小数部分,仅保留整数部分。
  • int minutes = t % 3600 / 60; 首先,t % 3600 计算出除去完整小时后剩余的秒数。然后,将这个剩余的秒数除以60(因为1分钟 = 60秒)得到完整分钟数。这里也使用了整数除法,因此结果是剩余秒数中包含的完整分钟数。
  • int seconds = t % 60;使用取模运算 t % 60 计算出除去完整分钟后剩余的秒数。因为1分钟是60秒,所以这个操作会得到小于60的秒数,即最后剩余的秒数部分。

闰年

判断闰年。闰年有两种情况:
(1) 能被100整除时,必须能被400整除;
(2) 不能被100整除时,被4整除即可。

  1. 输入一个年份,如果是闰年输出yes,否则输出no。
#include <iostream>
#include <cstdio>

using namespace std;

int main()
{
    int year;
    cin >> year;

    if (year % 100 == 0)
    {
        if (year % 400 == 0) cout << "yes" << endl;
        else cout << "no" << endl;
    }
    else
    {
        if (year % 4 == 0) cout << "yes" << endl;
        else cout << "no" << endl;
    }

    return 0;
}
  1. 用一条if语句,判断闰年。
#include <iostream>
#include <cstdio>

using namespace std;

int main()
{
    int year;

    cin >> year;

    if (year % 4 == 0 && year % 100 != 0 || year % 400 == 0)
        cout << "yes" << endl;
    else
        cout << "no" << endl;

    return 0;
}

斐波那契数列

求斐波那契数列的第n项。f(1) = 1, f(2) = 1, f(3) = 2, f(n) = f(n-1) + f(n-2)。

#include <iostream>

using namespace std;

int main()
{
    int n;
    cin >> n;

    int a = 1, b = 1, i = 1;
    while (i < n)
    {
        int c = a + b;
        a = b;
        b = c;
        i ++ ;
    }

    cout << a << endl;

    return 0;
}

打印n阶菱形

输入一个n,打印n阶菱形。n是奇数。

#include <iostream>

using namespace std;

int main()
{
    int n;
    cin >> n;

    int cx = n / 2, cy = n / 2;

    for (int i = 0; i < n; i ++ )
    {
        for (int j = 0; j < n; j ++ )
            if (abs(i - cx) + abs(j - cy) <= n / 2)
                cout << '*';
            else cout << ' ';
        cout << endl;
    }

    return 0;
}
曼哈顿距离

理解 abs(i - cx) + abs(j - cy) <= n / 2 这个条件的关键在于理解曼哈顿距离(Manhattan Distance)的概念,以及如何通过这个距离来定义一个菱形(或者说是正方形对角线方向的正方形)图案。

曼哈顿距离是在格点坐标系中,两点在标准的直角坐标系中的绝对轴距总和(只能横行走和纵向走,走到中心点要几步)。对于任意两点 (x1, y1)(x2, y2),它们的曼哈顿距离是 |x1 - x2| + |y1 - y2|

在这个程序中,(i, j) 表示当前遍历到的网格点的坐标,(cx, cy) 是图案中心点的坐标。abs(i - cx) + abs(j - cy) 计算的就是当前点 (i, j) 到中心点 (cx, cy) 的曼哈顿距离。

在这里插入图片描述

菱形图案的定义

这个条件 abs(i - cx) + abs(j - cy) <= n / 2 用于判断当前点是否在菱形图案内部(包括边界)。这里的 n / 2 实际上定义了菱形的“半径”,即从中心点到边界的最大曼哈顿距离。

  • abs(i - cx) + abs(j - cy) 的值小于或等于 n / 2 时,这意味着当前点 (i, j) 距离中心点的曼哈顿距离在菱形的半径范围内,因此,它位于菱形内部或边界上,程序应该在这个位置打印一个星号 *
  • 当这个距离大于 n / 2 时,当前点 (i, j) 在菱形外部,程序在这个位置打印一个空格
    -在这里插入图片描述
大数计算

计算 2 的 N 次方。N≤10000

#include <iostream>
#include <algorithm>

using namespace std;

int main()
{
    int a[10000], size = 1, n;
    a[0] = 1;

    cin >> n;
    while (n -- )
    {
        int t = 0;
        for (int i = 0; i < size; i ++ )
        {
            t += a[i] * 2;
            a[i] = t % 10;
            t /= 10;
        }
        if (t) a[size ++ ] = t;
    }

    for (int i = size - 1; i >= 0; i -- ) cout << a[i];
    cout << endl;

    return 0;
}

这段代码是一个计算2N次方的程序,特别适用于处理大数运算,即当N很大时,直接使用常规数据类型(如intlong)无法存储结果的情况。这里N可以达到10000。程序通过模拟手工乘法的方式来计算结果,将每一位数字存储在一个数组a中,数组的每个元素代表结果数的一位,a[0]是结果的最低位,a[size-1]是结果的最高位。

下面是代码的详细解释:

  1. 初始化

    • int a[10000]:定义一个数组a,用于存储计算过程中的每位数字。
    • size = 1:初始化结果数字的大小为1,因为20次方等于1,所以起始时数组只有一位数字1
    • a[0] = 1:将结果的最低位初始化为1
  2. 读取输入

    • cin >> n:从标准输入读取N的值。
  3. 计算2N次方

    • while (n -- ):循环N次,每次循环相当于将当前结果乘以2
    • 在每次循环中,使用变量t来存储进位,初始时进位为0
    • for (int i = 0; i < size; i ++ ):遍历数组的每一位,模拟乘法运算。
    • t += a[i] * 2:当前位乘以2加上前一位的进位(如果有)。
    • a[i] = t % 10:更新当前位的值为新计算结果的个位数。
    • t /= 10:计算新的进位值。
    • 如果最后一位运算完后还有进位(t不为0),则将这个进位作为新的最高位添加到数组的末尾,并增加size
  4. 输出结果

    • 由于数组中存储的是倒序的结果(即最低位在数组的开始位置),因此输出时需要从size - 1开始倒序遍历数组。
    • for (int i = size - 1; i >= 0; i -- ) cout << a[i];:倒序输出数组的每一位,即输出计算得到的2N次方的结果。
    • cout << endl;:在结果后输出换行符。

输入输出

格式化输入输出

#include <iostream>
#include <cstdio>

using namespace std;

int main()
{
    float b = 3.12345678;
    double c = 3.12345678;

    printf("%.4f\n", b);
    printf("%.3lf\n", c);

  	printf("%5d\n", a);
    printf("%8.4f\n", b);
    printf("%7.3lf\n", c);

 	printf("%-5d!\n", a);
    printf("%-8.4f!\n", b); // 如果整个数字(包括小数点和小数部分)不足8个字符,则在右侧用空格填充,实现左对齐。
    printf("%-7.3lf!\n", c);

	printf("%05d\n", a);
    printf("%08.4f\n", b);
    printf("%07.3lf\n", c);

    return 0;
}
  • float, double等输出保留若干位小数时用:%.4f, %.3lf
  • %8.3f, 表示这个浮点数的最小宽度为8,保留3位小数,当宽度不足时在前面补空格。
  • %-8.3f,表示最小宽度为8,保留3位小数,当宽度不足时在后面补上空格
  • %08.3f, 表示最小宽度为8,保留3位小数,当宽度不足时在前面补上0

getline()函数解决cin只读入一个单词的问题

cin 将空格(空格、制表符等)视为终止字符,这意味着它只能存储单个单词(即使您键入许多单词)

在处理字符串时,我们经常使用 getline() 函数来读取一行文本。它以 cin 作为第一个参数,字符串变量作为第二个参数:

string fullName;
cout << "Type your full name: ";
getline (cin, fullName);
cout << "Your name is: " << fullName;

    char s[100];
    cin.getline(s, 100); // 100是这一行最多读多少个字符
    cout << s << endl;
    return 0;

fgets读入整行

如果题目没有超时,用getline比较好;如果输入量比较大用fgets比较好

    char s[100];
    fgets(s, 100, stdin);//100是最多读入多少个字符
    cout << s << endl;

输出字符数组(两种方式puts和printf)

    char s[100];
    cin.getline(s, 100); // 100是这一行最多读多少个字符
    puts(s);
    printf("%s\n",s);//这两种输出方式等价
    return 0;

运算符

赋值运算符

这些赋值运算符是C++(以及C和其他语言)中的复合赋值运算符,它们将算术或位运算和赋值操作结合在一起。每个运算符的作用如下:

  1. &= (按位与赋值运算符)
  • 语法: x &= 3
  • 等效于: x = x & 3
  • 作用: 将 x3 进行按位与操作,然后将结果赋值给 x。按位与操作对应位都为1时结果为1,否则为0。
  1. |= (按位或赋值运算符)
  • 语法: x |= 3
  • 等效于: x = x | 3
  • 作用: 将 x3 进行按位或操作,然后将结果赋值给 x。按位或操作对应位有一个为1时结果为1,都为0时结果为0。
  1. ^= (按位异或赋值运算符)
  • 语法: x ^= 3
  • 等效于: x = x ^ 3
  • 作用: 将 x3 进行按位异或操作,然后将结果赋值给 x。按位异或操作对应位不同为1,相同为0。
  1. >>= (右移赋值运算符)
  • 语法: x >>= 3
  • 等效于: x = x >> 3
  • 作用: 将 x 的二进制表示向右移动 3 位,然后将结果赋值给 x。右移操作会将高位丢弃,对于无符号数,低位补0;对于有符号数,低位补充依赖于具体实现(通常是补符号位,即算术右移)。
  1. <<= (左移赋值运算符)
  • 语法: x <<= 3
  • 等效于: x = x << 3
  • 作用: 将 x 的二进制表示向左移动 3 位,然后将结果赋值给 x。左移操作会在低位补0,高位丢弃,相当于将 x 乘以 2 的移动位数次方(这里是 2^38)。

二进制位移操作解释

Switch

int day = 4;
switch (day) {
  case 1:
    cout << "Monday";
    break;
  case 2:
    cout << "Tuesday";
    break;
  case 3:
    cout << "Wednesday";
    break;
  case 4:
    cout << "Thursday";
    break;
  case 5:
    cout << "Friday";
    break;
  case 6:
    cout << "Saturday";
    break;
  case 7:
    cout << "Sunday";
    break;
}
// Outputs "Thursday" (day 4)

循环

处理未知数量输入的几种常见方法

  1. while(cin >> x)
    在C++中,cin >> x 尝试从标准输入(通常是键盘输入或重定向的文件输入)读取一个值到变量 x 中。如果读取成功,表达式的值为 true;如果遇到输入结束(如文件结束或遇到不匹配类型的输入),表达式的值为 false。因此,while(cin >> x) 循环会持续读取输入直到遇到输入结束。

  2. while(scanf("%d", &x) != -1)while(~scanf("%d", &x))
    在C语言中,scanf("%d", &x) 尝试从标准输入读取一个整数到变量 x 中。scanf 函数返回成功读取的项目数量。如果读取成功,返回 1;如果遇到输入结束(EOF),返回 -1

  • while(scanf("%d", &x) != -1) 循环会持续读取输入,直到 scanf 返回 -1,即遇到输入结束。
  • while(~scanf("%d", &x)) 利用了位运算符 ~(按位取反)。在大多数系统上,EOF(即 -1)按位取反后的结果是 0,而 0 是逻辑假。因此,这个循环同样会持续读取输入,直到遇到输入结束。这是一种更为简洁的写法。
  1. while(cin >> x && x)while(cin >> x, x)
    这两种形式都用于处理当读入的最后一个值为 0 且这个 0 不需要处理的情况。
  • while(cin >> x && x) 循环会持续读取并处理非零的输入。如果 x0 或遇到输入结束,循环停止。
  • while(cin >> x, x) 使用了逗号运算符,该运算符执行其两边的表达式,并返回右侧表达式的结果。这里先尝试从输入读取一个值到 x,然后通过逗号运算符返回 x 的值作为 while 循环的条件。这个用法较为少见,且可能引起混淆,其效果与 while(cin >> x && x) 相同。

以上这些方法提供了在未知数量输入的情况下从标准输入读取数据的有效手段,以及如何根据特定条件(如输入的值为 0)结束输入的方式。

for-each

“for-each 循环”(在 C++ 版本 11 (2011) 中引入,专门用于循环数组(或其他数据集合)中的元素

int myNumbers[5] = {10, 20, 30, 40, 50};
for (int i : myNumbers) {
  cout << i << "\n";
}

字符

常用 ASCIl 值:‘A’-Z’是65~90, ‘a’-z’是97-182,‘0’-'9’是 48-57。
宇符可以参与运算,运算时会将其当做整数

字符数组的常用操作

下面几个函数需要引入头文件:

#include <string.h>//或者
#include <cstring>
  1. strlen(str),求字符串的长度(\0不计入其中)时间复杂度是 O ( n ) O(n) O(n)
  2. strcmp(a, b),比较两个字符串的大小,a < b返回-1,a == b返回0,a > b返回1。这里的比较方式是字典序!
  3. strcpy(a, b),将字符串b复制给从a开始的字符数组。

字符串String

基本概念

可变长的字符序列,比字符数组更加好用。需要引入头文件:

#include <string>
  • 定义和初始化:
#include <iostream>
#include <string>

using namespace std;

int main()
{
    string s1;              // 默认初始化,s1是一个空字符串
    string s2 = s1;         // s2是s1的副本,注意s2只是与s1的值相同,并不指向同一段地址
    string s3 = "hiya";     // s3是该字符串字面值的副本
    string s4(10, 'c');     // s4的内容是 "cccccccccc"

    return 0;
}

其他数据类型转变为字符串to_string()

    int c = 10;
    string num = to_string(c);
    cout << num << endl;

字符串连接

使用+号或者append()

string firstName = "John";
string lastName = "Doe";
string fullName = firstName + " " + lastName;
fullName = firstName.append(lastName);
cout << fullName;

字符串判空

	string s1, s2 = "abc";
    cout << s1.empty() << endl;//输出1
    cout << s2.empty() << endl;//输出0

字符串长度

使用length()size()和strlen()不同,size()的时间复杂度是O(1)的

string txt = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
cout << "The length of the txt string is: " << txt.length();
cout << "The length of the txt string is: " << txt.size();

注意size是无符号整数,因此 s.size() <= -1一定成立

字符串输入输出

string不可以用scanf读

#include <iostream>
#include <cstring>

using namespace std;

int main()
{
    string s;

    cin >> s; // string不可以用scanf读

    printf("%s\n", s.c_str()); // 返回字符串所存的字符数组的首地址
    puts(s.c_str());
    return 0;
}

读入一行

    string s1;
    getline(cin, s1);
    cout << s1 << endl;

string的比较:

支持 >, <, >=, <=, ==, !=等所有比较操作,按字典序进行比较。

为string对象赋值:

string s1(10, 'c'), s2;     // s1的内容是 cccccccccc;s2是一个空字符串
s1 = s2;                    // 赋值:用s2的副本替换s1的副本
                            // 此时s1和s2都是空字符串

两个string对象相加:

psptring s1 = "hello,  "", s2 = "world\n";
string s3 = s1 + s2;                    // s3的内容是 hello, world\n
s1 += s2;                               // s1 = s1 + s2

字面值和string对象相加:

做加法运算时,字面值和字符都会被转化成string对象,因此直接相加就是将这些字面值串联起来:

string s1 = "hello", s2 = "world";      // 在s1和s2中都没有标点符号
string s3 = s1 + ", " + s2 + '\n';

当把string对象和字符字面值及字符串字面值混在一条语句中使用时,必须确保每个加法运算符的两侧的运算对象至少有一个是string:

string s4 = s1 + ", ";  // 正确:把一个string对象和有一个字面值相加
string s5 = "hello" + ", "; // 错误:两个运算对象都不是string

string s6 = s1 + ", " + "world";  // 正确,每个加法运算都有一个运算符是string
string s7 = "hello" + ", " + s2;  // 错误:不能把字面值直接相加,运算是从左到右进行的

遍历数组

可以将string对象当成字符数组来处理:

#include <iostream>
#include <string>

using namespace std;

int main()
{
    string s = "hello world";

    for (int i = 0; i < s.size(); i ++ )
        cout << s[i] << endl;

    return 0;
}

或者使用基于范围的for语句:

#include <iostream>
#include <string>

using namespace std;

int main()
{
    string s = "hello world";

    for (char c: s) cout << c << endl;

    for (char& c: s) c = 'a';//想在改变c的同时改变s[i],在前面加上引用符号&使c等价于s[i]
    cout << s << endl;

    return 0;
}

数组

初始化memset

memset 函数是C和C++标准库中的一个函数,用于将一块内存中的每个字节都设置为一个给定的值。它通常用于初始化数组或者内存块。memset 函数的原型定义在 <cstring>(在C++中)或 <string.h>(在C中)头文件中。

#include <iostream>
#include <cstring>
using namespace std;
int main()
{
    int a[10];
    // memset(a, 0, 40);
    memset(a, 0, sizeof a); // sizeof a 返回a所占用的字节数量
    return 0;
}

在这里插入图片描述
将数组中的每一个字节设置为这个值。
在这里插入图片描述
在这里插入图片描述
因此,memset一般设置为0或者-1(补码,每一位都是1)

函数原型

在C和C++中,memset 函数的原型如下:

void *memset(void *s, int c, size_t n);
参数
  • void *s:指向要填充的内存块的指针。
  • int c:是一个值,表示要设置的值。尽管这个参数的类型是 int,但实际上只有最低的8位(一个字节)会被用于设置内存块中的值。
  • size_t n:内存块的大小,即要设置的字节数。
返回值

memset 函数返回一个指向内存块 s 的指针。

使用示例

假设有一个字符数组 arr,我们想将其所有元素初始化为0:

char arr[100];
memset(arr, 0, sizeof(arr));

这段代码将 arr 数组的所有100个字节都设置为0。

注意事项
  • memset 适用于简单的数据类型(如字符数组、整数数组等)的初始化,因为它是按字节操作的。对于需要按位初始化的复杂数据类型(如带有构造函数的C++对象),使用 memset 可能不会得到预期的效果。
  • 当使用 memset 设置非零值时,需要注意 c 参数只使用了最低的8位,这意味着如果你想用 memset 来初始化比一个字节更大的数据类型(如 intfloat 等),除非你是将其初始化为0或某个字节值的重复(比如 0x01010101),否则结果可能不是你所期望的。
  • 由于 memset 是按字节设置值,对于初始化高级数据结构或需要调用构造函数的对象数组,应使用更适合的方法,如循环或标准库中的 std::fillstd::fill_n 函数。

数组复制memcpy

memcpy 函数是C和C++标准库中用于复制内存块的函数。它从源内存地址开始复制n个字节到目标内存地址。这个函数对于执行低级别的二进制数据复制非常有效,尤其是当你需要快速复制大量数据时。memcpy函数的原型定义在<cstring>(C++中)或<string.h>(C中)头文件中。

函数原型

在C和C++中,memcpy函数的原型如下:

void *memcpy(void *dest, const void *src, size_t n);
参数
  • void *dest:指向用于存储复制内容的目标内存块的指针。
  • const void *src:指向要从中复制数据的源内存块的指针。
  • size_t n:要复制的字节数。
返回值

memcpy函数返回一个指向目标内存块dest的指针。

使用示例

假设你有两个数组,sourcedestination,你想将source数组的内容复制到destination数组中:

char source[] = "Hello, World!";
char destination[20];

memcpy(destination, source, strlen(source) + 1);

这段代码将source数组包括结尾的空字符(\0)一共14个字节的内容复制到destination数组中。

注意事项
  • memcpy函数不处理源和目标内存块重叠的情况。如果内存块重叠,复制的结果是未定义的。对于重叠内存块的复制,应使用memmove函数。
  • 使用memcpy时必须确保目标内存块足够大,可以容纳要复制的数据,否则可能会导致缓冲区溢出,这是常见的安全漏洞之一。
  • memcpy是按字节复制数据,因此它可以用于任何类型的数据复制,包括基本数据类型、结构体、类等,但复制对象时要小心,因为简单的字节复制可能不会正确处理对象内部的深层复制需求,比如指针成员的正确复制。对于包含动态分配内存或复杂资源管理的对象,使用memcpy可能不适合,应考虑更高级的复制机制。

函数

多维数组形参的写法

// 多维数组中,除了第一维之外,其余维度的大小必须指定
void print(int (*a)[10]) {/* … */}
void print(int a[][10]) {/* … */}
#include <iostream>

using namespace std;

void print(int a[][10])
{
    for (int i = 0; i < 10; i ++ )
    {
        for (int j = 0; j < 10; j ++ )
            cout << a[i][j] << ' ';
        cout << endl;
    }
}

int main()
{
    int a[10][10];

    for (int i = 0; i < 10; i ++ )
        for (int j = 0; j < 10; j ++ )
            a[i][j] = j;

    print(a);

    return 0;
}

类与结构体

类与结构体的定义与使用

类中的变量和函数被统一称为类的成员变量。

private后面的内容是私有成员变量,在类的外部不能访问;public后面的内容是公有成员变量,在类的外部可以访问。

#include <iostream>

using namespace std;

const int N = 1000010;

class Person
{
    private:
        int age, height;
        double money;
        string books[100];

    public:
        string name;

        void say()
        {
            cout << "I'm " << name << endl;
        }

        int set_age(int a)
        {
            age = a;
        }

        int get_age()
        {
            return age;
        }

        void add_money(double x)
        {
            money += x;
        }
} person_a, person_b, persons[100];

int main()
{
    Person c;

    c.name = "yxc";      // 正确!访问公有变量
    c.age = 18;          // 错误!访问私有变量
    c.set_age(18);       // 正确!set_age()是共有成员变量
    c.add_money(100);

    c.say();
    cout << c.get_age() << endl;

    return 0;
}

结构体和类的作用是一样的。不同点在于类默认是private,结构体默认是public。

struct Person
{
    private:
        int age, height;
        double money;
        string books[100];

    public:
        string name;

        void say()
        {
            cout << "I'm " << name << endl;
        }

        int set_age(int a)
        {
            age = a;
        }

        int get_age()
        {
            return age;
        }

        void add_money(double x)
        {
            money += x;
        }
} person_a, person_b, persons[100];

构造函数

#include <iostream>

using namespace std;

struct Person
{
    int age, height;
    double money;

    // 特殊的赋值方式
    Person(int _age, int _height) : age(_age), height(_height){};

    Person(int _age, int _height, double _money) // 构造函数
    {
        age = _age;
        height = _height;
        money = _money;
    }
};

int main()
{
    // 多种初始化方式
    Person p1(18, 180, 10000);
    Person p2 = {18, 180, 10000};

    return 0;
}

指针和引用

指针指向存放变量的值的地址。因此我们可以通过指针来修改变量的值。

#include <iostream>

using namespace std;

int main()
{
    int a = 10;
    int *p = &a;

    *p += 5;
    cout << a << endl;

    return 0;
}

数组名是一种特殊的指针。指针可以做运算:

#include <iostream>

using namespace std;

int main()
{
    int a[5] = {1, 2, 3, 4, 5};

    for (int i = 0; i < 5; i ++ )
        cout << *(a + i) << endl;

    return 0;
}

引用和指针类似,相当于给变量起了个别名。

#include <iostream>

using namespace std;

int main()
{
    int a = 10;
    int &p = a;

    p += 5;
    cout << a << endl;

    return 0;
}

STL

multi是可以有重复元素,没有multi的不能有重复元素
在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/420753.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

#单片机(TB6600驱动42步进电机)

1.IDE:keil 2.设备:保密 3.实验&#xff1a;使用单片机通过普通IO口控制TB6600驱动42步进电机 4.时序图&#xff1a; TB6600 ENA、ENA-DIR-、DIRPUL-、PULB-、BA、A-VCC、GND使能电机&#xff08;直接悬空不接&#xff09;方向脉冲输入&#xff08;普通IO口模拟即可&#xff…

Rocky Linux 安装部署 Zabbix 6.4

一、Zabbix的简介 Zabbix是一种开源的企业级监控解决方案&#xff0c;用于实时监测服务器、网络设备和应用程序的性能和可用性。它提供了强大的数据收集、处理和可视化功能&#xff0c;同时支持事件触发、报警通知和自动化任务等功能。Zabbix易于安装和配置&#xff0c;支持跨平…

vscode在windows环境不能使用终端安装依赖

会报这样的错误提示 解决思路&#xff1a; 1、vscode用管理员打开 (非必须) 2、设置策略 打开 windows powerShell . 输入命令 set-ExecutionPolicy RemoteSigned 然后 Y . 查看是否设置成功 get-executionpolicy 3、下载总是超时&#xff0c;设置镜像源 查看镜像源 npm …

「算法」常见位运算总结

位运算符 异或 按位异或可以实现无进位相加&#xff0c;所谓无进位相加&#xff0c;就是在不考虑进位的情况下将两个数相加&#xff08;后面有道题需要用到这种操作&#xff09; 异或的运算律 ①a ^ 0 a ②a ^ a 0 ③a ^ b ^ c a ^ ( b ^ c ) 有符号右移>> 将一个…

基于springboot实现线上阅读系统项目【项目源码+论文说明】计算机毕业设计

基于springboot实现线上阅读系统演示 摘要 随着社会发展速度的愈来愈快&#xff0c;以及社会压力变化的越来越快速&#xff0c;致使很多人采取各种不同的方法进行解压。大多数人的稀释压力的方法&#xff0c;是捧一本书籍&#xff0c;心情地让自己沉浸在情节里面&#xff0c;以…

Fabric V2.5 通用溯源系统——应用后端GIN框架部分设计

本节对Fabric V2.5 通用溯源系统的应用后端部分做一个简单的介绍,包括目录结构、文件作用、用户注册登录与农产品信息上链过程介绍。此节内容免费发布在TrueTechLabs Fabric学习交流QQ群。 购买专栏前请认真阅读:《Fabric项目学习笔记》专栏介绍 TrueTechLabs Fabric学习交流…

【LeetCode】一周中的第几天+ 一年中的第几天

2023-12-30 文章目录 一周中的第几天方法一&#xff1a;模拟思路步骤 方法二&#xff1a;调用库函数方法三&#xff1a;调用库函数 [1154. 一年中的第几天](https://leetcode.cn/problems/day-of-the-year/)方法一&#xff1a;直接计算思路&#xff1a; 方法二&#xff1a;调用…

SpringBoot整合MySQL和Druid

✅作者简介:大家好,我是Leo,热爱Java后端开发者,一个想要与大家共同进步的男人😉😉 🍎个人主页:Leo的博客 💞当前专栏: 循序渐进学SpringBoot ✨特色专栏: MySQL学习 🥭本文内容:SpringBoot整合MySQL和Druid 📚个人知识库: Leo知识库,欢迎大家访问 目录 …

【VTKExamples::PolyData】第四十一期 PointLocator

很高兴在雪易的CSDN遇见你 VTK技术爱好者 QQ:870202403 前言 本文分享VTK样例PointLocator,并解析接口vtkPointLocator,希望对各位小伙伴有所帮助! 感谢各位小伙伴的点赞+关注,小易会继续努力分享,一起进步! 你的点赞就是我的动力(^U^)ノ~YO 1. PointLocator …

13款可以轻松上手画图软件推荐

在当今的数字世界里&#xff0c;我们有各种各样的创作工具&#xff0c;尤其是画图软件。所以问题来了&#xff1a;我们应该如何选择许多免费的绘画软件&#xff1f;为了回答这个问题&#xff0c;我们将在本文中分享10个领先的画图软件。每一个都有其独特的特点和优势&#xff0…

Oracle 11g升级19c 后部分查询功能很慢

*Oracle 11g升级19c 后部分查询功能很慢 今天生产突然有个查询非常慢&#xff0c;日志显示执行了50秒左右&#xff0c;但是从日志中拿出SQL在PLSQL执行&#xff0c;发现用时不到1秒&#xff0c;查看SQL,怀疑是下面几种原因导致 1、使用函数不当 UNIT.UNIT_CODE LIKE CONCAT(‘…

【Pytorch】成功解决AttributeError: ‘tuple’ object has no attribute ‘dim’

【Pytorch】成功解决AttributeError: ‘tuple’ object has no attribute ‘dim’ &#x1f308; 个人主页&#xff1a;高斯小哥 &#x1f525; 高质量专栏&#xff1a;Matplotlib之旅&#xff1a;零基础精通数据可视化、Python基础【高质量合集】、PyTorch零基础入门教程&…

部署若依前后端分离项目,连接数据库失败

部署若依前后端分离项目&#xff0c;连接数据库失败&#xff0c;异常如下&#xff1a; 解决方案&#xff1a;application配置文件里&#xff0c;连接数据库的参数useSSL的值改为false

微服务day02-Ribbon负载均衡与Nacos安装与入门

一.Ribbon负载均衡 在上一节中&#xff0c;我们通过在RestTemplte实例中加上了注解 LoadBalanced,表示将来由RestTemplate发起的请求会被Ribbon拦截和处理&#xff0c;实现了访问服务时的负载均衡&#xff0c;那么他是如何实现的呢&#xff1f; 1.1 Ribbon负载均衡的原理 Rib…

windows server mysql 数据库停止 备份 恢复全流程操作方法

一,mysql备份 mysql最好是原工程文件备份.不需要sql查询的方式备份.安全高效. 比如,安装php与mysql组合后,我的mysql文件保存在: D:\phpstudy_pro\Extensions\MySQL5.7.26\data\dux 我只需要复制一份,保存起来就行. 二,mysql恢复 怎么恢复呢.我们一般是只恢复其中一个表,则找…

Watir 试用手记——一个很不错的开源 Web 自动化测试框架

&#x1f525; 交流讨论&#xff1a;欢迎加入我们一起学习&#xff01; &#x1f525; 资源分享&#xff1a;耗时200小时精选的「软件测试」资料包 &#x1f525; 教程推荐&#xff1a;火遍全网的《软件测试》教程 &#x1f4e2;欢迎点赞 &#x1f44d; 收藏 ⭐留言 &#x1…

融资项目——JWT令牌

1.JSON Web Token (JWT)是一种自包含令牌。自包含令牌本身已经包含了用户的相关信息&#xff0c;然后将这些信息通过例如加密的形式形成的令牌&#xff0c;由服务器进行解密从而完成对用户信息的确认。JWT一共由头、载荷与认证签名三个部分组成。然后由这三段字符拼接形成&…

Python Web开发记录 Day5:jQuery(JavaScript库)

名人说&#xff1a;莫道桑榆晚&#xff0c;为霞尚满天。——刘禹锡&#xff08;刘梦得&#xff0c;诗豪&#xff09; 创作者&#xff1a;Code_流苏(CSDN)&#xff08;一个喜欢古诗词和编程的Coder&#x1f60a;&#xff09; 目录 五、jQuery1、jQuery-选择器和菜单案例①快速上…

CentOS7安装MySQL5.7

查看并卸载系统自带的 Mariadb rpm -qa|grep mariadb rpm -e --nodeps mariadb-libs-5.5.68-1.el7.x86_64 检查系统是否安装过MySQL rpm -qa | grep mysql 检查有无MySQL用户组 cat /etc/group | grep mysql cat /etc/passwd | grep mysql 创建MySQL用户组和用户 groupadd m…

年轻人怎么搞钱?

年轻人想要搞钱&#xff0c;可以考虑以下几个方面&#xff1a; 1. 创业&#xff1a;年轻人可以通过自己的创意&#xff0c;找到一个市场的空缺&#xff0c;开创自己的业务。可以从比较小的项目开始&#xff0c;逐渐扩大范围&#xff0c;积累经验和财富。 2. 投资&#xff1a;…