C语言相关
标准输入输出
格式化输入输出
int a,b;
int arr[10]={1},*p=&b;
double d;
char ch,str[30];
scanf("%d%d",&a,p);
scanf("%c%s",&ch,str);
scanf("%lf",&d);
scanf("%d%d",arr+1,&arr[2]);
printf("%-10d %10d\n",a,*p);//'-'表示左对齐(默认右对齐),"10"表示位宽
printf("%c--%s\n",ch,str);
printf("%05.2lf",d);//注意这里,C99只能用%f输出//'0'表示前面的空格用前导0代替,".2"表示保留两位小数
printf("%d %d %d\n",arr[0],arr[1],arr[2]);
printf("%o\n",arr);//‘o’表示八进制,这里是试图输出地址。
字符数据的输入输出
char c,s[20];
c=getchar();
putchar(c);
char ch;
scanf("%c",&ch);
if(ch>='a'&&ch<='z')ch=ch-'a'+'A';
else if(ch>='A'&&ch<='Z')ch=ch-'A'+'a';
printf("%c\n",ch);s=gets();
puts(s);
预处理命令
变量:
变量必须定义在函数开头(尤其注意for循环。。。)
变量的存在性(可见性)
遵循内部优先原则(如果程序块内外都定义了,则外部被屏蔽),从被定义的地方到程序块结束都可见,不会因为存储类别而有异议(static只改变生命周期,不改变可见性)。
变量的生存周期
按照生存周期,变量可以分为
静态存储
-静态局部变量(程序块内有效)(static)
-静态外部变量(本文件内有效)(定义在全局)
-外部变量(用 extern 声明后,其他文件也可以引用)(extern)
动态存储
-自动变量(程序块内有效)(缺省或者auto)
-寄存器变量(程序块内有效)(register(不过编译器会优化,现在很少自己定义))
-形式参数(程序块内有效)
数组名&指针:
我们都知道一维数组的时候,数组名字指代数组第一个元素的地址,类似于一个指针。
比如,定义int a[10]; 我们就知道 a==&a[0]; *(a+i)==a[i]; a类似于一个指向int的指针变量,a+1在地址上实际是a+1*sizeof(int)。
同理,定义完int a[10][10]; 我们就知道 a==&a[0]; a[0]==&a[0][0].
a[0]类似于一个指向int的指针变量,a[0]+1在地址上实际是a[0]+1*sizeof(int)。
a类似于一个指向"整个"int[10]的指针变量,a+1在地址上实际是a+1*10*sizeof(int)。
这里不容易理解的地方在于,a[i]在数学上是存在且有数字的,他的值就是:&a[i][0],同时也是:*(a+i);但是在物理上却是不存在的。
*(a+i)的实际意义,其实不是“指针变量a[i]”,而是以a[i]起头的一维数组“a[i][0]...a[i][9]”的首地址。
这是由“数组的定义”定义的,所以说a类似于一个指向指针的指针,但是实际上并不是,它是一个数组的一部分,就是数组的首地址。不要完全按照指针去理解。
当然,指向指针的指针也可以定义动态二维数组。
int** a;
a=new int*[n];
for(int i=;i<n;i++)
a[i]=new int[m];
这里的每个*(a+i)就是有物理存储的了。和静态数组的区别在于:
1,多了n个变量来存放二级指针。(缺点)
2,可以不连续存储。(优点)
分支结构:
?表达式(条件运算符)
int a,b;
scanf("%d%d",&a,&b);
printf("%d\n",a>b?1:0);
//这个程序是输入两个整数,如果第一个数字大于第二个则输出1,否则输出0
//C语言里唯一的三目运算符(+-*/都是二目)
//a?b:c //这个表达式的意思是,如果a是真(也就是说如果a非零),这个表达式的值为b,否则为c
c=(a>b?a:b);//这句话等价于max函数
if语句
嵌套的if语句里面的else的匹配要小心,与它上面的同一个程序块的离它最近的if匹配。
switch语句
char num=0;
scanf("%c",&num);switch(num){
case 1:p("wuhao");break;
default :p("error");
case 2:p("xujunwu");
case 3:p("xuwangzihao");break;
case 4:p("xuzhenghao");
}//switch后面跟的变量必须是整数,意味着可以是整型或者字符型。
//任意两个case后面的值不能相同,否则编译出错。
//各个case和default只是入口,他们在逻辑上不分先后,一旦哪个入口被确定了代码就从那个冒号开始执行语句,直到switch语句的结束(遇到后大括号或者break)
//这段代码写的很“不标准”,理解用,可以运行一下看看。(标准的做法是,除了最后一个入口,其余入口做完自己该做的事后都应该加上break,这段代码在default和case 2后面缺失break)
循环结构:
逻辑表达式都是有值的,1(真/true)或者0(假/false)。
自增/自减运算符
a++;//意思是a=a+1;表达式返回值是之前的a的值
++a;//意思是a=a+1;表达式返回值是a+1之后的值
a--;//意思是a=a-1;表达式返回值是之前的a的值
--a;//意思是a=a-1;表达式返回值是a-1之后的值
int a=0;
if(a++)printf("a++ %d\n",a);
a=0;
if(++a)printf("++a %d\n",a);
//运行一下观察结果。(if语句括住的表达式值为1的时候才能继续执行,否则执行else(没有else则忽视))
while和do_while语句
int n;
scanf("%d",&n);
while(n--){
printf("*");
}
printf("\n");
//----------------------------------------------------------------
int n;
scanf("%d",&n);
do{
printf("*");
}while(--n);printf("\n");
//这两段代码执行的操作都是输入n,输出一行n个'*'。在n>0的时候完全相同,但是n<1的时候,dowhile会输出一个,while不会输出。
//两者的区别在于先判断再执行还是先执行后判断。
//dowhile语句有个特点就是不论初始什么情况,循环体内部的命令总是有机会被执行一次。
//dowhile语句结束的时候有个分号别忘了。。。。
break&continue语句
int a;
do{
scanf("%d",&a);
printf("%d\n",a);
}while(1);
while(1){
scanf("%d",&a);
printf("%d\n",a);
}
//这两段循环都是无限循环,因为负责判断的表达式是个常量1,永远为真。
while(1){
scanf("%d",&a);
printf("%d\n",a);
if(a==0)break;
}
//break语句跳出当前循环,继续顺序执行。当我们输入0的时候,循环结束。
while(1){
scanf("%d",&a);
if(a%2)continue;
printf("%d\n",a);
if(a==0)break;
}
//continue语句跳出当前这次循环的末尾,继续执行下一次循环。当我们输入奇数的时候,不输出。
for语句
for(a;b;c){
work();
}
//*********************
a;
while(b){
work();
c;
}
//以上两段代码功能完全一样。下面举个例子。
int n=10,i,a[11];
i=1;
while(i<=n){
scanf("%d",&a[i]);
i++;
}
//******************
int n=10,i,a[11];
for(i=1;i<=n;i++){
scanf("%d",&a[i]);
}
//以上两个代码都是输入10个数字存在数组a里。
for(;;){
work();
}
//for语句三个表达式可以缺省。上面是一个无限循环。
指针:
int * p; //指向int的指针
int * p[4]; //指针数组,4个指向int数据的指针
int (*p)[4]; //指向int数组的指针
int * p(); //返回“指向一个int数据的指针”的函数
int (*p)(); //指向函数的指针,返回值为int
int **p; //指向“指向int数据的指针”的指针
void *p; //指向不确定数据类型的数据的指针(类型由计算机自动转换)
一个翻译C语言成人话的网站:https://cdecl.org/
看到一个巨无敌的读变量声明的方法叫做“右左震荡法”
(来源:http://ieng9.ucsd.edu/~cs30x/rt_lt.rule.html)
就是说:
0,见到如下符号就进行替换
- "[]" == "一个数组,他的每个元素是"
- "()" == "一个函数,它的返回值是"
- "*" == "一个指针,指向"
1,找到变量;
2,往右看,直到表达式结束或者遇到一个右括号。
3,往左看,直到表达式开头或者遇到一个左括号。
重复23,直到全部扫完。
举个例子:
examples: int *p[]; 1) 找到变量. int *p[];
^
"p 是" 2) 往右看,直到表达式结束或者遇到一个右括号。
int *p[];
^^
"p 是一个数组,他的元素是" 3) 不能再往右走了 (表达式结束), 开始左移:
int *p[];
^
"p 是一个数组,他的每个元素是一个指针,指向" 4) 继续左移:
int *p[];
^^^
"p 是一个数组,他的每个元素是一个指针,指向int".
(or "p is an array where each element is of type pointer to int") Another example: int *(*func())(); 1) Find the identifier. int *(*func())();
^^^^
"func 是" 2) Move right. int *(*func())();
^^
"func 是一个函数,返回值是" 3) 不能再右移了因为遇到了右括号,所以开始左移.
int *(*func())();
^
"func 是一个函数,返回值是一个指针,指向" 4) 不能再左移因为遇到左括号, 继续右移
. int *(*func())();
^^
"func 是一个函数,返回值是一个指针,指向一个函数,返回值是" 5) Can't move right anymore because we're out of symbols, so go left.
int *(*func())();
^
"func 是一个函数,返回值是一个指针,指向一个函数,返回值是一个指针,指向" 6) And finally, keep going left, because there's nothing left on the right.
int *(*func())();
^^^
"func 是一个函数,返回值是一个指针,指向一个函数,返回值是一个指针,指向int".
动态申请回收资源:
void * mallac(unsigned int size);
void * calloc(unsigned n,unsigned size);
void free(void * p); //p cames from the last calloc or mallac function.
void * realloc(void * p,unsigned int size); //resize
指针函数:
double Sum(double *arr,double n){
//函数主体
work();
}
double (*xzh)(double *,double);//声明函数指针。
xzh=Sum; //指针赋值。
sum=(*xzh)(a,10); //用函数指针调用函数。
自定义数据结构
struct结构体
struct pupil{
char name[10];
double yu;
double shu;
double wai;
};//结构体定义struct pupil sa[20]; //注意在C语言里,使用自定义数据类型的时候,struct前缀不能省略。(和C++区别)
struct pupil sum={" ",0,0,0};//顺序初始化成员(类似数组)
struct pupil sum={.name="aaa"};//允许单独初始化某个成员
for(i=1;i<=10;i++){
scanf("%lf%lf%lf",&sa[i].yu,&sa[i].shu,&sa[i].wai); //'.'是成员运算符
}
结构体指针
struct pupil PupilSum(struct pupil * arr , int n){//arr是一个指向“自定义数据类型pupil”的指针
struct pupil sum={" ",0,0,0};
//struct pupil sum={.name="aaa"};//允许单独初始化某个成员
int i;
for(i=1;i<n;i++){sum.yu+=(arr+i+1)->yu;//"->"是指向运算符,在调用指针指向的结构体内部成员的时候使用
sum.yu+=(*(arr+i+1)).yu;//由于运算符优先级的问题,这里的括号一个都不能省。。。。
//(这种写法和上一行效果一样,使用的时候二选一)
}
};
union共同体/联合体
union Data{
//联合体中所有数据公用一段存储空间,所以一个联合体元素的大小,等于其中占用空间最大的成员占用的空间,比如这个联合体 i 四个字节,c 一个字节,f 八个字节,所以每个该联合体数据占用空间就是八字节。一个联合体数据一次只能存储一个成员的信息。
int i;
char c;
double f;
}a={16},b={.c='a'};//可以对第一个元素赋值,或者对特定的一个元素赋值
union Data c={16,'h',1.0};//这种写法是错误的。
enum枚举类型
enum Weekday{sun,mon,tue,wed,thu,fri,sat};
//枚举类型如果使用默认的初值,就是{0...n-1}
enum Weekday workday,weekend=sat;
//---------------------------------------------------------------------------------------
enum Weekday{sun=3,mon=2,tue,wed=2,thu,fri,sat};
//枚举类型可以手动赋初值,可以重复,没有赋初值的元素的值,等于他上一个元素的值加一(首元素默认为0)
//比如现在他们的值是{3,2,3,2,3,4,5}
//枚举类型不能再次赋值(比如mon=4就是错的)
//枚举类型的变量可以赋值,可以相互比较(因为实质还是整数)
typedef声明新类型名
typedef int Grade;
Grade a; //这里的Grade等价于int
//--------------------------------------------------------------------------------------------------------------
typedef int DATA[10],*IP; //声明一个新的数据类型DATE,每个DATE类型的元素是长度为10的int数组。
//声明一个新的数据类型IP,每一个IP类型的元素是一个指向int类型数据的指针
DATA a[8]; //a是一个二维数组,这句话等价于int a[8][10];IP p; //p是一个指向int的指针,这句话等价于int *p;
//--------------------------------------------------------------------------------------------------------------
typedef struct Node{
int v;
int lc, rc;
}ND,*NP;NP root=NULL; //root是一个指向"struct Node"的指针
ND e[1000]; //e是一个数组,每个元素都是"struct Node"类型的。
sizeof函数,返回变量或者数据类型的大小(字节为单位)
typedef struct Node{
int v;
int lc, rc;
}ND,*NP;NP root=NULL;
ND e[1000];printf("%d %d\n",sizeof(NP),sizeof(root));//这里输出的是4 4
//NP是一种数据类型,指向struct Node的指针,指针的大小由操作系统决定,32位下是4字节。root是NP类型的变量。
printf("%d %d %d\n",sizeof(ND),sizeof(e[0]),sizeof(e));//这里输出的是12 12 12000//ND是struct Node,每个ND包含三个int,每个int是4字节,所以每个ND类型的变量是12字节。
//e[0]是一个ND类型的变量,e是包含了1000个ND类型变量的数组
字节对齐(百度面试遇到的.....)
接下来的文字,大量转载自:http://blog.csdn.net/hairetz/article/details/4084088
写出一个struct,然后sizeof,你会发现sizeof的结果往往都比你声明的变量总长度要大。这涉及到字节对齐的问题,对齐规则如下。
1:数据成员对齐规则:结构(struct)(或联合(union))的数据成员,第一个数据成员放在offset为0的地方,以后每个数据成员存储的起始位置要从该成员大小或者成员的子成员大小(只要该成员有子成员,比如说是数组,结构体等)的整数倍开始(比如int在32位机为4字节,则要从4的整数倍地址开始存储。
2:结构体作为成员:如果一个结构里有某些结构体成员,则结构体成员要从其内部最大元素大小的整数倍地址开始存储.(struct a里存有struct b,b里有char,int ,double等元素,那b应该从8的整数倍开始存储.)
3:收尾工作:结构体的总大小,也就是sizeof的结果,.必须是其内部最大成员的整数倍.不足的要补齐.
如果在程序的头部加一句#pragma pack(1),情况会有所不同,它告诉编译器,所有的对齐都按照1的整数倍对齐,换句话说就是没有对齐规则.
ps:Vc,Vs等编译器默认是#pragma pack(8),所以测试我们的规则会正常;注意gcc默认是#pragma pack(4),并且gcc只支持1,2,4对齐。套用三原则里计算的对齐值是不能大于#pragma pack指定的n值。
举个例子:
{char;char;short;int;short;} sizeof 应该等于12{char;short;char;int;short;} sizeof 应该等于16//int是4,short是2,char是1
文件操作
文件顺序读写
FILE *fp; //文件指针,FILE类型在头文件stdio.h里
fp=fopen("add.in","r"); //指针赋值,指向目标文件,并说明使用文件方式。
//第一个参数是路径,可以是绝对路径也可以是相对路径。
//第二个是文件使用方式,主要有三种,r读,w写,a追加
//r 时如果文件不存在会返回NULL,w 时文件存在会删除文件再新建(小心数据丢失)
//此外还有 "r+" "w+" "a+" 三种方式,分别是读写,写读,追加读,有的编译器不支持,所以不推荐用
FILE *ofp;
ofp=fopen("add.out","w");
fsanf(fp,"%d",&a);
fprintf(ofp,"%d\n",&a);
c=fgetc(fp);
fputc(c,ofp);
fgets(s,n,fp);
fputs(s,ofp);
fclose(fp);//关闭文件,清除缓冲区,解放指针
fclose(ofp);
以二进制方式读写文件
struct {
...
}a[20];//这是一个匿名结构体
FILE *ifp,*ofp;
ifp=fopen("add.in","r");
ofp=fopen("add.out","w");
fread(a,sizeof(a[0]),20,ifp);//直接把文件存储的二进制数据映射到地址{a...a+20*sizeof(a[0])};
fwrite(a,sizeof(a[0]),20,ofp);//直接把内存中的二进制数据原封不动的存入文件。
随机读写数据文件(常用于二进制文件的读写)
FILE *ifp;
char s[512];
ifp=fopen("add.in","r");
s=fgets(s,512,ifp);
rewind(ifp);//让位置标记重新指向0L
fseek(ifp,100L,0);//模式0,位置标记指向文件开头100字节处。
fseek(ifp,50L,1);//模式1,位置标记指向当前位置+50字节处。
fseek(ifp,-10L,2);//模式2,位置标记指向文件末尾-10字节处。
int i=ftell(fp);//返回当前位置标记所在位置,如果函数出错,返回-1L
C语言相关的更多相关文章
- 【个人笔记】002-PHP基础-01-PHP快速入门-02-PHP语言相关介绍输
002-PHP基础-01-PHP快速入门 02-PHP语言相关介绍 1.PHP是什么 Hypertext Preprocessor超文本预处理器 是一种通用开源脚本语言 Personal Home P ...
- Django模板语言相关内容 Djan
Django模板语言相关内容 Django模板系统 官方文档 常用语法 只需要记两种特殊符号: {{ }}和 {% %} 变量相关的用{{}},逻辑相关的用{%%}. 变量 {{ 变量名 }} ...
- 牛客网_Go语言相关练习_选择题(1)
声明:题目源自牛客网. 一.单项选择题 解析:作为形参时,可以要求单向,只读或只写. 解析:Go语言的内存回收机制规定,只要有一个指针指向引用一个变量,那么这个变量就不会被释放(内存逃逸),因此在Go ...
- Django——模板语言相关内容
Django模板语言相关内容 Django模板系统 官方文档 常用语法 只需要记两种特殊符号: {{ }}和 {% %} 变量相关的用{{}},逻辑相关的用{%%}. 变量 {{ 变量名 }} ...
- 6月15日 python学习总结 Django模板语言相关内容
Django模板语言相关内容 Django模板系统 官方文档 常用语法 只需要记两种特殊符号: {{ }}和 {% %} 变量相关的用{{}},逻辑相关的用{%%}. 变量 {{ 变量名 }} ...
- C语言相关的经典书籍(附Ebook)
个人稍微分了一下类,有的看过,有的听人“传说过”,欢迎大家补充和共同学习. 真心经典:每个行业或者领域都有一些东西是不会随时间而逐渐消逝,以下的就是. <C语言程序设计>(第2版.新版) ...
- Django模板语言相关内容
Django模板系统 官方文档 常用语法 只需要记两种特殊符号: {{ }}和 {% %} 变量相关的用{{}},逻辑相关的用{%%}. 变量 在Django的模板语言中按此语法使用:{{ 变量名 ...
- 牛客网_Go语言相关练习_判断&选择题(6)
本文共34道题目 一.判断题 此题考查编码规范. 反射最常见的使用场景是做对象的序列化(serialization,有时候也叫Marshal & Unmarshal). 例如:Go语言标准库的 ...
- 【工具向01】——markdown 文本编辑语言相关
markdown简介 Markdown是一种轻量级标记语言创始人为约翰·格鲁伯.它允许人们"使用易读易写的纯文本格式编写文档,然后转换成有效的XHTML或HTML文档".这种语言吸 ...
- C语言相关知识
1.指针:在程序中定义了一个变量,在进行编译时就会给该变量再内存中分配一个地址,通过访问这个地址可以找到所需变量,这个变量的地址成为该变量的指针.指针看作是内存中的一个地址,多数情况下,这个地址是内存 ...
随机推荐
- CSS——text-indent
在h1标签里套入a标签并写上文字,有利于seo,但是文字如何隐藏呢?一般都是a标签变成内联块并首行缩进为负值. <!DOCTYPE html> <html lang="en ...
- SSL&TLS传输层加密协议实现图解--(重要)
一.SSL&TLS 1.SSL:Secure Sockets Layer ,加密套接字协议层 1)SSL是为网络通信提供安全及数据完整性的一种安全协议,在传输层对网络连接进行加密 Secure ...
- Origin C调用GSL
GSL (GNU Scientific Library, http://www.gnu.org/software/gsl/)是C.C++的数值算法库,提供了范围宽广的数学程序,包括随机数字生成器.数理 ...
- js 图表转图片
最近项目上有个需求,是将一些teechart做的图表转换成图片插入自动生成的PDF里,Teechart绘图和如何生成PDF这些这里就不说了,这个任务比较别扭的一点是,图表自动生成,且整个过程中页面不能 ...
- / Vijos / 题库 /1250 / 最勇敢的机器人
/ Vijos / 题库 /1250 / 最勇敢的机器人 借鉴博客:http://www.cnblogs.com/chty/p/5830516.html 背景 Wind设计了很多机器人.但是它们都认为 ...
- 使用final关键字修饰一个引用类型变量时,是引用不能变,还是引用的对象不能变?
使用final关键字修饰一个引用类型变量时,是指引用变量不能变,引用变量所指向的对象中的内容还是可以改变的. 测试代码如下: package reviewTest; /** * @ClassName: ...
- 9.3.4 BeaufitulSoup4
BeautifulSoup 是一个非常优秀的Python扩展库,可以用来从HTML或XML文件中提取我们感兴趣的数据,并且允许指定使用不同的解析器. 使用 pip install BeaufifulS ...
- NetworkManager
网络管理器(NetworManager)是检测网络.自动连接网络的程序.无论是无线还是有线连接,它都可以令您轻松管理.对于无线网络,网络管理器优先连接已知的网络并可以自动切换到最可靠的无线网络.利用网 ...
- noip模拟赛 radius
分析:这道题实在是不好想,一个可以骗分的想法是假定要求的那个点在中心点上,可以骗得不少分.但是在边上的点要怎么确定呢?理论复杂度O(﹢无穷).答案一定是和端点有关的,涉及到最大值最小,考虑二分最大值, ...
- 学习笔记——TCP“三次握手”和“四次挥手”,简单介绍
TCP/IP协议中,TCP协议提供可靠的连接服务,采用“三次握手”建立一个连接. (1)第一次握手:客户端发送SYN包(SYN=j)到服务器,并进入SYN_SEND状态,等待服务器确认. (2)第二次 ...