单位换算
1KB=210B=1024B
1MB=210KB=1024KB
1GB=210MB=1024MB
内存地址
以2GB内存地址为例,2GB=231B,计算机就为这231个存储单元(字节)的位置编码:
#include<stdio.h>
int main(void){
int a,b,c;
printf("%p,%p,%p\n",&a,&b,&c);
int d[3];
d[0]=1,d[1]=2,d[2]=3;
printf("%d,%d,%d\n",d[0],d[1],d[2]);
printf("%p,%p,%p\n",&d[0],&d[1],&d[2]);
return 0;
}
一维数组
定义数组及初始化
#include<stdio.h>
int main(void){
//1.定义数组
//int a[2*2];
/*
int b = 2;
int c[2*b]; //error
*/
const int b=2; //常变量
int c[2*b];
//int e[3.1]; //error
int e[(int)3.1];
int f['A'];
int g[true];
//2.定义并初始化数组
/* 完全初始化
//int a[4]={1,2,3,4};
int a[]={1,2,3,4};
*/
int a[4]={1}; //在不完全初始化中,元素如果未被初始化将会有一个默认值0
for(int i=0;i<4;++i)
printf("%d\n",a[i]);
return 0;
}
数组的排序
#include<stdio.h>
int main(void){
int a[5] = {89,34,-56,1,23};
int len = 5;
/* //冒泡排序
for(int i=0;i<len-1;++i){
for(int j=1;j<len-i;++j){
if(a[i]>a[i+j]){
int temp=a[i];
a[i]=a[i+j];
a[i+j]=temp;
}
}
}
*/
//选择排序
for(int j=0;j<len-1;++j){
int c=0;
for(int i=1;i<len-j;++i){
if(a[c]<a[i])
c=i;
}
int b=a[c];
a[c]=a[len-1-j];
a[len-1-j]=b;
}
for(int k=0;k<len;++k)
printf("%d,",a[k]);
putchar('\n');
return 0;
}
指针
#include<stdio.h>
void f1(int b){
b=10;
}
void f2(int *c){
*c=10;
}
int main(void){
int *p; //p时int *类型的,用来存放int型变量的地址 读作:定义了一个指向 int的指针变量 p
int a=2;
p=&a; //p指向 a
*p=3; //*p等价于 a
f1(a); //printf输出3
f2(&a); //printf输出10 通过函数改变main函数当中的某一个变量,就需要对这个变量取地址
printf("%d\n",a);
int d[3]; //数组名 d是一个int *类型的常量,其值为d[0]的地址
p=d;
p[0]=1;
p[1]=2;
p[2]=3;
//printf("%d,%d,%d\n",d[-1]=1,d[3]=1;d[4]=1); //error 数组下标越界
*p=10;
*(p+1)=20; //*(d+1)=20
*(p+2)=30; //*(p+2) ->p[2] *(p+2)和*(2+p)等价 2[p]
0[p]=100;
1[p]=200;
2[p]=300;
//d = &a; //error 因为 d是一个常量
printf("%p,%p,%p\n",p,p+1,p+2); // p + n 实际上是 p + sizeof(*p)*n
for(int i=0;i<3;++i)
printf("%5d",d[i]);
return 0;
}
数组的增删改查及倒置
#include<stdio.h>
#define LEN 10
//有效数个数
int length(int *a){ //参数还可以写成 int a[LEN] 或者 int a[] 都代表a是一个int * 类型的变量
int j = 0;
while(j<LEN){
if(a[j] == 0)
break;
else
++j;
}
return j;
}
void show(int a[]){
int len=length(a);
for(int i=0;i<len;++i)
printf("%5d",a[i]);
putchar('\n');
}
//删
bool del(int *a,int index){
int len = length(a);
if(len==0 || index>len-1 || index<0)
return false;
else{
for(int i=index+1;i<len;++i)
a[i-1]=a[i];
a[len-1]=0;
return true;
}
}
//增
bool insert(int *a,int index,int value){
int len=length(a);
if(len==LEN ||index<0 || index>len)
return false;
else{
for(int i=len-1;i>=index;--i)
a[i+1]=a[i];
a[index]=value;
return true;
}
}
//倒置
void invert(int *a){
int len=length(a);
/*
int from = 0;
int end = len-1;
while(from<end){
int d = a[from];
a[from] = a[end];
a[end]=d;
from++;
end--;
}*/
for(int from=0,end=len-1;from<end;from++,end--){
int d = a[from];
a[from] = a[end];
a[end]=d;
}
}
//查
int find1(int *a,int value){
int len=length(a);
for(int i=0;i<len;++i){
if(a[i]==value)
return i;
}
return -1;
}
//二分查找
int find2(int *a,int value){
int len=length(a);
int from = 0;
int end = len-1;
while(from<=end){
if(value==a[(from+end)/2])
return (from+end)/2;
else if(value > a[(from+end)/2])
from = (from+end)/2+1;
else
end = (from+end)/2-1;
}
return -1;
}
int main(void){
int a[LEN]={3,6,9,12,15};
/*if(del(a,5))
show(a);
else
printf("删除失败\n");
*/
//insert(a,2,8);
//invert(a);
//printf("%d\n",find1(a,12)); //3
//printf("%d\n",find1(a,7)); //-1
printf("%d\n",find2(a,15)); //4
printf("%d\n",find2(a,7)); //-1
show(a);
//printf("有效元素的个数为:%d\n",length(a));
//show(a);
return 0;
}
二维数组
二维数组的定义及初始化
1.二维数组定义的一般形式:
类型说明符 数组名 [常量表达式][常量表达式]
2.二维数组在内存中的存储方式
例如:int a[2][3]; 这里定义了一个2行3列的数组,我们可以把它看成一个表格:
但实际内存是线性的,(假设此二维数组从第1000个字节处开始存放)所以实际储存方式如下::
#include<stdio.h>
int main(void){
//1.完全初始化
//int a[3][4]={1,2,3,4,5,6,7,8,9,10,11,12};
/*int a[3][4]={
{1,2,3,4},
{5,6,7,8},
{9,10,11,12}
};
*/
//2.不完全初始化
//int a[3][4] = {1}; //1,0,0,0,0,0,0,0,0,0,0,0
//int a[3][4]={{1,2,3,4},{},{9,10,11,12}}; //只适合部分编译器
//int a[3][4] = {{1},{2,3},{4}}; //1,0,0,0,2,3,0,0,4,0,0,0
//int a[3][4] = {{1},{2,3}}; //1,0,0,0,2,3,0,0,0,0,0,0
int a[][4]={1,2,3,4,5,6,7,8,9,10,11}; //1,2,3,4,5,6,7,8,9,10,11,0
/* 输出方式1
for(int i=0;i<3;++i)
for(int j=0;j<4;++j)
printf("%d\n",a[i][j]);
*/
//输出方式2
for(int i=0;i<12;++i)
printf("%d\n",a[i/4][i%4]);
return 0;
}
通过指针引用多维数组
&a[1]:1012
a[1]+2:1020
*(a+0)+1:1004
&a[1][1]:1016
*( *(a+1)+2):6
求二维数组的鞍点
鞍点:某行最大值+某列最小值
#include<stdio.h>
#define M 5
#define N 6
bool f(int (*a)[N],int i,int j){
for(int x=0;x<N;++x){
if(a[x][j]<a[i][j])
return false;
}
return true;
}
void show(int a[M][N]){ //int a[][N] 或者 int(*a)[N] 都是定义了一个指向含有N个整型元素的数组的指针
for(int i=0;i<M;++i){
for(int j=0;j<N;++j){
printf("%5d",a[i][j]);
}
putchar('\n');
}
}
int main(void){
int a[M][N];
for(int i=0;i<M*N;++i)
a[i/N][i%N] = i;
show(a);
for(int i=0;i<N;++i){
int k = 0;
for(int j=1;j<N;++j){
if(a[i][k]<a[i][j])
k=j;
}
if(f(a,i,k))
printf("a[%d][%d]是这个二维数组的鞍点\n",i,k);
}
return 0;
}
字符数组
#include<stdio.h>
int main(void){
char a[10]={'h','a',' ','h','a','\n'}; //'\0'空字符 是C语言中字符串结束的标志
printf("haha\0hehe"); //输出haha
printf("%s","ABCD"); //字符串常量末尾都有一个空字符
printf("%s",a);
//字符型数组定义时初始化所有特有的形式
char b[10] = {"ha ha\n"};
char c[10] = "ha ha\n";
char d[]="ha"; // d 数组有3个元素
//c = "ha ha\n"; //error 因为c是一个char * 类型的常量
char *ch = "ha ha\n"; //字符串常量在计算机的内存当中是一个没有名字的数组
printf("AAA%s",ch);
return 0;
}
字符串的输入和输出
#include<stdio.h>
void show(char *a,int len){
for(int i=0;i<len;++i){
printf("%d\n",a[i]);
}
}
int main(void){
char a[30],b[30],c[30],ch;
/*
scanf("%s%s%s%c",a,b,c,&ch); //如果输入项是字符数组的数组名或者是char *类型的变量就不需要加取地址符 使用scanf输入多个字符串时,用空格,tab或者换行来分隔
printf("%s%s%s%c",a,b,c,ch);
show(a,30); //a数组当中没有被赋值的元素 是一个垃圾值
*/
gets(a);//和scanf函数一样都会把字符数组当中的一个元素赋值为空字符。不同点1.gets可以把空格,tab赋给这个字符数组的元素。2.gets会丢弃换行符
ch = getchar();
puts(a);
putchar(ch);
puts("haha"); //puts输出该字符串之后 在输出一个换行符
int x=2,y=3;
printf("x=%d,y=%d\n",x,y);
//char *p = "x=%d,y=%d\n";
char *p = "x=%#x,y=%#x\n";
printf(p,x,y); //printf和scanf被称为可变格式输出输入函数
return 0;
}
处理字符串的函数
库函数#include<string.h>中
#include<stdio.h>
//有效长度
int strlen(char *a){
if(a == NULL)
return 0;
int len = 0;
while(a[len] != '\0')
len++;
return len;
}
//小写
char *strlwr(char *a){
if(a == NULL)
return NULL;
char *a1 = a;
while(*a != '\0'){
if(*a <= 'Z' && *a >= 'A')
*a += 32;
++a;
}
return a1;
}
//大写
char *strupr(char *a){
if(a == NULL)
return NULL;
char *a1 = a;
while(*a != '\0'){
if(*a <= 'z' && *a >= 'a')
*a -= 32;
++a;
}
return a1;
}
//复制
char *strcpy(char *a,char *b){
if(a == NULL||b == NULL)
return a;
char *a1 = a;
/*while((*a = *b)!= '\0'){
a++;
b++;
}*/
while((*(a++) = *(b++))!= '\0')
;
return a1;
}
//连接
char *strcat(char *a,char *b){
if(a == NULL||b == NULL)
return a;
char *a1 = a;
while(*(a++) != '\0')
;
a--;
while((*(a++) = *(b++))!= '\0')
;
return a1;
}
//覆盖
char *strncpy(char *a,char *b,int n){
if(a == NULL||b == NULL)
return a;
char *a1 = a;
for(int i=0;i<n;++i){
a[i]=b[i];
}
return a1;
}
//比较大小
int strcmp(char *a,char *b){
if(a == NULL||b == NULL)
return 2;
do{
if(*a=='\0' && *b=='\0')
return 0;
else if(*a<*b)
return -1;
else if(*a>*b)
return 1;
a++,b++;
}while(true);
}
int main(void){ //以上函数注释掉也可以运行,在库函数#include<string.h>中
char a[] = "ABChaha";
printf("%d\n",strlen(a));
printf("%s\n",strlwr(a));
printf("%s\n",strupr(a));
printf("%s\n",strcpy(a,"lala"));
printf("%s\n",strcat(a,"123"));
printf("%s\n",strncpy(a,"abcdef",4));
printf("%d\n",strcmp("abcde","abde"));
return 0;
}
习题1
1.输出以下杨辉三角形(要求输出10行)
方法一:
#include<stdio.h>
#define N 10
int main(void){
int a[N][N]={0};
for(int i=0;i<N;++i){
a[i][0]=1;
a[i][i]=1;
for(int j=0;j<i+1;++j){
if(i>=2&&j>=1)
a[i][j]=a[i-1][j-1]+a[i-1][j];
printf("%5d",a[i][j]);
}
putchar('\n');
}
return 0;
}
方法二:
#include<stdio.h>
#define N 10
void show(int a[N][N]){
for(int i=0;i<N;++i){
for(int j=0;j<=i;++j)
printf("%6d",a[i][j]);
putchar('\n');
}
}
int main(void){
int a[N][N]={0};
for(int i=0;i<N;++i)
a[i][0]=1;
for(int i=0;i<N;++i)
for(int j=1;j<=i;++j)
a[i][j]=a[i-1][j-1]+a[i-1][j];
show(a);
return 0;
}
习题2
2.有n个整数,使前面各数顺序向后移m个位置,最后m个数变成最前面m个数,如下图:
#include<stdio.h>
#define N 10
void show(int a[]){
for(int i=0;i<N;++i)
printf("%d",a[i]);
putchar('\n');
}
void move(int *a,int k,int index){
for(int i=0;i<k;++i){
int d = a[index];
a[index] = a[index-1];
a[index-1] = d;
index--;
}
}
int main(void){
int a[N];
for(int i=0;i<N;++i)
a[i]=i;
show(a);
int m;
do{
printf("请输入m的值:");
scanf("%d",&m);
if(m>=0&&m<=N)
break;
printf("输入有误。");
}while(1);
for(int i = N-m;i<N;++i)
move(a,N-m,i);
show(a);
return 0;
}
习题3
3.有n个人围城一圈,顺序排号。从第1个人开始报数(从1到3报数),凡报到3的人退出圈子,问最后留下的原来第几号的那位。
#include<stdio.h>
int main(void){
int a[1000]={0};
printf("请输入总人数:");
int n;
scanf("%d",&n);
for(int i=0,cnt=0,sum=0;sum!=n-1;++i){
if(a[i%n]==3)
continue;
if((a[i%n]=(cnt++)%3+1)==3)
sum++;
}
int i;
for(i=0;i<n;++i)
if(a[i]!=3)
break;
printf("最后留下的是原来第%d个人\n",i+1);
return 0;
}