[C语言] 基础知识
内容是以前的学习笔记,内容不全,主观性较大,部分基础知识未展示
基础知识
固定格式
#include<stdio.h>
int main(void)
{
return 0;
}
// 自定义文件,在当前目录下,则库名不用<>而用""
#include<stdio.h>
int main()
{
char a='B',b='O',c='Y';
a=a+32; //字符型可以加上数字,表示ASCII码变化 字符型+字符型为ASCII码相加
b=b+32;
c+=32
printf("BOY的小写是%c%c%c\n",a,b,c); //最后一次输出加上\n换行
return 0;
}
int a;
double b;
char c;
scanf("%d,%lf,%c",&a,&b,&c); //输入的表示 double需要输入时表示成long float,输出时只要%f即可
// 上述写法不会读入空格
scanf("%c%c%c",&a,&b,&c) // 这种写法会读入空格
getchar(), putchar()
#include<stdio.h>
#define PI 3.1415926 // 定义宏常量
int main()
{
char a,b,c;
const double AI=3.1415926; // 定义为不可修改的变量,实际不是常量
a=getchar(); //getchar()为逐字获取键盘输入,返回值是ASCII码
b=getchar();
c=getchar();
a+=32;
b+=32;
c+=32;
putchar(a); //putchar()输出单字符 a为字符则输出,为数值则表示ASCII码输出对应字符
putchar(b);
putchar(c);
putchar("\n"); //最后一次输出加上\n换行
return 0;
}
类型修饰符
内容 | 定义 |
---|---|
unsigned int | 最高位也是数位,正数范围扩大一倍 |
signed int | 即int |
常量及变量
china在内存在占6个字节,即c h i n a NULL,最后一位内存中为\0
\a 响铃; \ddd 三位八进制数; \xhh 两位十六进制数
常量最好使用宏定义
C语言中两个操作数都是整数则结果向下取整 30/4=7
前置和后置的区别
int x,y,i=25;
x=--i;
y=i;
// 前置 x=24,y=24
int x,y,i=25;
x=i--;
y=i;
// 后置 x=25,y=24
赋值嵌套:x=(y=(z=100))
位运算
a=01,b=10
位与 a&b=0
位或 a|b=11
位异或 a^b=11
位反 ~a=10
右移位 a>>n 除于2的n次幂
左移位 a<<n 乘于2的n次幂
sizeof 长度运算 取数据类型或变量的储存长度,字符串要+1
取值类型小的数会自动向取值范围大的数靠
对异常输入的处理
#include<stdio.h>
int main()
{
int r;
float x,y,z,t;
r=scanf("%f %f %f %f",&x,&y,&z,&t);
if(r==4&&(x>0&&y>0&&z>0&&t>0)) // 关键地方
{
printf("%.2f",x+y+z-t);
}
else
{
printf("error");
}
return 0;
}
数学运算
#include<stdio.h>
#include<math.h> //涉及数学运算需加上
int main()
{
int a=2,b;
double c=5.02,d,e;
b=abs(a); //整数求绝对值专用
c=fabs(a); //任何数求绝对值
e = pow(c,a); //指数
return 0;
}
- %m.nf
m为总长度,n为小数位数,m为正则向前补空,为负向后补空 如果m前有0则补零
如果m或n是*表示需再赋值或给予变量 printf("%*.*d",7,2,i)
如果是输入中 scanf("%*d%d",&i,&j) 则表示跳过第一个输入值
- %e(%m.ne)
科学计数表示,未限定m和n时e前6位,e+三位共5位
- (int)(x) 强转 y=(float)(x)
强制转整数,抹去而不是四舍五入
- 输入
输入中带有空格,则会跳过输入流中所有空格字符,在多个输入且输入字符时需要注意
scanf("%d%d",&i,&j) 和scanf("%d,%d",&i,&j) 输入不一样,要考虑输入流中不可打印字符
选择语句
#include<stdio.h>
int main()
{
int a;
scanf("%d",&a);
if(a>=60)
{
printf("High\n");
}
else
{
printf("low\n");
}
return 0;
}
//if else后面不接分号,且后续就一句或接一个选择语句 大括号可以省略
#include<stdio.h>
int main()
{
int a;
scanf("%d",&a);
if(a>=60)
printf("High\n");
else
printf("low\n");
return 0;
}
#include<stdio.h>
int main()
{
int a;
scanf("%d",&a);
if(a>=60)
printf("High\n");
else
if(a>=40)
printf("Middle\n");
else
printf("low\n");
return 0;
}
|| 或 && 且
# 判断一个字母是否为大写
char ch;
scanf("%c",&ch);
if(ch>='A'&&ch<='Z') //字母可以根据ASCII码比较大小
选择表达式
判断语句可以写成如下形式:
表达式1?表达式2:表达式3
#include<stdio.h>
int main()
{
int a;
scanf("%d",&a);
a>=60?printf("High\n"):printf("low\n");
return 0;
}
switch语句
题目:输入成绩 90-100为A,80以上为B,70以上为C,60以上为D,小于60为E
#include<stdio.h>
int main()
{
double score,a;
scanf("%lf",&score);
a=(int)(score/10)
switch(a)
{
case 10: //重复可以放空
case 9:printf("成绩等级为A\n");break;
case 8:printf("成绩等级为B\n");break;
case 7:printf("成绩等级为C\n");break;
case 6:printf("成绩等级为D\n");break;
case 5:
case 4:
case 3:
case 2:
case 1:
case 0:printf("成绩等级为E\n");break;
default:printf("输入不正确\n");break; //对异常值的处理
}
return 0;
}
循环语句
while循环
先判断再执行一次循环体
题目:2+4+6+…+100
#include<stdio.h>
int main()
{
int n=1,sum=0,a=2;
while(n<=50) //判断首尾循环以及等号是否成立
{
sum+=a;
a+=2;
n++;
}
return 0;
}
do...while循环
先执行一次循环体再判断
#include<stdio.h>
int main()
{
int n=1,sum=0,a=2;
do
{
sum+=a;
a+=2;
n++;
}
while(n<=50); //末尾有分号;
return 0;
}
break/continue
#include<stdio.h>
int main()
{
int n=1,sum=0,a=2;
while(n<=50)
{
sum+=a;
a+=2;
n++;
if(n>=30)
break;
if(n==18)
continue;
}
return 0;
}
//也可写成如下
#include<stdio.h>
int main()
{
int n=1,sum=0,a=2;
while(n<=50&&sum<3000) //将终止条件取反放到循环条件中
{
sum+=a;
a+=2;
n++;
if(n==18)
continue;
}
return 0;
}
for循环
//while循环:
语句1[定义+赋值]
while(语句2[循环条件])
{
语句3[递进条件]
循环体
}
//for循环
语句1[定义]
for(语句1[赋值];语句2[循环条件];语句3[递进条件])
{
循环体
}
定义赋值可以放循环外,递进条件可以放循环内,类似while循环,但前后分号 ; 需保留
//for循环
语句1[定义+赋值]
for(;语句2[循环条件];)
{
语句3[递进条件]
循环体
}
数组
定义一维数组
题:输入10个整数
#include<stdio.h>
int main()
{
int i,a[10]; //用一维数组连续定义10个数
for(i=1;i<=10;i++)
{
scanf("%d",&a[i-1])
}
return 0;
}
如果是明确赋值可写为:
int a[10]={2,3,4};
上述式子等价于:
int a[10];
a[0]=2;
a[1]=3;
a[2]=4;
a[3]=0;
a[4]=0;
题:输入10个整数,并由小到大排序
//选择排序
#include<stdio.h>
int main()
{
int i,j,k,a[10];
for(i=0;i<=9;i++)
scanf("%d",&a[i])
for(i=0;i<=8;i++) //循环内跟循环或者选择可以省略大括号
for(j=i+1;j<=9;j++)
if(a[i]>a[j])
{
k=a[i];
a[i]=a[j];
a[j]=k;
}
return 0;
}
定义二维数组
int a[2][3]={{1,2,3},{4,5,6}};
int a[2][3]={1,2,3,4,5,6}; //两种写法等同,取前三个为第一行a[0][0]/a[0][1]/a[0][2]
int a[2][3]={{1,2,3},{}}; //没给的数值默认为0,没给的字符默认为\0
输出字符数组
//整体输出 2种方法
// 1.用%s输出
#include<stdio.h>
int main()
{
char c[3][3]={{'C','H','E'},{'N','X','I'},{'G','L','6'}};
printf("%s\n",c);
return 0;
}
// 2.puts()
#include<stdio.h>
int main()
{
char c[3][3]={{'C','H','E'},{'N','X','I'},{'G','L','6'}};
puts(c);
printf('\n');
return 0;
}
// \0后的不输出,可在定义数组时多定义一个字符,用\0占据末尾确保程序正确
输入字符数组
//用scanf()输入 "I am ChenXi"
#include<stdio.h>
int main()
{
char c1[6],c2[6],c3[6]; //不足的用\0补齐
scanf("%s%s%s",c1,c2,c3); //(1)提取的字符串不含空格 (2)c前不需要&存址
return 0;
}
//gets()
#include<stdio.h>
int main()
{
char c[18];
gets(c); //提取的字符串含空格
return 0;
}
题:输入一行由空格和单词组成的字符串(80个字符内),统计有多少单词
#include<stdio.h>
int main()
{
char c[81];
gets(c);
int sum=0,i;
if(c[0]!=' ')
sum=1;
for(i=0;c[i]!='\0';i++)
if(c[i]==' '&&c[i+1]!=' '&&c[i+1]!='\0')
sum++;
printf("合计有&c个单词\n",sum);
return 0;
}
函数
调用有参函数
题:输入4个数,输出前两数最大值,后两数最大值,四个数最大值
#include<stdio.h>
int main()
{
float max(float x,float y); //函数的声明,写在开头,加分号
float a[4],i;
for(i=0;i<=3;i++)
{
printf("请输入第%d个数",i+1);
scanf("%f",&a[i]);
}
max_f=max(a[0],a[1]);
max_b=max(a[2],a[3]);
max_t=max(max_f,max_b);
printf("前两数最大值为%f\n",max_f);
printf("后两数最大值为%f\n",max_b);
printf("四个数最大值为%f\n",max_t);
return 0;
}
float max(float x,float y) //函数的解释,写在主体后面,不加分号
{
if(x>=y) //不需要再定义
return(x);
else
return(y);
}
//函数的解释本题也可以写为
float max(float x,float y)
{
return(x>=y?x:y);
}
调用无参函数
(指无返回值)
题:输入10个整数,输出升序排序
#include<stdio.h>
int main()
{
void sort(int a[],int n);
int a[10],i;
for(i=0;i<=9;i++)
{
printf("请输入第%d个数",i+1);
scanf("%d",&a[i]);
}
sort(a,10);
printf("排序后的整数依次是\n");
for(i=0;i<=9;i++)
printf("%d",a[i]);
printf("\n");
return 0;
}
void sort(int a[],int n)
{
int i,j,k;
for(i=0;i<=n-1;i++)
for(j=i+1;j<=n;j++)
if(a[i]>a[j])
{
k=a[i];
a[i]=a[j];
a[j]=k;
}
}
函数嵌套
(最内层函数最后解释)
题:输入4个整数,输出最大数
#include<stdio.h>
int main()
{
int max4(int a,int b,int c,int d);
int a,b,c,d,max_t;
scanf("%d,%d,%d,%d",&a,&b,&c,&d);
max_t=max4(a,b,c,d);
printf("最大数为%d\n",max_t);
return 0;
}
int max4(int a,int b,int c,int d)
{
return(max2(max2(max2(a,b),c),d));
}
int max2(int x,int y)
{
return(x>=y?x:y);
}
函数递归
题:求n的阶乘
//判明递归函数相邻的关系和递归终止条件
#include<stdio.h>
int main()
{
int jiecheng(int n);
int n;
scanf("%d",&n);
printf("%d的阶乘为%d\n",n,jiecheng(n));
return 0;
}
int jiecheng(int n)
{
int results;
if(n<0)
printf("输入错误\n");
else if(n==0||n==1)
results=1;
else
results=jiecheng(n-1)*n;
return(results);
}
指针
定义指针变量
int *p,a=5;
p=&a;
题:输入两个整数,先大后小输出
#include<stdio.h>
int main()
{
int a,b,*p,*q,*r;
scanf("%d,%d",&a,&b);
p=&a;
q=&b;
if(a<b)
{
r=p;
p=q;
q=r;
}
printf("%d %d\n",*p,*q);
return 0;
}
指针变量和一维数组
题:输入5个整数,2倍后输出
#include<stdio.h>
int main()
{
int a[5];
int *p,i;
p=&a[0];
for(i=0;i<=4;i++)
{
scanf("%d",p+i);
*(p+i)=*(p+i)*2;
}
for(;p<=&a[4];p++) //指针和数组已关联
printf("%d\t",*p);
printf("\n");
return 0;
}
知识点
- &a[5]=a+5 (知识点1,2是指针变形的核心)
- a[5]=*(a+5)
- &a[0]=a
指针变量和一维数组相关函数
一、形参是指针变量
函数声明: a[]→*p
函数解释: a[i]→*(p+1)
二、实参是指针变量
函数使用: a→p (数组a是a[0]的指针q)
指针变量和二维数组
int *p,a[2][3]={{1,2,3},{4,5,6}};
p=&a[0][0];
p+5=&a[1][2]
知识点
- &a[i][j]=a[i]+j=a[0]+i*列数+j=p+i*列数+j
- a[i][j]=*(a[i]+j)
对二维数组而言,降维的元素为指针
指针变量和二维数组相关函数
一、形参是指针变量
函数声明: a[][某数]→*p
函数解释: a[i][j]→*(p+i*列数+j)
函数使用: a→*a
二、实参是指针变量
函数使用: a→*p (使用前先关联)
指针变量指向二维数组的行变量
int a[3][4]={{1,2,3,4},{4,5,6,7},{4,5,6,6}};
int (*p)[4]; //(*p)[某数] 该指针为指向数组的行变量
p=a; //指向数组的第一行
p=a+1; //指向数组的第二行
用指向二维数组行变量的指针变量做形参数
函数声明: a[][某数]→(*p)[某数]
函数解释: a[i][j]→*(*(p+i)+j)
指针变量和字符串相关函数
(字符串等同一维数组)
void dec(char old[],char new[])
{
int i=0;
for(;old[i]!='\0';i++)
new[i]=old[i];
new[i+1]='\0';
}
//形参改为指针变量
void dec(char *p,char *q)
{
int i=0;
for(;*(p+i)!='\0';i++)
*(q+i)=*(p+i);
*(q+i+1)='\0';
}
指针可以直接指向字符串
char *p;
p="ChenXi";
指针函数
题:输入两个整数,用指针函数输出两者大值
#include<stdio.h>
int main()
{
int max(int x,int y);
int a,b,max_t;
int (*p)(int,int); //定义指针函数,注意格式
p=max; //两个函数进行关联
printf("请输入两个整数: \n");
scanf("%d,%d",&a,&b);
printf("两数中较大值为: %d",(*p)(a,b));
return 0;
}
int max(int x,int y)
{
return(x>y?x:y);
}
返回指针值的函数
题:3个学生1/2/3各四门成绩,输入学生序号后输出4门成绩
思路:
输入序号后调用函数返回行指针,另一个普通指针指向行指针初始值一次性输出
#include<stdio.h>
int main()
{
float *search(float (*p)[4],int n); //返回值是指针的函数标识方法
float a[3][4]={{87,88,94,65},{74,86,93,81},{82,75,93,83}};
float *p;
int num,i;
printf("请输入学生序号");
scanf("%d",&num);
printf("第%d名学生的成绩为: \n",num);
p=search(a,num-1); //调用时候放的是数组,声明的时候是行变量
for(i=0;i<=3;i++)
printf("%f\n",*(p+i));
printf("\n");
return 0;
}
float *search(float (*p)[4],int n)
{
int *q;
q=(p+n)[0];
return(q);
}
结构体
定义结构体
struct student
{
int student_id;
char name[30];
char sex;
float score;
};
struct student a={001,"ChenXi",'M',99.5};
//结构体的格式 末尾的大括号后面跟分号
//也可以写作如下
struct student
{
int student_id;
char name[30];
char sex;
float score;
}a={001,"ChenXi",'M',99.5};
题:学生信息放于结构体变量中,然后输出
#include<stdio.h>
struct student
{
int student_id;
char name[30];
char sex;
float score;
}a={001,"ChenXi",'M',99.5};
int main()
{
printf("学号:%d\n姓名:%s\n性别:%c\n成绩:%f\n:",a.student_id,a.name,a.sex,a.score);
//注意结构体内变量的写法
return 0;
}
//结构体定义和赋值放在int main()以前
#include<stdio.h>
struct student
{
int student_id;
char name[30];
char sex;
float score;
}a;
int main()
{
printf("%d,%s,%c,%f",&a.student_id,a.name,&a.sex,&a.score); //字符串的输入(数组)不需要&
return 0;
}
结构体数组
struct student
{
int student_id;
char name[30];
float score;
}students[3]={{001,"ChenXi",99.5},{002,"ChenX",99.7},{003,"Chen",89.5}};
结构体变量和指针变量
#include<stdio.h>
struct student
{
int student_id;
char name[30];
float score;
}a={001,"ChenXi",99.5};
int main()
{
struct student *p;
p=&a;
printf("学号:%d\n姓名:%s\n成绩:%f\n:",(*p).student_id,(*p).name,(*p).score);
return 0;
}
//也可以写作如下
printf("学号:%d\n姓名:%s\n成绩:%f\n:",p->student_id,p->name,p->score);