c1
C for Windows
基础篇
intro to c
编译机制
windows:源文件.c——<编译>——目标文件.obj——<链接>——可执行文件.exe
unix:.c > .o > .out
include "head.h" 双引号表示头文件位于该目录下
基本数据类型
- 基本类型
int float char 枚举类型
- 构造类型
数组类型 结构体类型 联合体类型
- 指针类型
- 空类型
变量与常量,注意区分
int
int 2byte; long int 4byte(1字节=8字)
进制:0开头:八进制;0x:十六进制
定义:(unsigned) int/short int/long int a;
float
float 4
double 8
long double 16
char
字符用单引号,字符串用双引号
一个字符占一个字节,以ASCII码存储
字符数据与整型数据通用
转义字符
\n 换行
\t 制表
\r 回车
\a 响铃
\?,\',\"
\0 空字符,表示字符串的结束
\ddd 八进制数表示的字符
\0xhh 二位十六进制数表示字符
关键字(32)
default do double else enum extern float for goto
if int long register return short signed sizeof static
struct switch typedef union unsigned void volatile while
字符处理库: ctype.h
常量
常量名一般大写
#define <name> <value> 不需要说明常量类型
const <typename> <name>=<value>
运算符与表达式
算术:+,-,*, /, %(求余),++, --
a++ 返回a再自增
++a自增再返回
关系:==, <=,>=,!=
赋值:=,+=,-=,/=,%=,&=, |=, ^=, >>=, <<=
逻辑:&&与; ||或; !非
类型转换
自动类型转换:混合表达式,自动提升规则
强制类型转换:x=9.5; int(x)值为9,而不改变x值
赋值表达式中的类型转换:int a;a=7.6, 则a为7
输入输出
字符数据输入输出
#include<stdio.h> /*标准输入输出流*/
ch=getchar() /*无参数,多用于调试过程暂停程序*/
putchar('\n')
printf
格式化输出
普通字符 printf("please input a char\n")
格式化 printf("%d,%d",a,b)
%d,%o,%x, 10进制,8进制,16进制
%f float;%c char; %s string
%p 地址
整型输出
%d %ld %md %mld
浮点型输出
%f %m.nf %-m.nf(align to left)
%e %-m.ne
字符串
%s %-ms(align to left add empyt)
%-m.ns 输出前n个字符
% p 输出地址
%%
输出%
scanf
格式化输入
scanf(“%d\n”,&a) 格式一致
- 不能规定输入数据的精度
- 使用*忽略对应的数据(%*d)
gets&puts
#include<stdio.h> /*standard input&output*/
void main()
{
char str[100];
printf("please input your words:");
gets(str);
printf("what you input is:");
puts(str);
}
结构化设计
选择结构
break 跳出循环;continue跳出当下循环
/*if-else*/
if(states)
states;
else if()
states;
else
states
/*switch*/
switch(states)
{
case states:
states;
break;
case states:
states;
break;
default:
states; /*如果为其他值*/
}
/*条件运算符*/
statement1?state2:state3 /*if 1 is true use 2 else 3*/
循环结构
/*while*/
while(states)
states;
/*do-while*/
do
states;
while();
/*for*/
for(state1;state2;state3)
states;
/*state1,varify with state2, then state3 to return state2 ...*/
/*goto*/
loop:
{
states;
goto loop; //跳转到语句标号loop/类似汇编
}
数组
一维数组
类型说明符 数组名 [常量表达式]
数组长度必须在定义时指定
初始化
int a[]={1,2,3,4,5} //等价于
int a[5]={1,2,3,4,5}
int a[5]={1,2,3} //其余元素赋值为0
二维数组
int a[3][4]={{1,2,3,4},[23,4,5,6],{4,5,6,7}} //可以省略第二层花括号
字符数组
char []
未分配字符则以‘\0’补充
变长数组
//vla
//函数参量声明
int sum(int rows,int cols,int ar[rows][cols]);
int sum(int,int,int[*][*]);
//函数内部
int quarters=4;
int regions=5;
double sales[regions][quarters];
/*
变长数组必须是自动存储类,必须再函数内部或作为函数参量声明,而且省明时不可以进行初始化。
*/
函数
函数传递的是数值,而不是地址
定义
类型说明符 函数名(参数列表)
若省略函数类型,默认为int
参数类型可以另起一行声明
float add(x,y)
float x,float y;
{}
返回值:可以有多个返回值,执行到哪个算哪个
函数原型:若函数定义在main()函数之后,则要在使用前声明。
参数
数组元素作为函数参数传递的是元素值
数组名则是将首地址传入
数组名作为参数定义:int max(int a[])
多位数组:
int a[3][4]
;
int a[][4]
函数原型声明可以省略参数名,定义函数不可以省略
变量的存储类别
静态变量:
static: 固定存储单元,只赋值一次
extern: 外部变量
动态变量:
auto 自动变量
register 寄存器变量,减少读取时间
函数的作用域
static 定义内部函数,只能被本文件引用
extern 外部函数(可以省略)
字符串
字符串不作为数据类型,将字符数组当作字符传来使用,结尾以'\0' 标识
整个引号中的内容作为指向该字符串存储位置的指针
初始化
//由编译器决定数组大小
char c[]={"C lnguage"}; //与字符数组的联系
char c[]="C language";
char c[]={'C',' ','l','a','n','g','u','a','g','e','\0'};
//'\0'指明是一个字符串而不是字符数组
//define 分配。必须是整型常量
//指针建立字符串
char *s1="C language";
数组和指针
char *s1="c language";
char s2[]="c language";
//s1是个指针变量,可以自增自减;s2作为指向字符串首字符的指针是个常量
//都可以使用数组取值's1[2]==s2[2]'
//都可以使用指针加法:'*(s1+2)==*(s2+2)'
字符串数组和指针
char *s1[2]={"yee","che"};
char s2[2][5]={"yee","che"};//二维数组必须明确指明长度
//s1[0],s1[1]实际上存放各个字符串首字符地址
字符串输入输出
gets()/puts()
- puts(0)自动在输出字符串时添加换行符
char name[81];
char *ptr;
gets(name);//接受一个分配指定大小的地址,以换行符结束
ptr=gets(name);//gets()返回指向字符串的指针;
while(gets(name)!=NULL);//出错或遇到文件结尾则返回空地址NULL
char dont[]={'w','0','w','!'};
puts(dont);//puts遇到空字符则停下,dont没有空字符,所以会输出下面内存中的内容直到遇到空字符
fgets()
- 参数有三个
- 读取前n-1个字符或换行符结束
- 若读到换行符则换行符存入字符串
char name[81];
char *ptr;
ptr=fgets(name,81,stdin);//第三个参数指明读取哪个文件,从键盘输入则使用'stdin'
fputs()
- 第二个参数指明要写的文件,’stdout‘标准输出
- 不自动添加换行符
scanf()
- 字符串以第一个非空白字符开始
- 以指定长度或下一个空白字符结束
- 结束一个数据的输入:空格/回车/tab/
- scanf()的格式控制串可以使用其它非空白字符,但在输入时必须输入这些字符,如逗号
字符串函数
- 函数参数是指针
strlen()
#include<string.h>
//strlen不计算空字符
strcat()/strncat()
strcat(str1,str2); //link str2 to str1
strncat(str1,str2,n);//指定可添加最大长度,或遇空字符结束
int available=Size-strlen(str1)-1;
strcmp()/strncmp()
strcmp(str1,str2);//compare equal-0/less-minus/more-plus
strncmp(str1,str2,n);//比较前n个
strcpy()/strncpy()
strcpy(str1,str2); //copy str2 to str1 返回第一个参数的首地址
strncpy(str1,str2,n);//把前n个或直到遇到空字符
sprintf
- 写到字符串而不是输出显示
//字符串的整体输入输出
char a[40];
scanf("%s",a); /*空格或回车结束,没有&标识符*/
printf("%s",a);
//
gets()/puts(); //若输入字符串包括空格,则用gets()
//
#include<string.h>
strlen(); //不包括 ‘\0’
strcpy(str1,str2); //copy str2 to str1
strcmp(str1,str2);//compare equal-0/less-minus/more-plus
strcat(str1,str2); //link str2 to str1
strlwr(str); //lower letter
strupr(str); //higher letter
指针
定义与引用
&:取地址运算符
*:指针运算符
地址:变量名被翻译成地址,通过&a标识地址
指针:int *Ptr定义指针,Ptr=&a赋值,*Ptr取指针变量所代表的地址中的值
Attention
- 指针作为参数,不能修改其本身的值,但可以修改地址存放的值,因为地址是不变的。
- 定义指针要指明数据类型,以便确定地址存储空间的计算
- 不能对未初始化的指针赋值/取值
合法操作
- 赋值(把一个地址赋值指针)
- 取值(不能对未初始化的指针取值取值)
- 取地址(指针本身的存储地址)
- 自增/自减
- 整数加减
- 同类型指针求差(比如指向同一数组不同元素的两指针,万万不可求和)
- 比较
错误语法分析
int ar[]={1,2,3,4};
ar++; //数组名类型同指针,但不是可变量,故其地址不可自增,而其地址指向的值可以改变
指针与数组
指向数组的指针变量
//定义
p=a; //数组名表示第一个元素的地址,普通变量名没有这一特性
p=&a[0]; //第一个元素
//引用
a[1];
p[1];
*(p+1) //指针的算术运算是地址的运算 *p++=*(p++)
二维数组
//指向多维数组的指针
int (*p) [2]; //定义p指向一个包含2个interesting值的数组
int p[][2]; //仅在形式参量时可以
**p=*p[0]=p[0][0];//取值
描述 | 含义 |
---|---|
&a[0][0], a[0] ,*a *(a+0) | 第一行首地址 |
&a[1][0] a+1, a[1] *(a+1) | 第二行首地址 |
&a[2][1] *(a+2)+1 a[2]+1 | 第三行第二列地址 |
a[2][1] *(*(a+2)+1) *(a[2]+1) | 第三行第二列的值 |
a | 二维数组名,首地址 |
行指针变量
指针数组
int *p[5];
int* p[5];
//二级指针
int **p;
指针与字符串
//字符指针指向字符串
char *str="a long string"; //与字符数组等价
//字符指针数组
char *p[]={"SJTU","how","hi"};
printf("print%s\n", p[0]); //tell me what was going on
//字符数组,打印首地址即可打印整个字符串
指针与函数
//保护数组内容
int sum(int a[]); //参数为数组名,即指针,则通过地址的方式易改变数组的值
int sum(const int a[]);//若设计意图不改变数组,则使用关键字const
/*
并不要求数组不变,只是告知函数在处理数组时应把它当作常量来对待
*/
//指向函数的指针
int (*p)(int,int);
p=add; //指针变量指向函数入口
(*p)(a,b);//指针调用
int sum(int a[]);
int sum(int *a)
/*
无论在任何情况下,int *ar表示ar是指向int的指针, int ar[]也可以表示ar是指向int的指针,但只在声明形式参量(函数声明和函数原型)时才可以这样用
*/
指针与常量
const int *p=&a;//指向常量的指针,不能通过p改变数据,a不需要为常量
//通常能够用来作为函数参数,以表明不会用这个指针修改数据
//但普通指针不可以指向常量,否则便可以通过指针来修改数据
int *const p=&a;// 指针常量,不可再指向其它地址
const int *const p=&a; // 常量指针常量,指向常量的常量指针,不可修改地址/数据
结构体
定义
struct <struct_name>
{
<members>;
};
//struct <struct_name> 构成结构体类型
//定义结构体变量
struct teacher teacher1,teacher2;
//引用
teacher1.name;
//初始化
struct teacher teacher1={1001,'hi',45};
teacher.name="halo";
strcpy(stu.name,"wang") //字符数组不可以直接赋值
结构体数组
struct student stu[3]={{},{},{}};
指针与结构体
指针指向结构体变量
struct student *p;
p=&stu1;
指针指向结构体数组
p=stu;
(*p).name;
typedef自定义类型名
typedef int BIG;
typedef struct date Date; //结构体类型名更加精炼
typedef int NUM[20]; //NUM a=int a[20];
typedef int(*POINTER)(int int);
联合体
枚举类
enum weekday{sun,mon,tue,wed,thu,fri,sat}; //定义
enum weekday w1,w2;//变量
符号常量,取值0-7,当然可以在定义时指定,之后不可更改
w1,w2,只能取其中一个值
可以将整数值直接赋给枚举变量
命令行参数
int main(int argc,char *argv[]){
int count = 0;
printf("the command line has:%d arguments\n", argc-1);
for (count = 0; count < argc; count++) {
printf("%d: %s\n", count, argv[count]);
}
}