【c++基础】

news2024/11/15 15:47:32

C++基础入门

  • 统一初始化
  • 输入输出
    • 输入输出符
    • 输入字符串
  • const与指针
    • c和c++中const的区别
    • const与指针的关系
    • 常变量与指针
    • 同类型指针赋值的兼容规则
  • 引用
    • 引用的特点
    • const引用
    • 作为形参替换指针
    • 其他引用形式
    • 引用和指针的区别
  • inline函数
  • 缺省参数
  • 函数重载
    • 判断函数重载的规则
    • 名字粉碎
    • C++编译时函数名修饰约定规则
  • 函数模板
  • 名字空间:nameplace
    • 命名空间的使用
  • new/delete
    • C++的动态内存管理
  • C11的新特性
    • 类型推导
      • auto的限制
      • 可以推导函数返回值
    • decltype关键字
    • 基于范围的for循环
      • 遍历数组(容器)
      • 基于范围的for循环
    • 指针空值--nullptr
    • typedef与using的使用
  • string的使用

统一初始化

初始化列表的方法:

int main() {
	int a = 10;
	int b{ 10 };
	int c(10);
	int ar[] = { 1,2,3,4,5,6,7,8 };
	int arr[]{ 1,2,3,4,6,5,7,8,9 };
	return 0;
}

输入输出

输入输出符

输入流:cin (键盘)
输出流:cout (控制台,屏幕)
使用cin和cout标准输入输出时,必须包含 (iostream)头文件以及std标准命名空间。

int main() {
	int a;
	int b;
	cin>>a>>b;//>>提取符
	cout<<"a="<<a<<"b="<<b<<endl;//<<插入符  endl<=>"\n"《=>换行
	return 0;
}

输入字符串

int main() {
	const int n = 128;
	char str[n];
	cin >> str ;
	cout << str<<endl;//输入abc cde输出abc
    cin.getline(str,n);
	cout << str << endl;//输入abc def输出abc def
	cin.getline(str,n,'#');
	cout << str << endl;//输入def vyw# ugfua输出def vyw
	return 0;
}

getline函数:
1)getline(istream &is,string &str,char delim);
2)getline(istream& is,string &str);
delim终结符 ,遇到该字符停止读取操作,不写默认回车

const与指针

c和c++中const的区别

c中const修饰一个变量,叫做常变量,其本质上还是一个变量,可以修改。而c++中const是一个常量,本质上不能修改。

int main() {
	const int a{ 10 };
	int ar[a]{ 1,2,3,4 };
	int* p =(int *) &a;
	*p = 20;
	printf("a=%d *p=%d \n", a, *p);
}
int main() {
	const int n{ 10 };
	int ar[n]{ 1,2,3,4 };
	int* p = (int*)&n;
	*p = 100;
	cout << "n=" << n << "p=" << *p<<endl;
	return 0;
}

const与指针的关系

此处存在三种情况如下:

int main() {
	int a=10,b=20;
	int* p=&a;//普通指针
	const int* p1=&a;//控制了解引用不能改变(解引用为常性)
	int const*p2=&a;//控制了解引用不能改变(解引用为常性,同上相同)
	int * const p3=&a;//控制了指针本身指向(指针变量自身为常性)
	const int* const p4=&a;//解引用和指针本身指向都进行控制
}

以上几种写法均正确,只是编译方式不同

常变量与指针

int main() {
	const int a=10;
	int* p1=&a;//error  a本身为常量,此处错误在于可以用*p解引用进行修改相矛盾
	const int* p2=&a;//OK const限制了解引用
	int * const p3=&a;//error,仅控制了指向,没有控制解引用
	const int* const p4=&a;//OK
	int *p5=(int*)&a;//OK 不安全
	return 0}

同类型指针赋值的兼容规则

能力强的指针赋值给能力收缩的指针

int main() {
	int a = 10, b = 20;
	int* p = &a;
	int* s1 = p;
	const int* s2 = p;
	int* const s3 = p;
	const int* const s4 = p;
	cout << "*p=" << *p << " *s1=" << *s1 << " *s2=" << *s2 << "*s3=" << *s3 << "*s4=" << *s4 << endl;
	return 0;
}

引用

引用的定义
类型& 引用变量名称=变量名称;
这就是引用变量的定义。&和类型结合称之为引用符号,不是取地址,代表别名的意思。

int main() {
	int a=10;
	int b=a;
	int &c=a;//引用定义时必须进行初始化
	return 0;
}

引用的特点


 - [ ] List item

int main() {
	int a=10;
	int &b;//error 引用定义时必须进行初始化
	int &c=nullptr;//error 不存在空引用
	int& d=a;//OK
	inr&&e=a;//error 不存在双重引用
}

const引用

int main() {
	int a=10;
	const int b=20;
	int &x=b;//error
	const int &x=b;//OK
	const int& y=a;//OK
	const int &z=10;//OK
}

作为形参替换指针

使用指针替换两个变量值

void swap(int *x,int *y){
	int temp;
	temp=*x;
	*x=*y;
	*y=temp;
}
int main() {
	int a=10,b=20;
	swap(&a,&b);
	return 0;
}

使用引用替换两个变量的值

void swap(int &x,int &y){
	int temp=x;
	x=y;
	y=temp;
}
int main () {
	int a=10;
	int b=20;
	swap(a,b);
	return 0;
}

其他引用形式

int main() {
	int a=10,b=20;
	int ar[5]{1,2,3,4,5};
	int *p=&a;
	int *&rp=p;//引用指针
	int &x=ar[0];
	int (&br)[5]=ar;//引用数组
	return 0;	
}

引用和指针的区别

从语法规则上讲,指针变量存储某个实例(变量或对象)的地址;引用是某个实例的别名。
程序为指针变量分配内存区域;不为引用分配内存区域。
解引用是指针使用前要加上“ * ”;引用可以直接使用,不需要解引用
指针变量的值可以发生改变,存储不同实例的地址;引用在定义时就要被初始化,之后无法改变(不能是其他实例的引用)。
指针变量的值可以为NULL,引用不存在空引用。
指针变量作为形参时需要测试他的合法性(判空),引用不需要。
对指针变量使用sizeof得到的是指针变量的大小(4字节),对引用变量使用sizeof的到的是变量的大小。
理论上指针没有级数的限制(二级指针等),但是引用只有一级
++引用与++指针的效果不同:对指针变量++操作,会使指针变量指向下一个实体的地址;不改变实体本身的内容。但是对引用进行++操作就会直接影响到变量的本身。
不可以对函数中的局部变量或对象以引用或者指针的方式返回。

int * fun() {
	int a=10;
	return &a;
}
int &func_2() {
	int a=10;
	return a;
}
//以上两种方法均错误

此处我们在执行的过程中可以运行,但是为什么不能作为返回值呢?
当函数被调用时,函数的形参都在栈桢中,当使用指针或者引用作为返回值时,我们返回的都是这个局部变量的地址,但是函数返回时函数的栈桢会被回收,我们返回的这个地址也就会失效。但是我们为什么可以运行呢,因为这个地址还存在上一个栈桢的存留,因此可以进行使用该地址找到我们局部变量的值,如果这个栈桢被骚扰,或者说这个栈桢被一个新的函数调用时作为了另一个函数的栈桢,返回的地址上的值就会被改变,就不是我们所期望的值。因为我们不能确定该栈桢有没有被骚扰,所以不能用指针或者引用作为返回值。

inline函数

当程序执行函数调用时,系统要进行建立栈空间进行保护现场,传递参数,控制程序执行和转移等当一个函数功能简单且执行多次,为了提高效率,直接将函数的代码嵌入到程序中,这个办法会存在两个缺点,一是书写相同代码,二是程序可读性往往没使用函数的好。为了协调好效率和可读性之间的矛盾,c++r提供了另一种方法–内联函数,方法是在函数定义时用修饰词inline。

inline bool IsNumber(char ch) {
	return ch >= '0' && ch <= '9' ? 1 : 0;
}

例如该函数,在其面前加上inline关键字,该函数就变成了内联函数,编译期间编译器能够在调用点内联展开该函数。
inline是一种以空间换时间的做法,省去调用函数的开销。但是函数体的代码过长或是递归函数即便加上inline关键字也不会在调用点内以内联展开该函数。
inline对编译器而言只是一个建议,编译器会自动优化。
inline不建议声明和定义分离,分离会导致链接错误。因为inline被展开,就没有函数地址了,链接就会找不到。

//A.h
#pragma once
inline bool IsNumber(char ch);
//A.cpp
#include"A.h"
inline bool IsNumber(char ch) {
	return ch >= '0' && ch <= '9' ? 1 : 0;
}
//main.cpp
#include"A.h"
#include<iostream>
using namespace std;


int main() {
	char c = '4';
	bool i=IsNumber(c);
	cout << i << endl;
}
//无法解析的外部符号 "bool __cdecl IsNumber(char)" (?IsNumber@@YA_ND@Z),函数 _main 中引用了该符号	测试	D:\tulun\测试\main.obj	1	

那在什么情况下使用内联函数什么情况下使用普通函数呢?
如果函数的执行开销小于开栈清栈开销(函数体较小),使用inline处理效率高,如果函数执行开销大于开栈清栈开销,使用普通函数方式处理。
内联函数和宏定义的区别:

  • 内联函数在编译时展开,代餐的宏在预编译时展开
  • 内联函数直接嵌入到目标代码中,带参的宏时简单的做文本替换。
  • 内联函数有类型检测,语法判断功能,宏只是替换

缺省参数

一般情况下,函数调用时的参数个数和形参相同,但是为了更方便的使用函数,c++也允许定义具有缺省参数的函数,这种函数调用时,参数个数可以与形参不相同。
缺省参数指在定义时函数时为形参指定缺省值。
这样的函数在调用时,对于缺省函数,可以给出实参,也可以不给出参数值。如果给出实参,将实参传递给形参进行调用,如果不给出实参,则按缺省值进行调用。
缺省参数的函数调用:缺省参数并不一定时常量表达式,可以是任意表达式,甚至可以通过函数调用给出。如果缺省实参时任意表达式,则函数每次被调用时则表达式被要求重新求值。但是表达式必须有意义。

#include<iostream>
int add1(int a=3,int b=6){
	return a+b;
}
int main() {
	cout<<add1()<<endl;//9
	cout<<add1(4)<<endl;//10
	cout<<add1(1,2)<<endl;//3
	return 0;
}

缺省参数可以有多个,但所有缺省参数必须放在参数,但是所有缺省参数必须放在参数表的右侧,即先定义所有的非缺省参数,在定义缺省参数。这是在函数调用时,参数自左向有逐个匹配,当实参个形参个数不一致时只有这样才不会产生二义性。
多文件结构

//A.h
void fun(int ,int b=23,int c=8000);
//void fun(int ,int =23.int =8000);
//A.cpp
void fun(int a,int b , int c) {
	cout << "a=" << a << "b=" << b << "c=" << c << endl;
}
//main.cpp
int main() {
	using namespace std;
	fun(12);
	fun(10, 20);
	fun(10, 20, 30);
	return 0;
}

运行结果:在这里插入图片描述
习惯上,缺省参数在公共头文件包含的函数声明中指定,不要再函数定义中指定。如果再函数的定义中指定缺省参数值,再公共头文件包含的函数声明中不能再次指定缺省参数值。缺省实参不一定必须是常量表达式,可以是任意表达式。

int my_rand() {
	srand(time(NULL));
	int ra = rand() % 100;
	return ra;
}
void fun(int a, int b = my_rand()) {
	cout << "a=" << a << "b=" << b << endl;

}
int main() {
	fun(12);
	return 0;
}

当缺省实参是一个表达式时 ,在函数被调用时该表达式被求值。(c语言不支持)

函数重载

C语言实现int,double,char类型的比较大小函数。

int my_max_i(int a,int b) {return a>b?a:b;}
double my_max_d(double a,double b) {return a>b?a:b;}
char my_max_c(char a,char b) {return a>b?a:b;}

这些函数都执行了相同的一般性动作,都返回两个形参中的最大值;从用户角度来看,只有一种操作,就是判断最大值。这种词汇上的复杂性不是“判断参数中的最大值”问题本身固有的,二十反应了程序设计环境的一种局限性:在同一个域中出现的名字必须指向一个唯实体(函数体)。
这就要程序员记住每一个函数的名字,函数重载解决了这种问题。
函数重载:在C++中可以为两个或两个以上的函数提供相同的函数名称,只要参数类型不同或者参数类型相同而参数个数不同称为函数重载

int my_max(int a, int b) {
	return a > b ? a : b;
}
double my_max(double a, double b) {
	return a > b ? a : b;
}
char my_max(char a, char b) { 
	return a > b ? a : b;
}

int main() {
	int ix = my_max(1, 2);
	double dx =my_max (12.23, 23.45);
	char cx = my_max('a', 'b');
	return 0;

}

如上,如果两个参数表中的参数个数或者顺序不同则认为两个函数重载。

判断函数重载的规则

1.如果两个参数的参数相同,但是返回类型不同,会被标记为编译错误,函数的重复声明。

int my_max(int a,int b){return a>b?a:b;}
unsigned int my_max(int a,int b){return a>b?a:b;}
int main() {
	int ix=my_max(12,23);
	unsigned int=my_max(12.23);//error 返回值为int
	return 0;
}

2.参数表的比较过程与形参名无关

int my_add(int a,int b);
int my_add(int x,int y);

3.如果两个函数的参数表中只缺省参数不同,则第二个声明被歧视为第一个的重复声明。

void Print(int*br,int n);
void Print(int* br,int len=10);

4.typedef名为先右数据提供了一个替换名,他并没有创建一个新类型,因此,如果两个参数表的区别只在于一个使用了typedef,而另一个使用了与typedef,而另一个使用了与typedef相应的类型。则该参数表被视为相同的参数列表。

typedef unsigned int u_int;
int Print(u_int a);
int Print(unsigned int b);

5.当一个参数类型又const或colatile修饰时,如果形参是按值传递方式定义,再识别函数声明是否相同时并不考虑修饰符。

void fun(int a) {}
void fun(const int a){}

6.当一个形参类型又const或者volatile修饰时,如果形参定义指针或引用时,在识别函数声明是否是相同时,就要考虑const修饰词。

void fun(int* p) {}
void fun(const int*p) {}
void fun(int& a) {}
void fun(const int &a) {}

7.注意函数调用的二义性,如果在两个函数的参数表中,形参类型相同,而形参个数不同,形参默认值将会影响函数的重载。

void fun(int a) {}
void fun(int a,int b) {}
void fun(int a,int b=10);

8.函数重载解析的步骤如下

  • 确定函数调用考虑的重载函数的结合,确定函数调用中实参表的属性,
  • 从重载函数集合中选择函数,该函数可以在(给出实参个数和类型)的情况下可以调用函数
  • 选择与调用最匹配的函数。

名字粉碎

在c++中可以实现函数重载就是因为名字粉碎技术使得重载函数在编译过程中进行了区别。例如:
在这里插入图片描述
_fastcall调用约定在输出函数名前加上一个“@”符号,在函数名后面也是一个“@”符号和其参数的字节数。格式为:@functionname@number
在这里插入图片描述

C++编译时函数名修饰约定规则

_cdecl调用约定
1.以“?”表示函数名的开始,后面跟函数名
2.函数名后面以@@YA表示参数表的开始,后跟参数表;
3.参数表以代号表示:
在这里插入图片描述
PA–表示指针,后面的代号表明指针类型,如果相同类型的指针连续出现,以“0”代替,一个“0”代表一次重复
4.参数表的第一项为该函数的返回值类型,其后一次为参数的数据类型,指针表示在其所指护具类型前;
5.参数表后以“@Z”标识整个名字的结束,如果该函数无参数,则以“Z”标识结束。
在这里插入图片描述

函数模板

为了代码重用,代码就必须是通用的;通用的代码就必须不受数据类型的限制。那么我们可以把数据类型改为一个设计参数。这种类型的程序设计我们称之为参数化程序设计。软件模块由模板构造,包括函数模板和类模板。
函数模板可以用来创建一个通用功能的函数,以支持多种不同形参,简化重载函数的设计。函数模板定义如下:

template<模板参数表>
返回类型 函数名(形式参数表) {
	...;//函数体
}

<模板参数表>,尖括号中不能为空,参数可以有多个,用逗号分开,模板参数主要是模板类型参数。
模板类型参数代表一种类型,由关键字class或typenname后加一个标识符构成,在这里两个关键字意义相同,他们表示后面的参数名代表一个潜在的内置或用户设计的类型。

template<class T>
T my_max(T a,T b){
	return a>b?a:b;
}
int main() {
	my_max(12,23);
	my_max('a','b');
	my_max(12.34,23,56);
	return 0;
}

在这里插入图片描述
在编译过程中,根据函数模板的实参构造出独立的函数,这就是模板函数,这个构造过程称之为模板实例化。

名字空间:nameplace

在C++中支持三种域:局部域,命名空间域,类域。命名空间域即使随C++引入的,相当于给一个文件域用花括号把文件的一部分括起来,并以关键字namespace开头给他起名。括起来的部分称为声明块(可以包括类,变量,函数等)。主要为了解决全局名字空间污染问题,即命名冲突。举例:

namespace yhp{
	int g_max=10;
	int g_min=0;
	int my_add(int a,int b){return a-b;}
}

名字空间域可以进行分层嵌套,同样有分层屏蔽作用,同一个工程中允许存在多个相同的明明空间,编译器最终会合成同一个命名空间。

命名空间的使用

1.加命名空间及作用域限定符

int main() {
	int a=yhp::my_add(12,23);
	printf("%lf n",Primer::pi);
	Primer::MAtrix::my_max('a','b');
	return 0;
}

2.使用using将名字空间中成员引入
使用using声明可只写一次限定修饰名。usiing声明以关键字using开头,后面是别限定修饰的名字空间成员名:

using yhp::pi;
using Primer::Matrix::my_max;
int main() {
	printf("%lf n",Primer::pi);
	printf("%f n",pi);
	my_max('a','b');
	return 0;
}

3.使用using namespace名字空间名称引入
使用using指示符可以一次性的使用空间中的所有成员直接被使用,比using声明方便。

//A.h
namespace yhp {
	int my_add(int, int);
	int my_sub(int,int);
}
//A.cpp
#include"A.h"
namespace yhp {
	int my_add(int a, int b) {
		return a + b;
	}
	int my_sub(int a, int b) {
		return a - b;
	}
}
//main.cpp
#include"A.h"
#include<iostream>
using namespace std;

using namespace yhp;

int main() {
	printf("%d n",my_add(12, 23));
	return 0;
}

使用using指示符,标准C++库中所有组件都在一个std的名字空间中声明和定义的,所以使用标准C++库只写一个using指示符:using namespace std;就可以直接使用标准C++库中所有成员。

new/delete

可执行空间的虚拟地址空间:在这里插入图片描述

内核:操作系统
栈区:函数的形参,非静态的局部变量,函数现场保护数据等等 栈是向下增长的。
共享库的内存映射区域:用于装载一个共享的动态内存库。用户可使用系统接口创建共享内存,做进程通信。
堆区:用于程序运行时动态分配内存,堆时可以向上增长的。
数据段:存储全局数据和静态数据。
代码段:可执行的程序和常量数据。
C语言的动态内存管理用malloc,calloc,realloc等函数。

int* ipa=(int*)malloc(sizeof(int)*n);
int *ipb=(int*)calloc(n,sizeof(int));
ipa=(int*)realloc(ipa,sizeof(int)*n*2);

C++的动态内存管理

1.new的运算符使用

int main() {
	int n=10;
	int* ipa=new int(10);//直接进行赋值
	int* ipb=new int[3]{1,2,3};
	int* ipc=new int[n]{1,2,3,4,5,6,7};//数组进行赋值
	delete ipa;
	delete[]ipb;//释放
	delete[]ipc;
	return 0;
}

2.new的函数方式使用

int main() {
	int n = 10;
	int* ipa = (int*)::operator new(sizeof(int));
	int* ipb = (int*)::operator new(sizeof(int) * n);
	::operator delete(ipa);
	::operator delete(ipb);
	return 0;
}

3.定位new(placement newexpression)的使用

int main() {
	int n=10;
	int* ipa=(int*)malloc(sizeof(int));
	int* ipb=(int*)::operator new(sizeof(int)*n);
	new(ipa)int(20);
	new(ipb)int[]{1,2,3,4,5,6,7,8,9};
	free(ipa);
	::operator delete(ipb);
	return 0;
}

4.对于内置类型new/delete/malloc/free可以混用。
区别:

  • new/delete是C++中的运算符。malloc/free是函数。
  • malloc申请内存空间时,手动计算所需大小,new只需类型名,自动计算大小;
  • malloc申请的内存空间不会初始化,new可以初始化;
  • malloc的返回值为void*,接收时必须强转,new不需要;
  • malloc申请内存空间失败时,返回的是NULL,使用时必须判空;new申请内存空间失败时抛出异常,所以要有捕获异常处理程序。

C11的新特性

类型推导

auto类型推导:auto定义的变量,可以根据初始化的值,在编译时推导出变量名的类型。

int main() {
	auto x=5;//x为int类型
	auto pi=new auto(1);// pi被推到为int*
	const auto *xp=&x,u=6//xp是const int*类型,u是const int类型
	static auto dx=0.0//double
	auto int b;//C11中auto不再表示存储类型指示符
	auto s;//error 没有初始化 auto无法推导出s的类型
}
int main() {
	auto x=5;
	const auto *xp=&x,u;//error
	const auto* ip=&x,u=6.0;//error
	return 0;
}

1.虽然经过前面const auto* xp=&x推导,auto的类型可以确定为int了,但是仍要写后面的=6,否则编译器不予通过。
2.u的初始化不能使编译器推导产生二义性。
auto的一些使用方法可以和同指针,引用结合起来使用,还可以带上cv限定。
1)当不声明为指针或引用时,auto的推到结果和初始化表达式抛弃引用和cv限定后类型一致.
2)当声明为指针或引用时,auto的推导结果将保持初始化表达式的cv属性。
auto不能作为函数形参类

auto的限制

  • C11中auto称为类型指示符
  • auto不能用于函数参数
  • auto不能用于非静态成员变量
  • auto无法定义数组
  • 实例化模板时不能使用auto作为模板参数

可以推导函数返回值

template<class T>
T my_max(T a,T b){
	return a>b?a:b;
}

int main() {
	auto x=my_max(12,23);
	auto y=my_max('a','b');
	cout<<x<<"    "<<y<<endl;
	return 0;
}

decltype关键字

auto所修饰的变量必须被初始化,即必须要定义变量,若仅希望得到类型不需要定义变量应该怎么办呢?C++11新增了decltype关键字:decltype(exp),exp表示一个表达式,器推导过程是在编译器完成的,不会真正的计算表达式的值。

int main() {
	int x=10;
	decltype(x) y=1;//y->int
	const int &i=x;
	decltype(i) j=y;//j->const int &
	decltype(x+y) z=0;//z->int
	const decltype(z)*ip=&z;//*ip->int,ip->int*
}

也可以用于函数表达式,但不会真正计算表达式的值。

基于范围的for循环

不同容器和数组,遍历的方法不尽相同,写法不同意,也不够简洁,而C++11基于范围的fpr循环以统一,简洁的方式来遍历容器和数组,用起来更加方便了。

遍历数组(容器)

int main(){
	int arr[]={1,2,3,4,5};
	int len=sizeof(arr)/sizeof(arr[0]);
	int* ip=NULL;
	for(ip=arr;ip!=ip+len;ip++){
		cout<<*ip<<endl;
	}
}

基于范围的for循环

int main() {
	int arr[]={1,2,3,4,5};
	for(int x:arr){
		cout<<x<<" ";	
	}
	return end;
	return 0;
}

模板:

for(ElenType val:array){
	...//循环体
}
//ElenType:是范围变量的数据类型。他必须是数组元素相同的数据类型,或者数组元素可以自动转换过来的类型。
//val:是范围变量的名称。
//array:是让该循环体进行处理的数组名称
//循环体中可以用continue结束本次循环,也可以用break跳出循环

可以使用auto自动推导出val类型

int main() {
	int ar[]={1,2,3,4,5};
	for(auto x:ar){
		x+=10;
		cout<<x<<" ";
	}
}

指针空值–nullptr

  • nullptr是C11新引入的指针控制类型的常量,在C++中可以直接使用。
  • sizeof(nullptr)与sizeof((void*)0)所占字节数相同都(4,8)。
  • 为了提高代码的健壮性,在后续表示指针空值最好用nullptr。

typedef与using的使用

typedef unsigned int uint;
using uint=unsigned int;

template<class _Ty>
using pointer=_Ty*;
int main() {
	int x=10;
	double dx=12.25;
	pointer<int>ip=&x;
	pointer<double>dp=&dx;
	return 0;
}

string的使用

int main() {
	char str[] = { "tulun" };
	int len = strlen(str);
	string s1 = "tulun";
	for (int i = 0; i < len; ++i) {
		cout << str[i];
	}
	for (int i = 0; i < s1.size(); ++i) {
		cout << s1[i];
	}
	cout << s1 << endl;
	s1 = "hello";
	cout << s1 << endl;
	s1 += "tulun";
	cout << s1 << endl;
	cin >> s1;
	cout << s1 << endl;
	return 0;
}

运行结果:在这里插入图片描述

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

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

相关文章

Goby 征文大擂台,超值盲盒等你来!

001 Goby 技术征文正式启动 Goby 致力于做最好的网络安全工具。为了促进师傅们知识共享和技术交流&#xff0c;现发起关于 Goby 的技术文章征集活动&#xff01; 欢迎所有师傅们参加&#xff0c;分享您的使用经验或挖洞窍门等&#xff0c;帮助其他人更好地了解和利用 Goby。 …

Winform界面实现控件中英文语言切换

一、业务需求 在Winform项目的开发过程中,涉及到一个基础的功能就是需要对界面中的显示语言内容可以进行选择切换,方便不同地区的使用者快速上手使用;效果如下: 二、需求分析 需要实现对Winform项目界面显示语言可选择切换步骤如下: ①修改控件的显示内容; ②获取到界面显…

【计算机网络】数据链路层

概述 封装成帧 差错检验 可靠传输 实现机制 可靠传输的实现机制 停止等待协议 回退N帧协议 选择重传协议 【计算机网络】MAC帧和PPP帧&#xff08;定义使用范围区别共同点&#xff09;_GPNU_Log的博客-CSDN博客_ppp帧 PPP帧和以太网帧 | Mixoo 数据链路层的协议有PPP协…

Rman单实例迁移到单实例

关于同平台同版本数据库之间的迁移操作的实验 ---Source DB[rootoracle-db-19cs ~]# cat /etc/redhat-release CentOS Stream release 8 [rootoracle-db-19cs ~]# --- Target DB[rootoracle-db-19ct ~]# cat /etc/redhat-release CentOS Stream release 8 [rootoracle-db-19ct…

如何使用dlinject将一个代码库实时注入到Linux进程中

关于dlinject dlinject是一款针对Linux进程安全的注入测试工具&#xff0c;在该工具的帮助下&#xff0c;广大研究人员可以在不使用ptrace的情况下&#xff0c;轻松向正在运行的Linux进程中注入一个共享代码库&#xff08;比如说任意代码&#xff09;。之所以开发该工具&#…

扬帆优配|新概念火了!时空大数据龙头再冲击涨停

时空大数据近期受资金追捧。 今天早盘&#xff0c;中通邦本开盘后再度冲击涨停&#xff0c;一度封死涨停板&#xff0c;之后涨停打开&#xff0c;截至上午收盘仍上涨超5%。此前&#xff0c;中通邦本已接连两日涨停&#xff0c;公司在互动渠道上表示&#xff0c;参股公司北京邦本…

Spring中Bean生命周期及循环依赖

spring中所说的bean对象 与 我们自己new的对象(原始对象)是不同的&#xff1b;bean对象是指spring框架创建管理的我们的对象生命周期即&#xff1a;何时生&#xff0c;何时死1.实例化 Instantiation&#xff1a;spring通过反射机制以及工厂创建出来的原始对象&#xff1b;2.属性…

【Spring】八种常见Bean加载方式

&#x1f6a9;本文已收录至专栏&#xff1a;Spring家族学习 一.引入 (1) 概述 ​ 关于bean的加载方式&#xff0c;spring提供了各种各样的形式。因为spring管理bean整体上来说就是由spring维护对象的生命周期&#xff0c;所以bean的加载可以从大的方面划分成2种形式&#xff…

2023年融资融券研究报告

第一章 行业概况 融资融券是证券交易市场上的两种金融衍生品交易方式&#xff0c;主要用于股票、债券等证券的融资和投资。 融资是指投资者向证券公司借入资金购买证券&#xff0c;以期望股票价格上涨后卖出获得利润。融资需支付一定的利息和费用&#xff0c;利息根据借入的资…

CSS实现checkbox选中动画

前言 &#x1f44f;CSS实现checkbox选中动画&#xff0c;速速来Get吧~ &#x1f947;文末分享源代码。记得点赞关注收藏&#xff01; 1.实现效果 2.实现步骤 定义css变量&#xff0c;–checked&#xff0c;表示激活选中色值 :root {--checked: orange; }创建父容器&#xf…

python+pytest接口自动化(6)-请求参数格式的确定

我们在做接口测试之前&#xff0c;先需要根据接口文档或抓包接口数据&#xff0c;搞清楚被测接口的详细内容&#xff0c;其中就包含请求参数的编码格式&#xff0c;从而使用对应的参数格式发送请求。例如某个接口规定的请求主体的编码方式为 application/json&#xff0c;那么在…

Go 实现 AOI 区域视野管理

在游戏中,场景里存在大量的物体.如果我们把所有物体的变化都广播给玩家.那客户端很难承受这么大的压力.因此我们肯定会做优化.把不必要的信息过滤掉.如只关心玩家视野所看到的.减轻客户端的压力,给玩家更流畅的体验. 优化的思路一般是: 第一个是尽量降低向客户端同步对象的数量…

【Java】P1 基础知识与碎碎念

Java 基础知识 碎碎念安装 Intellij IDEAJDK 与 JREJava 运行过程Java 系统配置Java 运行过程Java的三大分类前言 本节内容主要围绕Java基础内容&#xff0c;从Java的安装到helloworld&#xff0c;什么是JDK与什么是JRE&#xff0c;系统环境配置&#xff0c;不深入Java代码知识…

传导EMI抑制-Π型滤波器设计

1 传导电磁干扰简介 在开关电源中&#xff0c;开关管周期性的通断会产生周期性的电流突变&#xff08;di/dt&#xff09;和电压突变(dv/dt)&#xff0c;周期性的电流变化和电压变化则会导致电磁干扰的产生。 图1所示为Buck电路的电流变化&#xff0c;在Buck电路中上管电流和下…

ubuntu 22.04 mangodb

文章写在2023年3月1日 目前最新的mangodb稳定版本是6.04 1.安装server server安装包为mangodb的程序主体。 服务器deb安装包下载地址 https://www.mongodb.com/try/download/community ubuntu22.04的server deb 文件url https://repo.mongodb.org/apt/ubuntu/dists/jammy/mo…

计算机组成原理 浮点数运算清晰明了

注释&#xff1a;阶码和尾数都需要符号位区分正负 例题1&#xff1a;x 2^-11*0.100101&#xff0c; y 2^-10*(-0.011110)&#xff0c;求xy 第零步 补码表示 对于x来说-11 补码表示为 11011&#xff1b; 0.100101补码表示为00.100101对于y来说-10补码表示为 10110&#xff…

【el】表单

elementUI中的表单相关问题一、用法1、动态表单调用接口返回表单&#xff0c;后端的接口返回值如下&#xff1a;这些是渲染后的效果页面使用&#xff08;父组件&#xff09;<el-button size"small" class"Cancelbtn" click"sub(true)">发起…

python程序员狂飙上头——京海市大嫂单推人做个日历不过分吧?

嗨害大家好鸭&#xff01;我是小熊猫~ 这个反黑剧其实火了很久了&#xff0c; 但是我现在才有空开始看 该说不说&#xff0c;真的很上头&#xff01;&#xff01;&#xff01; 大嫂简直就像是干枯沙漠里的玫瑰 让人眼前一亮哇~~ 我小熊猫此时此刻就成为大嫂的单推人&…

Auto-encoder 系列

Auto-Encoder (AE)Auto-encoder概念自编码器要做的事&#xff1a;将高维的信息通过encoder压缩到一个低维的code内&#xff0c;然后再使用decoder对其进行重建。“自”不是自动&#xff0c;而是自己训练[1]。PCA要做的事其实与AE一样&#xff0c;只是没有神经网络。对于一个输入…

Django学习——基础篇(上)

一、Django的安装 pip install djangopython目录下出现两个文件 djando-admin.exe django django-admin.exe django 二、创建项目 1.命令行&#xff08;终端&#xff09; 1.打开终端 winR 输入cmd 2.进入项目目录 3.执行命令创建项目 2.Pycharm 两种方法对比 1.命令行创…