ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

最后一遍温习C语言(北京大学慕课)

2021-10-24 12:05:03  阅读:175  来源: 互联网

标签:慕课 const C语言 int st 排序 温习 include 指针


C语言基本知识

前言

自己学过C语言,温习所写,皆为自身的心得体会,写的非常简短,不适合初学者看,写的一般,请多包涵。

C语言快速入门

#include <iostream>
#include <cstdio>

变量:用来存放数据
%d:表示等待输入整数
&a:表示把输入的整数放入变量a
程序的注释:多行注释、单行注释

变量和数据类型

变量代表系统分配的内存空间。
名字决定地址,类型决定字节。
先定义,再使用或者说引用。
变量名不能和C++预留的保留字相同。
数据类型说明一个变量表示什么样的数据。
数据类型的自动转换:不同数据类型的数据可以互相赋值。
整数转化为字符型只保留最右边的一个字节。
整型和浮点数转化。

常量

值不会改变的量。
十六进制以“0x”开头。
八进制以“0”开头。
0-9:48-57
A-Z:65-90
a-z:97-122
\n:10换行,输出位置下一行
\r:13回车,输出位置本行开头
\t:9制表符,输出位置下一个制表符开头
字符型常量单引号char,字符串常量双引号
字符串常量中转义字符也可以生效(\,",’)。
符号常量:宏定义#define 名字 值,比数值常量方便。

运算符

格式控制符%d%f%c等等。

scanf("%d%c",&n,&c);//此时输入34k,中间不要加空格

输入字符不会跳过空格,其他类型会跳过。
scanf有除了%之外的非控制字符,输入时也有,则会跳过。

scanf("%d %c",&n,&c);//此时输入的时候可以添加空格

控制printf输出的宽度:%nd空格来补,%0nd零来补。
控制printf输出的浮点数的精度:%.nf。
cin进行输入,cout进行输出。
cin.get作用:从标准输入吸收任何字符(包括回车和空格),优先吸收cin缓存(之前cin的残留内容)。

#include <iostream>
using namespace std;
 
int main()
{
char ch;
cout << "This program has paused. Press Enter to continue.";
cin.get(ch);
cout<<(int)ch<<endl;
cout << "It has paused a second time. Please press Enter again."; ch = cin.get();cout<<(int)ch<<endl;
cout << "It has paused a third time. Please press Enter again.";cin.get();cout<<(int)ch<<endl;
cout << "Thank you! \n";
return 0;
}

***cin.get()一次只能读取最早缓存的一个字符,可以一次性输入多个字符,但是读取的时候只能一个一个的读取。
cin.get()读取输入的所有字符,会返回一个大于0的整型,读不到会返回-1

//读入所有输入的字符:即显示输入的字符串
#include <iostream>
using namespace std;
int main()
{
	int c;
	while((c=cin.get())!=EOF)
	{
		cout<<(char)c;
	}
	return 0;
}
#include <iostream>
#include <cstdio>
using namespace std;
int main()
{
	int c;
	while(scanf("%c",&c)!=EOF)
	{
		printf("%c",c);
	}
	return 0;
}

只有^z才可以结束输入。
赋值运算符
算术运算符
++a返回+1后的值
a++返回+1前的值
关系运算符
逻辑运算符:&& || !
逻辑表达式的短路计算
强制类型转换运算符
优先级
++,–,!最高了
算术
关系
逻辑
赋值

条件分支结构和循环结构

if语句和switch语句
for语句和while语句
break语句
出现在循环体中,用来跳出当前的一层循环。
continue语句
出现在循环体中,用来结束本次循环,不跳出当前循环。

freopen重定向输入

输入由键盘重定向为文件,运行时就可以不用输入数据了。
例:freopen(“C:\test.txt”,“r”,stdin);//包括转义字符

数组

一维数组定义。
元素一个挨一个的连续存放。
筛法求n以内的所有素数:去掉46810,去掉69,最后生下了2357。
(标志数组isPrime,1是素数,0不是素数)
数组的初始化。
数组越界
下标的值为负数或者太大了。
二维数组

函数

一些实现了某种功能的需要反复使用的代码包装而成的功能模块。
函数调用语句进入函数执行,返回值语句进入主函数执行。
函数声明在函数的调用之前,函数定义不一定要在函数调用之前。
函数声明又叫做函数原型,参数名称可以忽略,但是参数的类型必须要有。
形参是实参的拷贝,形参改变不影响实参,除非形参是数组。
一维数组作为函数的参数,不用写出数组的元素个数,形参数组改变,实参数组也改变。
二维数组作为函数的参数,不用写出有多少行,但是必须要写出有多少列。
递归:一个函数自己调用自己。
递归必须要有终止条件,否则会无限制的循环下去的。
库函数:编译器自带的函数。
头文件:包含许多库函数的声明以及其他信息。
位运算:与&、或|、异或^、非~、左移<<、右移>>。
与:某些位清零其他位不变,获取某变量中的某一位。
或:某些位置一其他位不变。
异或:某些位取反其他位不变。
左移:高位丢弃,低位补零。左移n位,相当于乘以2的n次方。
右移:符号位为1,补1;高位为0,补0。右移n位,相当于除以2的n次方。

字符串

字符串常量:字符数目+1,还有一个结尾字符‘\0’。
双引号要写为",\要写为\。
用cin读入字符串:回车为止

cin<<一维字符数组名
cout>>一维字符数组名

用scanf读入字符串:空格/回车为止

scanf("%s",一维字符数组名);
printf("%s",一维字符数组名);

***二者都会自动添加结尾字符,可能会发生数组越界。
用gets读入字符串:回车为止

gets(一维字符数组名)

字符串库函数
cstring,字符串函数都以’\0‘来判断字符串的结尾,实参可以是一维字符数组或者字符串常量。
字符串拷贝:strcpy后面拷贝到前面。
字符串比较大小:int strcmp,返回0则相等。
求字符串的长度:int strlen。
字符串拼接:strcat,后面的加到前面的后面。
字符串转化为大写:strupr。
字符串转化为小写:strlwr。

指针

一个变量,代表了一个内存地址。
指针变量的类型是int*、char*等等。
*p是一个表达式,代表着从地址p开始的sizeof(T)个字节的内容。
*是间接引用运算符。
指针指向变量==变量地址赋值给指针。
&取地址运算符。
意义:指针可以让人们直接自由访问内存空间,不仅限于变量所在的存储空间。
***在写一些接近硬件的程序,比如硬件驱动程序、病毒等等,就需要不仅限于变量所在的内存空间。
指针的互相赋值,必须是相同类型,如果不是相同类型必须先进行强制类型转化。
两个同类型的指针可以比较大小。
两个同类型的指针可以相减。
指针变量加减一个整数的结果仍然是指针。
指针变量可以自增、自减。
指针可以用下标运算符[ ]进行运算。
空指针:指向地址0的指针。
地址0不能访问。
指针可以作为条件表达式来使用,if(p)。
指针作为函数参数。(没有违背形参是实参的拷贝,此时形参确实是实参的拷贝,只不过实参是地址,此时形参拷贝的是地址,使用的时候使用的是地址指向的内容,而不是直接使用的形参,因此操作额结果并不会发生改变)
数组的名字就是一个指针常量。
二维数组T a[N][N]中,a[N]是一个类型为T *的指针。
指向指针的指针。
字符数组名的类型是char星。
字符串操作库函数
char *strchr:找到字符c第一次出现的位置。
char *strstr:寻找子串第一次出现的位置。
int stricmp:大小写无关的字符串比较。
int strncmp:前n个子串的大小比较。
char *strncpy:只拷贝前n个字符。
char *strtok:从字符串中逐个抽出被某些字符分隔的子串。
void指针
内存操作库函数
void *memset:将从字符串某位置开始的n个字节都设置成某个初始值。
void *memcpy:将从地址开始的n个字节拷贝到另一个字节中去。
函数指针:指向函数的指针变量,int(*p)(int char);。
***函数指针的调用:函数指针名赋值,函数指针名(参数)。
qsort快速排序库函数:起始地址,元素个数,元素大小,排序规则。
(排序规则函数中,如果返回值小于0,那么排在前面)。

结构

一种自定义的数据类型,会有一个名字,这个名字可以用来定义变量。
访问结构变量的成员变量。
结构数组。
指向结构变量的指针(也可以通过指针访问成员变量)。

各种变量

全局变量
局部变量
静态变量:全局+static的局部,地址一定不变,非静态每次都可能会发生改变。
变量的作用域:作用域大的被小的屏蔽。
变量的生存期:在此期间,变量占有内存空间,且只能归它使用。

选择排序(n*n)

从前往后依次找最小的那个。

插入排序(n*n)

有序的在左边,无序的在右边,开始有序的就只有a[0],每次取出无序数组的最左边的一个元素加入到有序数组中去,直到无序中没有元素。

冒泡排序(n*n)

有序的在右边,无序的在左边,开始有序的啥也没有,无序的从左到右找最大的放到有序的最左边,依次这么进行下去,直到无序的没有任何元素为止。

快速排序(n*logn)

二分查找(logn)

STL初步

STL:标准模板库,其中包括一些常用的算法和数据结构。
使用算法#include “algorithm”
1.用sort进行排序
sort(数组名+n1,数组名+n2)。
将数组中下标范围为[n1,n2)的元素从小到大排序。
sort(数组名+n1,数组名+n2,greater())。
将数组中下标范围为[n1,n2)的元素从大到小排序。

#include <iostream>
#include <cstring>
#include <algorithm>
using namespace std;
struct Rule1{
	bool operator()(const int &a1,const int &a2)const{
		return a1>a2;//按从大到小排序 
	}
};
struct Rule2{
	bool operator()(const int &a1,const int &a2)const{
		return a1%10 < a2%10;//按个位数从小到大排序 
	}
};
void Print(int a[],int size)
{
	for(int i=0;i<size;++i)
		cout<<a[i]<<",";
	cout<<endl;
}
int main()
{
	int a[]={12,45,3,98,21,7};
	sort(a,a+sizeof(a)/sizeof(int));
	Print(a,sizeof(a)/sizeof(int));
	sort(a,a+sizeof(a)/sizeof(int),Rule1());
	Print(a,sizeof(a)/sizeof(int));
	sort(a,a+sizeof(a)/sizeof(int),Rule2());
	Print(a,sizeof(a)/sizeof(int));
	return 0;
}

在这里插入图片描述
sort(数组名+n1,数组名+n2,排序规则结构名())。
排序规则结构定义:
struct 结构名
{
bool operator()(const T &a1,const T &a2)const{
//a1应该排在前面,返回true,否则返回false
}
}

#include <iostream>
#include <cstring>
#include <algorithm>
using namespace std;
struct Student{
	char name[20];
	int id;
	double gpa;
};
Student students[]={
	{"Jack",112,3.4},{"Mary",102,3.8},{"Mary",117,3.9},
	{"Ala",333,3.5},{"Zero",101,4.0}
};
struct StudentRule1{//按姓名从小到大排序 
	bool operator()(const Student &s1,const Student &s2)const{
		if(stricmp(s1.name,s2.name)<0)
			return true;
		return false;
	}
};
struct StudentRule2{//按id从小到大排序 
	bool operator()(const Student &s1,const Student &s2)const{
		return s1.id<s2.id;
	}
};
struct StudentRule3{//按gpa从高到低排序 
	bool operator()(const Student &s1,const Student &s2)const{
		return s1.gpa>s2.gpa; 
	}
};
void PrintStudents(Student s[],int size)
{
	for(int i=0;i<size;++i)
		cout<<"("<<s[i].name<<","
			<<s[i].id<<","<<s[i].gpa<<")";
	cout<<endl;
}
int main()
{
	int n=sizeof(students)/sizeof(Student);
	sort(students,students+n,StudentRule1());
	PrintStudents(students,n);
	sort(students,students+n,StudentRule2());
	PrintStudents(students,n);
	sort(students,students+n,StudentRule3());
	PrintStudents(students,n);
	return 0;
}

在这里插入图片描述
2.二分查找算法
在从小到大的数组中进行二分查找。
binary_search(数组名+n1,数组名+n2,值)。
自定义排序规则、任何类型数组中进行二分查找。
binary_search(数组名+n1,数组名+n2,排序规则结构名())。

#include <iostream>
#include <cstring>
#include <algorithm>
using namespace std;
struct Rule{
	bool operator()(const int &a1,const int &a2)const{
		return a1%10<a2%10;
	}
};
void Print(int a[],int size){
	for(int i=0;i<size;++i){
		cout<<a[i]<<",";
	}
	cout<<endl;
}
int main()
{
	int a[]={12,45,3,98,21,7};
	sort(a,a+6);
	Print(a,6);
	cout<<binary_search(a,a+6,12)<<endl;
	sort(a,a+6,Rule());
	Print(a,6);
	cout<<binary_search(a,a+6,12)<<endl;
	cout<<binary_search(a,a+6,8,Rule())<<endl;
	return 0;
}

在这里插入图片描述
用lower_bound()二分查找下界(大于等于)。
用upper_bound()二分查找上界(大于)。
在这里插入图片描述
3.multiset
希望增加删除数据、查找数据都能快速完成,可以用平衡二叉树数据结构存放数据,具体体现在multiset,set,multimap,map四种”排序容器“中。

multiset<type> st;
st中可以存放type类型的数据并且自动从小到大排序
st.insert
st.find
st.erase
复杂度都是log(n)
#include <iostream>
#include <cstring>
#include <set>//multiset和set的头文件
using namespace std;
int main()
{
	multiset<int> st;
	int a[10]={1,14,12,13,7,13,21,19,8,8};
	for(int i=0;i<10;i++)
	{
		st.insert(a[i]);//插入的是a[i]的复制品
	}
	multiset<int>::iterator i;//迭代器,类似于指针,必须通过迭代器来访问容器中的元素
	for(i=st.begin();i!=st.end();++i)
		cout<<*i<<",";//*i类似于指针的*p,表示指针指向的内容
	cout<<endl;
}

迭代器

multiset<T>::iterstor p;

迭代器类似于指针,不同的是,迭代器只能++和–,只能比较!=或者==,不能比较大小,不能加减整数,也不能相减。

st.begin()返回值为迭代器类型,指向头一个元素的迭代器
st.end()返回值为迭代器类型,指向最后一个元素的后一个迭代器

//查找
i=st.find(22);
if(i=st.end())cout<<"not found"<<endl;
st.insert(22);
//成员函数的使用
//寻找13之前的第一个元素的迭代器
i=st.low_bound(13);
cout<<*i<<endl;
//寻找8之后的第一个元素的迭代器
i=st.upper_bound(8);
cout<<*i<<endl;
//删除迭代器i指向的元素
st.erase(i);
for(i=st.begin();i!=st.end();++i)
{
	cout<<*i<<" ";
}
return 0;

自定义排序规则的multiset

#include <iostream>
#include <cstring>
#include <set>
using namespace std;
struct Rule1{
	bool operator()(const int &a,const int &b){
		return (a%10)<(b%10);
	}//返回值为true说明a的个位数必须小于b的个位数
};
int main()
{
	multiset<int,greater<int>> st;//排序规则为从大到小
	int a[10]={1,14,12,13,7,13,21,19,8,8};
	for(int i=0;i<10;++i)
		st.insert(a[i]);
	multiset<int,greater<int>>::iterator i;
	for(i=st.begin();i!=st.end();++i)
		cout<<*i<<",";
	cout<<endl;

	multiset<int,Rule1> st2;//排序规则为个位数从小到大
	int a[10]={1,14,12,13,7,13,21,19,8,8};
	for(int i=0;i<10;++i)
		st.insert(a[i]);
	multiset<int,Rule1>::iterator p;
	for(p=st.begin();p!=st.end();++p)
		cout<<*p<<",";
	cout<<endl;

	p=st2.find(133);
	cout<<*p<<endl;//输出13
	//find(x):在容器中找一个元素y,使得”x必须排在y前面“和”y必须排在x前面“都不成立,那么我们就认为二者相等,并不是一定要x==y
}
#include <iostream>
#include <cstring>
#include <algorithm>
#include <set>
using namespace std;
struct Student{
	char name[20];
	int id;
	int score;
};
Student students[]={{"Jack",112,78},{"Mary",102,85},{"Ala",333,92},{"Zero",101,70},{"Cindy",102,78}};
struct Rule{
	bool operator()(const Student &s1,const Student &s2)const
	{
		if(s1.score!=s2.score)
			return s1.score>s2.score;
		else
			return (strcmp(s1.name,s2.name)<0);
	}
};
int main()
{
	multiset<Student,Rule> st;
	for(int i=0;i<5;++i)
		st.insert(student[i]);
	multiset<Student,Rule>::iterator p;
	for(p=st.begin();p!=st.end();++p)
		cout<<p->score<<" "<<p->name<<" "<<p->id<<endl;
	Student s={"Mary",1000,85};
	p=st.find(s);
	if(p!=st.end())
	{
		cout<<p->score<<" "<<p->name<<" "<<p->id<<endl;
	}
	return 0;
}

4.set
和multiset的区别在于容器中不能有重复的元素(重复:并不是”==“)(插入元素可能不成功)。

#include <iostream>
#include <cstring>
#include <set>
using namespace std;
int main()
{
	set<int> st;
	int a[10]={1,2,3,8,7,7,5,6,8,12};
	for(int i=0;i<10;++i)
		st.insert(a[i]);
	cout<<st.size()<<endl;//输出8,重复的元素不占
	set<int>::iterator i;
	for(i=st.begin();i!=st.end();++i)
		cout<<*i<<",";//输出1 2 3 5 6 7 8 12,没有重复元素
	cout<<endl;
}
//插入写法
pair<set<int>::iterator,bool>=st.insert(2);
if(!result.second)
	cout<<*result.first<<"already exists."<<endl;
else
	cout<<*result.first<<"inserted."<<endl;
return 0;

5.multimap

multimap<T1,T2> mp;//元素都是pair类型
struct{
	T1 first;//关键字
	T2 second;//值
};
mp中元素按照first排序,可以按照first进行查找。
#include <iostream>
#include <map>
#include <cstring>
using namespace std;
struct StudentInfo{
	int id;
	char name[20];
};
struct Student{
	int score;
	StudentInfo info;
};
typedef multimap<int,StudentInfo> MAP_STD;//给类型起个别名
int main()
{
	MAO_STD mp;
	Student st;
	char cmd[20];
	while(cin>>cmd)
	{
		if(cmd[0]=='A')//插入
		{
			cin>>st.info.name>>st.info.id>>st.score;
			mp.insert(make_pair(st.score,st.info));
		}
		else if(cmd[0]=='Q')//查找
		{
			int score;
			cin>>score;
			MAP_STD::iterator p=mp.lower_bound(score);//迭代器,寻找比score小的第一个元素
			if(p!=mp.begin())//说明找到了符合要求的元素
			{
				--p;
				score=p->first;//比要查询的分数低的最高分
				MAP_STD::iterator maxp=p;
				int maxId=p->second.id;
				for(;p!=mp.begin()&&p->first==score;--p)
				{
					if(p->second.id>maxId)
					{
						maxp=p;
						maxId=p->second.id;
					}
				}
			}
			if(p->first==score)
			{
				if(p->second.id>maxId)
				{
					maxp=p;
					maxId=p->second.id;
				}
			}
			cout<<maxp->second.name<<" "
				<<maxp->second.id<<" "
				<<maxp->first<<endl;
		}
		else
			cout<<"Nobody"<<endl;
	}
	return 0;
}

6.map
不能有重复的元素,可以使用[ ],下标为关键字,返回值为关键字相同的元素的second,有可能会插入失败。

#include <iostream>
#incldue <map>
#include <string>
using namespcae std;
struct Stduden{
	string name;
	int score;
};
Student students[5]={{"Jack",89},{"Tom",74},{"Cindy",87},{"Alysa",87},{"Micheal",98}};
typedef map<string,int> MP;
int main()
{
	MP mp;
	for(int i=0;i<5;++i)
	{
			mp.insert(make_pair(students[i].name,students[i].score));
	}
	cout<<mp["Jack"]<<endl;//输出为89
	mp["Jack"]=60;//修改second为60
	for(MP::iterstor i=mp.begin();i!=mp.end();++i)
		cout<<"("<<i->first<<","<<i->second<<<")";
	cout<<endl;
	Stdudent st;
	st.name="Jack";
	st.score=99;
	pair<MP::iterator,bool>p=mp.insert(make_pair(st.name,st.score));
	if(p.second)
		cout<<"("<<p.first->first<<","<<p.first->second<<")inserted"<<endl;
	else
		cout<<"insertion failed"<<endl;
	mp["Harry"]=78;
	MP::iterator q=mp.fond("Harry");
	cout<<"("<<q->first<<","<<q->second<<")"<<endl;
	return 0;
}
#include <iostream>
#include <set>
#include <map>
#include <string>
using namespace std;
struct Wore{
	int times;
	string wd;
};
struct Rule{
	bool operator()(const Word &s1,const Word &s2)const
	{
		if(w1.times!=w2.times)
			return w1.times>w2.times;
		else
			return w1.wd<w2.wd;
	}
};
int main()
{
	string s;
	set<Word,Rule> st;
	map<string,int> mp;
	while(cin>>s)++mp[s];
	for(map<string,int>::iterator i=mp.begin();i!=mp.end();++i)
	{
		Word tmp;
		tmp.wd=i->first;
		tmp.times=i->second;
		st.insert(tmp);
	}
	for(set<Word,Rule>::iterator i=st.begin();i!=st.end();++i)
		cout<<i->wd<<" "<<i->times<<endl;
}

标签:慕课,const,C语言,int,st,排序,温习,include,指针
来源: https://blog.csdn.net/m0_52133556/article/details/119693844

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有