【C++】1.C++基础

news2024/11/15 1:27:01

1.命名空间

使用命名空间的目的是对标识符的名称进行本地化,以避免命名冲突或名字污染,namespace关键字的出现就是针对这种问题的。

1°定义

定义命名空间,需要使用到namespace关键字,后面跟命名空间的名字,然后接一对{}即可,{}中即为命名空间的成员。

  • 普通的命名空间
namespace N1
{
  int a;
  int Add(int left, int right)
  {
    return left + right;
  }
}
  • 命名空间可以嵌套
namespace N2
{
  int a;
  int b;
  int Add(int left, int right)
  {
    return left + right;
  }
   
  namespace N3
  {
    int c;
    int d;
    int Sub(int left, int right)
    {
      return left - right;
    }
  }
}
  • 同一个工程中允许存在多个相同名称的命名空间

    编译器最后会合成同一个命名空间中(可以写两个N1)

namespace N1
{
  int Mul(int left, int right)
  {
    return left * right;
  }
}

2°使用

  • 加命名空间名称及作用域限定符 ps: N::a
  • 使用using将命名空间中成员引入 ps: using N::b
  • 使用using namespace 命名空间名称引入 ps: using namespace N;

输入输出 cin和cout都在std这个命名空间内

#include <iostream>
using namespace std;

int main()
{
  //1.std::不用using namespace std    endl换行
  std::cout << "hello world"<<std::endl;
  int i = 1;
  double d = 1.11;
  cin >> i >> d;
  //2.加了using namespace std  不需要std::
  cout << i << " " << d << endl;
  return 0;
}

2.缺省参数

1°概念

缺省参数是声明或定义函数时为函数的参数指定一个默认值。在调用该函数时,如果没有指定实参则采用该默认值,否则使用指定的实参。

例如:

#include <iostream>
using namespace std;

void Func(int a = 0) 
{
    cout << a << endl;
}
int main()
{
    Func(10);//10
    Func();//0
}

2°分类

  • 全缺省参数
  • 半缺省参数
#include <iostream>
using namespace std;

//全缺省 所有参数都给
//可以传1个 也可以传多个
void Func1(int a = 10, int b = 20, int c = 30)
{
    cout << "a = " << a << endl;
    cout << "b = " << b << endl;
    cout << "c = " << c << endl;
}

//半缺省 给部分参数
//必须传1个(没有缺省的位置必须传) 也可以多个
//必须从右往左连续缺省 右边的必须先给值
void Func2(int a, int b = 10, int c = 20)
{
    cout << "a = " << a << endl;
    cout << "b = " << b << endl;
    cout << "c = " << c << endl;
}

int main()
{
    Func1();//10 20 30
    Func1(1);//1 20 30
    Func1(1, 2);//1 2 30
    Func1(1, 2, 3);//1 2 3
    Func2(1);//1 10 20
    Func2(1, 2);//1 2 20
    Func2(1, 2, 3);//1 2 3
}

3°注意

  • 半缺省参数必须从右往左连续给出 不可以间隔
  • 缺省参数不可以在函数的声明和定义中同时出现 编译器无法确定给哪个缺省值
  • 缺省值必须是常量或者全局变量
  • C语言不支持(编译器不支持)

3.函数重载

1°概念

  • 一个函数可以有多个意义
  • 要求:函数名相同 参数不同(类型/个数/顺序不同)
  • 不要参数也可以 返回值相同和不同都可以

注意:只有返回类型不同不能构成重载 必须有参数不同

void Func()

int Func()

short Add(short left, short right)

{

        return left+right;

}

int Add(short left, short right)

{

        return left+right;

}

都不构成函数重载

2°名字修饰

为什么C语言不支持函数重载 而C++支持呢?

在C/C++中,一个程序要运行起来,需要经历以下几个阶段:预处理、编译、汇编、链接。

编译链接过程

  1. 预处理 -> 头文件的展开/宏替换/条件编译/去掉注释 list.h list.c test.c
  2. 编译 -> 检查语法生成汇编代码 list.i test.i
  3. 汇编 -> 汇编代码转成二进制的机器码 list.s test.s
  4. 链接 -> 将两个目标文件链接到一起 list.o test.o

编译这一步时

  • C:在linux下,采用gcc编译完成后,函数名字的修饰没有发生改变
  • C++:在linux下,采用g++编译完成后,函数名字的修饰发生改变,编译器将函数参数类型信息添加到修改后的名字中。

原因

  • C语言没办法支持重载,因为同名函数没办法区分。(编译器在编译.c文件时,只会给函数进行简单的重命名)
  • C++是通过函数修饰规则来区分,只要参数不同,修饰出来的名字就不一样,就支持了重载。

3°extern "C"

有时候在C++工程中可能需要将某些函数按照C的风格来编译,在函数前加extern "C",意思是告诉编译器,将该函数按照C语言规则来编译。

4°练习

  • 下面两个函数能形成函数重载吗?有问题吗或者什么情况下会出问题?
void TestFunc(int a = 10)
{
  cout<<"void TestFunc(int)"<<endl;
}
void TestFunc(int a)
{
  cout<<"void TestFunc(int)"<<endl;
}

不形成函数重载 因为两个函数的参数相同

  • C语言中为什么不能支持函数重载?

C语言没办法支持重载,因为同名函数没办法区分。(编译器在编译.c文件时,只会给函数进行简单的重命名)

C++是通过函数修饰规则来区分,只要参数不同,修饰出来的名字就不一样,就支持了重载。

  • C++中函数重载底层是怎么处理的?

在.cpp文件中,虽然两个函数的函数名一样,但是他们在符号表中生成的名称不一样。

  • C++中能否将一个函数按照C的风格来编译?

可以 在函数前加extern "C"

4.引用

1°概念

引用不是新定义一个变量,而是给已存在变量取了一个别名,编译器不会为引用变量开辟内存空间,它和它引用的变量共用同一块内存空间

#include <iostream>
using namespace std;

int main()
{
    int a = 1;
    int& ra = a;//ra是a的引用 引用也就是别名 a再取了一个名称ra
    int& b = a;
    int& c = b;
    //4个名字公用一块空间
    //改变任何一个别名的值 每个别名和变量本身都会改变
    c = 10;
    //10 10 10 10
    cout << a << " " << ra << " " << b << " " << c << " " << endl;
}

注意:引用类型必须和引用实体是同种类型的

2°引用特性

  • 引用在定义时必须初始化
  • 一个变量可以有多个引用
  • 引用一旦引用一个实体,再不能引用其他实体
#include <iostream>
using namespace std;

int main()
{
    int a = 1;
    //int& b; //引用必须在定义时初始化
    int& c = a;
    int d = 2;
    c = d; 
    //分析:这里是c变成了d的引用? no 
    //还是d赋值给c? ok
    //说明c已经是a的引用了 不会再是其他变量的引用
    //结论:引用一旦引用一个实体,再不能引用其他实体
    return 0;
}

3°常引用

#include <iostream>
using namespace std;

int main()
{
    //int a = 0;
    //int& b = a;//b的类型是int
    //如果
    //const int a = 0;
    //int& b = a;//b的类型是int 编译不通过 原因:a是只读 b的类型是int 可读 可写 所以不行
    const int a = 0;
    const int& b = a;
    int c = 1;
    int& d = c;
    const int& e = c;
    //行不行?可以的-> C可读可写 e变成别名只读
    //总结:引用取别名时 变量访问的权限可以缩小 不能放大 
    //取别名变量范围小
    return 0;
}

别名是可读可写 如果变量只可读 那么取别名编译失败

别名的权限较小

进阶:隐式类型转换+取别名

#include <iostream>
using namespace std;

int main()
{
    int i = 0;
    double d = i;//隐式类型转换
    //double& rb = i;
    //float& rf = i;
    //跟字节大小无关
    //无法通过编译
    //但加const 可以
    const double& rd = i;
    const float& rf = i;
    //为什么?
    //i->double临时变量->db/rd/rf
    //临时变量具有常性(const只可读)
    //所以不加const就放大了权限 加const就可以成立
    //变量之间赋值没有权限缩小和放大的关系 引用才有
    const int ci = i;
    int x = ci;
    return 0;
}
  • 引用:

一个int变量给到一个double变量

int变量->double临时变量(临时变量具有常性)->取别名的时候只能是const类型的

权限不能放大

  • 赋值:

都可以 没有权限问题

4.使用场景

1°作参数

void swap_c(int* p1, int* p2)
{
    int tmp = *p1;
    *p1 = *p2;
    *p2 = tmp;
}
//r1是a的别名 r2是b的别名 r1和r2的交换就是a和b的交换
void swap_cpp(int& r1, int& r2)
{
    int tmp = r1;
    r1 = r2;
    r2 = tmp;
}

2°作返回值

#include <iostream>
using namespace std;

//返回一个临时变量(tmp) tmp的类型是int tmp的值是n的值
//这里会多产生一个tmp的空间
int Count1()
{
    static int n = 0;
    n++;
    return n;
}

//这个时候tmp就是n的别名 返回的就是n
//这里不会产生多的空间
int& Count2()
{
    static int n = 0;
    n++;
    return n;
}

int main()
{
    //int& r1 = Count1();编译不通过 返回的是tmp(临时变量) 临时变量具有常性 只可读 给到可读可写 不行
    const int& r1 = Count1();
    int& r2 = Count2();//返回的就是tmp(n的别名) 不是临时变量
    return 0;
}
  • 传值返回和隐式类型转换都先要产生一个临时变量(拷贝) **临时变量具有常性 **
  • 此时传值返回直接取别名可能有权限放大问题
  • 此时隐式类型转换取别名不加const会有问题

但引用返回就规避了问题 因为引用和原本变量是同一空间 可以理解就是返回原来的变量

注意:

int& Add(int a, int b)
{
    int c = a + b;
    return c;
    //局部变量(栈上) 返回后 栈销毁了
    //返回c的别名
}

int main()
{
    //返回之后用了c的别名 再取一个别名ret
    //栈已经销毁还给系统 还去使用这块空间 会出现随机值
    int& ret = Add(1, 2);
    cout << "Add(1, 2) is :" << ret << endl;
    return 0;
}

此时c是引用返回 但c是局部变量(栈上) 出了Add函数作用域后 栈销毁了 还给了系统

此时还去使用这块空间 出现随机值

解决方法:

  • 如果还想要引用返回 那就加上static(static int c) 这样c的空间不会出函数作用域就销毁
  • 使用传值返回

注意当使用static时(那条语句只会被执行一次):

int& Add(int a, int b)
{
    static int c = a + b;
    //这条语句只会被执行一次(第二次及以后调用函数不会再次执行)
    //只会被定义一次变量
    return c;
}
int main()
{
    int& ret1 = Add(1, 2);
    int& ret2 = Add(3, 4);//就算再调用一次 c还是3
    cout << "Add(1, 2) is :" << ret1 << endl;//3
    cout << "Add(3, 4) is :" << ret2 << endl;//3
    return 0;
}

如果函数返回时,出了函数作用域,如果返回对象还未还给系统,则可以使用引用返回,如果已经还给系统了,则必须使用传值返回

什么变量可以使用引用返回:全局变量 静态变量

3°传值vs传引用

  • 传值:会产生一份临时拷贝并返回
  • 传引用:直接返回本来变量
  • 传值效率更低(当参数或者返回值类型非常大)

那么函数使用引用返回好处是什么?->少开辟一个拷贝变量的空间 提高程序的效率

作参数时

#include <iostream>
#include <time.h>
using namespace std;

struct A 
{ 
    int a[10000]; 
};
void TestFunc1(A a) 
{}
void TestFunc2(A& a)
{}
void TestRefAndValue()
{
    A a;
    // 以值作为函数参数
    size_t begin1 = clock();
    for (size_t i = 0; i < 10000; ++i)
        TestFunc1(a);
    size_t end1 = clock();
    // 以引用作为函数参数
    size_t begin2 = clock();
    for (size_t i = 0; i < 10000; ++i)
        TestFunc2(a);
    size_t end2 = clock();
    // 分别计算两个函数运行结束后的时间
    cout << "TestFunc1(A)-time:" << end1 - begin1 << endl;
    cout << "TestFunc2(A&)-time:" << end2 - begin2 << endl;
}
int main()
{
    TestRefAndValue();
    return 0;
}

作为返回类型

#include <iostream>
#include <time.h>
using namespace std;

struct A 
{ 
    int a[10000]; 
};
//40000byte

//值返回
A TestFunc1(A a) 
{
    return a;
}

//引用返回
A& TestFunc2(A& a) 
{
    return a;
}

void TestRefAndValue()
{
    A a;

    //以值作为函数参数
    size_t begin1 = clock();
    for (size_t i = 0; i < 10000; ++i)
        TestFunc1(a);
    size_t end1 = clock();

    //以引用作为函数参数
    size_t begin2 = clock();
    for (size_t i = 0; i < 10000; ++i)
        TestFunc2(a);
    size_t end2 = clock();

    //分别计算两个函数运行结束后的时间
    cout << "TestFunc1(A)  time:" << end1 - begin1 << endl;
    cout << "TestFunc2(A&) time:" << end2 - begin2 << endl;
}

int main()
{
    TestRefAndValue();
    return 0;
}

4°引用vs指针

初始化 用法 sizeof +- 安全等方面

不同:

  1. 引用在定义时必须初始化,指针没有要求
  2. 引用在初始化时引用一个实体后,就不能再引用其他实体,而指针可以在任何时候指向任何一个同类型实体
  3. 没有NULL引用,但有NULL指针
  4. 在sizeof中含义不同:引用结果为引用类型的大小,但指针始终是地址空间所占字节个数(32位平台下占4个字节)
  5. 引用自加即引用的实体增加1,指针自加即指针向后偏移一个类型的大小
  6. 多级指针,但是没有多级引用
  7. 访问实体方式不同,指针需要显式解引用,引用编译器自己处理
  8. 引用比指针使用起来相对更安全

5.内联函数

1°概念

以inline修饰的函数叫做内联函数,编译时C++编译器会在调用内联函数的地方展开没有函数压栈的开销,内联函数提升程序运行的效率。

2°特性

  • inline是一种以空间换时间的做法,省去调用函数额开销。所以代码很长或者有循环/递归的函数不适宜使用作为内联函数
  • inline对于编译器而言只是一个建议,编译器会自动优化,如果定义为inline的函数体内有循环/递归等等,编译器优化时会忽略掉内联。
  • inline不建议声明和定义分离,分离会导致链接错误。因为inline被展开,就没有函数地址了,链接就会找不到。
  • 一般内联适用于小函数 小于20行
#include <iostream>
using namespace std;

//在前面加inline(内联) 空间换时间
//原:Call Swap(1w)+3行指令
//现:Call Swap(1w*3) 直接全部展开了 空间变大了 但时间减少了
inline void Swap(int& x1, int& x2)
{
    int tmp = x1;
    x1 = x2;
    x2 = tmp;
}

//频繁调用Swap 调用函数需要建立栈帧 是有消耗的
//如何解决:1.C语言使用宏函数 2.C++使用内联函数

int main()
{
    int a = 0;
    int b = 2;
    Swap(a, b);
    return 0;
}

3°练习

宏的优缺点?

优点:

  • 增强代码的复用性。
  • 提高性能。

缺点:

  • 不方便调试宏。(因为预编译阶段进行了替换)
  • 导致代码可读性差,可维护性差,容易误用。
  • 没有类型安全的检查 。

C++有哪些技术替代宏?

  • 常量定义 换用**const ** #define N 10; -> const int N = 10;
  • 函数定义 换用内联函数

6.auto关键字(C++11)

1°简介

C++11:auto不再是一个存储类型指示符,而是作为一个新的类型指示符来指示编译器,auto声明的变量必须由编译器在编译时期推导而得。

使用auto定义变量时必须对其进行初始化,在编译阶段编译器需要根据初始化表达式来推导auto的实际类型。因此auto并非是一种“类型”的声明,而是一个类型声明时的“占位符”,编译器在编译期会将auto替换为变量实际的类型

int a = 0;

auto b = a;

此时b的类型就会根据a的类型推导出来

2°使用

  • auto与指针和引用结合起来使用

用auto声明指针类型时,用auto和auto*没有任何区别,但用auto声明引用类型时则必须加&

#include <iostream>
using namespace std;

int main()
{
    int a = 0;
    auto b = a;//b的类型是根据a的类型推导出是int
    int& c = a;

    auto& d = a;//引用类型加上&
    auto* e = &a;
    auto f = &a;//不加*也可以推出来指针 指针可以不加

    cout << typeid(a).name() << endl;
    cout << typeid(b).name() << endl;
    cout << typeid(c).name() << endl;
    
    cout << typeid(d).name() << endl;
    cout << typeid(e).name() << endl;
    cout << typeid(f).name() << endl;

    //auto实际作用
    //类型很长可以直接写成auto 
    //使用auto来进行优化 简化代码的方法
    return 0;
}
  • 在同一行定义多个变量

当在同一行声明多个变量时,这些变量必须是相同的类型,否则编译器将会报错,因为编译器实际只对第一个类型进行推导,然后用推导出来的类型定义其他变量。

auto a=1,b=2;

auto c=3,d=4.0;

第二行编译失败 因为auto已经是int类型了 auto d = 4.0不可以

3°auto不能推导的情况

参数和数组不能用auto

auto不能作为形参类型

auto不能直接用来声明函数

7.范围for循环(C++11)

C++98:for(int i = 0;i<sizeof(arr)/sizeof(arr[0]);++i)

C++11:for循环后的括号由冒号“ :”分为两部分:第一部分是范围内用于迭代的变量,第二部分则表示被迭代的范围。

#include <iostream>
using namespace std;

int main()
{
    int array[] = { 1,2,3,4,5 };
    //要求将数据中的值乘2倍 再打印一遍

    //C语言的做法
    for (int i = 0; i < sizeof(array) / sizeof(int); ++i)
    {
        array[i] *= 2;
    }
    for (int i = 0; i < sizeof(array) / sizeof(int); ++i)
    {
        cout << array[i] << " ";
    }
    cout << endl;

    //C++11->范围for(语法糖)->特点:写起来比较简单
    //e是别名 e的改变就是数组的改变
    //可以看成array中每个元素取出来赋值给e
    //e的改变不会影响array中元素的改变
    //e如果是别名就可以
    for (auto& e : array)
    {
        e *= 2;
    }
    for (auto e : array)
    {
        cout << e << " ";
    }
    cout << endl;
    return 0;
}

注意: for循环迭代的范围必须是确定的

void TestFor(int array[]) { for (auto& e : array)//这里传参 array是首元素地址 无法通过编译 cout << e << endl; }

这里是首元素地址 for循环范围不确定

8.指针空值nullptr(C++11)

C++98: int* p = NULL;

NULL实际是一个宏

stddef.h中:

#ifndef NULL #ifdef __cplusplus #define NULL 0 #else #define NULL ((void *)0) #endif #endif

NULL可能被定义为字面常量0,或者被定义为无类型指针(void*)的常量。

字面常量0既可以是一个整形数字,也可以是无类型的指针(void*)常量。

但是编译器默认情况下将其看成是一个整形常量,如果要将其按照指针方式来使用,必须对其进行强转(void *)0。

这里就会遇到麻烦 你想的是指针 但编译器会默认为整形常量

所以C++11引用nullptr关键字

  • 在使用nullptr表示指针空值时,不需要包含头文件,因为nullptr是C++11作为新关键字引入的。
  • 在C++11中,sizeof(nullptr) 与 sizeof((void*)0)所占的字节数相同。
  • 为了提高代码的健壮性,在后续表示指针空值时建议最好使用nullptr

【C++】1.C++基础 完

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

DepGraph:适用任何结构的剪枝

文章目录摘要1、简介2、相关工作3、方法3.1、神经网络中的依赖关系3.2、依赖关系图3.3、使用依赖图剪枝4、实验4.1、设置。4.2、CIFAR的结果4.3、消融实验4.4、适用任何结构剪枝5、结论摘要 论文链接&#xff1a;https://arxiv.org/abs/2301.12900 源码&#xff1a;https://gi…

软考高级-信息系统管理师之质量管理(最新版)

质量管理目录 项目质量管理质量管理基础质量与项目质量质量管理质量管理标准体系1、IS09000系列,8项基本原则如下。2、全面质量管理(TQM)3、六西格码意为“六倍标准差”,4、软件过程改迸与能力成熟度模型项目质量管理过程规划质量管理1、规划质量管理2、规划质量管理:输入3、…

【java】Spring Cloud --Spring Cloud 的核心组件

文章目录前言一、Eureka&#xff08;注册中心&#xff09;二、Zuul&#xff08;服务网关&#xff09;三、 Ribbon&#xff08;负载均衡&#xff09;四、Hystrix&#xff08;熔断保护器&#xff09;五、 Feign&#xff08;REST转换器&#xff09;六、 Config&#xff08;分布式配…

【C++】RBTree——红黑树

文章目录一、红黑树的概念二、红黑树的性质三、红黑树节点的定义四、红黑树的插入五、代码实现一、红黑树的概念 红黑树&#xff0c;是一种二叉搜索树&#xff0c;但在每个结点上增加一个存储位表示结点的颜色&#xff0c;可以是Red或Black。 通过对任何一条从根到叶子的路径上…

Python爬虫(7)selenium3种弹窗定位后点击操作,解决点击登录被隐藏iframe无法点击的登陆问题

之前的文章有关于更多操作方式详细解答&#xff0c;本篇基于前面的知识点进行操作&#xff0c;如果不了解可以先看之前的文章 Python爬虫&#xff08;1&#xff09;一次性搞定Selenium(新版)8种find_element元素定位方式 Python爬虫&#xff08;2&#xff09;-Selenium控制浏览…

看见统计——第四章 统计推断:频率学派

看见统计——第四章 统计推断&#xff1a;频率学派 接下来三节的主题是中心极限定理的应用。在不了解随机变量序列 {Xi}\{X_i\}{Xi​} 的潜在分布的情况下&#xff0c;对于大样本量&#xff0c;中心极限定理给出了关于样本均值的声明。例如&#xff0c;如果 YYY 是一个 N(0&am…

Spring系列-2 Bean的生命周期

背景&#xff1a; 作为Spring系列的第二篇&#xff0c;本文结合容器的启动流程介绍单例Bean的生命周期&#xff0c;包括Bean对象的创建、属性设置、初始化、使用、销毁等阶段&#xff1b;在此过程中会介绍Spring用于操作Bean或者BeanDefinition的相关扩展接口。 文章重心在于介…

Spring Boot 日志文件,你都会了吗?

目录 1、日志文件的作用 2、日志的使用 2.1、从程序中得到日志对象 2.2、使用日志 2.3、日志格式 3、日志级别 3.1、这样的日志级别有什么用&#xff1f; 3.2、日志级别分类和使用 3.3、日志级别设置 4、日志持久化 5、更简单的日志输出——lombok 5.1、对比 5.2、…

阅读源码和查看官方文档,是解决问题最高效的办法。

作为一个工作8年的老程序员告诉你&#xff1a;阅读源码和查看官方文档&#xff0c;是解决问题最高效的办法。不信你来看&#xff0c;这个困扰了读者半天的问题我查了源码和文档后瞬间解决。 前言 上周五有位读者私信我一个问题&#xff0c;说困扰了他半天&#xff0c;研究了一…

利用Rust与Flutter开发一款小工具

1.起因 起因是年前看到了一篇Rust iOS & Android&#xff5c;未入门也能用来造轮子&#xff1f;的文章&#xff0c;作者使用Rust做了个实时查看埋点的工具。其中作者的一段话给了我启发&#xff1a; 无论是 LookinServer 、 Flipper 等 Debug 利器&#xff0c;还是 Flutt…

基于springboot+vue的疾病匿名检测查询系统

基于springbootvue的疾病匿名检测查询系统 ✌全网粉丝20W,csdn特邀作者、博客专家、CSDN新星计划导师、java领域优质创作者,博客之星、掘金/华为云/阿里云/InfoQ等平台优质作者、专注于Java技术领域和毕业项目实战✌ &#x1f345;文末获取项目下载方式&#x1f345; 一、项目背…

【拥抱开源】发布自己的项目到maven中央仓库

文章目录&#x1f388;第一步&#xff0c;注册账号&#x1f4bf;第二步&#xff0c;登录&#x1f4c0;第三步&#xff0c;设置信息&#x1f4be;第四步&#xff0c;创建问题&#x1f4f9;第五步&#xff0c;验证信息&#x1f3a5;第六步&#xff0c;上传jar包到中央仓库&#x…

网页中字体混淆的处理(简易方法)——爬虫学习笔记

网页中字体混淆的处理——爬虫学习笔记之评论爬取一、网页分析1、打开某点评网址。2、在网页源代码中寻找评论信息&#xff08;1&#xff09;进入这个“火锅店”的详情页&#xff0c;然后右击“检查”&#xff08;2&#xff09;点上面“刷新”详情页&#xff0c;逐步寻找。&…

RK3288 GPIO记录

1、引脚对应的GPIO 编号第一种 使用/sys/kernel/debug/gpio查询所有gpio引脚的基数第二种 cat /sys/class/gpio/gpiochip248/label对应的label就是GPIO引脚&#xff0c;例如下图GPIO8对应的基数就是2482、计算编号编号 基数 PIN脚如GPIO8的基数是248&#xff0c; GPIO8_A6的编…

Java开发 - 数风流人物,还看“微服务”

目录 前言 服务器端的发展历程 早期的服务器 动态的页面 用户内容网站 微服务 企业级应用 互联网应用 微服务介绍 什么是微服务&#xff1f; 为什么使用微服务 怎么使用微服务 Spring Cloud 什么是Spring Cloud Nacos注册中心 什么是Nacos 创建微服务项目 创建…

【Servlet篇】一文带你吃透Request对象

文章目录1. 前言2. Request 对象2.1 Request 继承体系2.2 Request 获取请求参数1. 获取请求行数据2. 获取请求头数据3. 获取请求体数据4. 获取请求参数的通用方式3. IDEA中快速创建 Servlet你问我青春还剩几年&#xff1f;我的回答是&#xff0c;趁现在&#xff0c;正当时。身边…

CS144-Lab2

实验架构 除了写入传入流之外&#xff0c;TCPReceiver 还负责通知 sender 两件事&#xff1a; “First unassembled” 字节的索引&#xff0c;称为“acknowledgment”或 “ackno”。这是接收方需要来自发送方的第一个字节。“first unassembled ” 索引和“first unacceptable…

【项目精选】基于SSH的任务调度系统的设计与实现(视频+源码+论文)

点击下载源码 虽然科技进步在改革开发这几十年来速度飞快&#xff0c;计算机行业也发展迅速&#xff0c;但仍然有大量商家或企业&#xff0c;甚至项目组&#xff0c;采用落后的人工管理方式或者低效的任务调度策略&#xff0c;这无疑是对计算机的一种无视。 计算机处理信息的准…

Python每日一练(20230220)

目录 1. 存在重复元素 II 2. 按要求实现程序功能 3. 分割链表 附录 链表 1. 存在重复元素 II 给定一个整数数组和一个整数 k&#xff0c;判断数组中是否存在两个不同的索引 i 和 j&#xff0c;使得 nums [i] nums [j]&#xff0c;并且 i 和 j 的差的 绝对值 至多为 k。 …

高级数据类型

为了解决单一的业务而存在bitmapsBitmaps类型的基础操作 获取指定key对应偏移量上的bit值getbit key offset 设置指定key对应偏移量上的bit值&#xff0c;value只能是1或0setbit key offset valueBitmaps类型的扩展操作状态位的统计业务需求&#xff1a;1. 统计每天某一部电…