大一学习的 C 语言,现在回过头来发现已经忘的差不多了,正好趁着这个机会复习整理下,本文的目的偏向于整理备忘,讲解的部分会占很少。
目录及相关习题参考 《C程序设计(第四版)》谭浩强
当型循环
直到型循环
(1)普通整型(int),存储单元中使用反码形式存放
2字节 -32768~32767 或 4字节 -2147483648~2147483647
(2)短整型(short int 或 short),同反码存储
vc6.0 int 4 字节,short int 2 字节
(3)长整型(long int 或 long)
vc6.0 long 4 字节
(4)双长整型(long long int)
一般 8 字节
有符号数据 0 正 1 负,默认为有符号数据
一字节
char c = '?';
注意
'A' 表示一个字符
"A" 表示一个字符串,后面还有一个 \0
单精度浮点型(float),双精度浮点型(double),长双精度(long double)
因为 C 是强类型语言,如赋值语句两侧变量类型不相同则会进行转换
注意
printf("%f\n", 1/3); //输出 0.000000,因为 1/3 结果为整型 0
printf("%f\n", 1.0/3); //正确方法,输出 0.333333
(double)a
(int)(x+y)
int(x)+y //只将 x 转为整型
两种注释方式
/*
开始,*/
结束//
开始语法:printf(格式字符, 输出变量);
example: printf("%d,%c\n",i,c); // 注意是双引号
修饰字符
%m.nf 指定数据的宽度和小数位数,m 包含小数点
printf("%6.3f\n", 1.0/3); //输出 0.333
printf("%06.3f\n", 1.0/3); //输出00.333 宽度不够 0 凑位
语法:scanf(格式字符, 地址表列);
example: scanf("a=%f,b=%f,c=%f", &a, &b, &c); //1. 双引号 2. 注意是地址 &a
注意
(1)
double 类型数据
scanf 时格式字符使用 %lf
printf 时格式字符使用 %f
(2)
scanf 时,遇空格,回车,tab或遇到非法字符(如输入数字时遇到字符)则认为该数据结束
putchar 输出一个字符
putchar(c);
getchar 输入一个字符
c = getchar();
getchar 还可以获取屏幕上无法显示的字符,如控制字符
//math 库 pow 函数应用
#include
#include
int main(){
float r, p;
int n;
r = 0.09;
n = 10;
p = pow((1+r), n);
printf("%f\n", p);
return 0;
}
//利息计算
#include
#include
int main(){
double P1, P2, P3, P4, P5;
P1 = 1000*(1+5*0.0585);
P2 = (1000*(1+2*0.0468))*(1+3*0.054);
P3 = (1000*(1+3*0.054))*(1+2*0.0468);
P4 = 1000*pow(1+0.0414, 5);
P5 = 1000*pow(1+0.0072/4, 5*4);
printf("%f\n%f\n%f\n%f\n%f\n", P1, P2, P3, P4, P5);
return 0;
}
注意
第二问,char 存储为一字节,按补码形式存储
注意
scanf 时,遇空格,回车,tab或遇到非法字符(如输入数字时遇到字符)则认为该数据结束
所以 71.82 和 Aa 之间不应有空格或回车
一般有两种形式
(1)
if(a>b){
c = a;
}
else{
c = b;
}
(2)
if(number>500){
cost = 0.15;
}
else if(number>300){
cost = 0.075;
}
else{
cost = 0;
}
注意
// 无花括号时,if 条件为真,只会执行之后的一条语句
#include
int main()
{
if (true)
{
printf("11111111111\n"); // 这两条都会打印
printf("11111111111\n");
}
if (false)
printf("11111111111\n"); // 只有这一条不会打印
printf("22222222222\n"); // 以下两条都会打印
printf("22222222222\n");
return 0;
}
ch=(ch>='A' && ch<='Z')?(ch+32):ch;
switch(grade){
case 'A': printf("85~100\n");break;
case 'B': printf("70~84\n");break;
case 'C': printf("60~69\n");break;
case 'D': printf("<60\n");break;
default: printf("enter datda error!\n");
}
//注意每次需要用 break 跳出语句,不然后一直往下运行
// (1)判断哪个等级方法(2)60一下输出E
#include
int main()
{ float score;
char grade;
printf("请输入学生成绩:");
scanf("%f",&score);
while (score>100||score<0)
{printf("\n 输入有误,请重输");
scanf("%f",&score);
}
switch((int)(score/10))
{case 10:
case 9: grade='A';break;
case 8: grade='B';break;
case 7: grade='C';break;
case 6: grade='D';break;
case 5:
case 4:
case 3:
case 2:
case 1:
case 0: grade='E';
}
printf("成绩是 %5.1f,相应的等级是%c\n ",score,grade);
return 0;
}
#include
#include
int main()
{
int num,indiv,ten,hundred,thousand,ten_thousand,place; //分别代表个位,十位,百位,千位,万位和位数
printf("请输入一个整数(0-99999):");
scanf("%d",&num);
if (num>9999)
place=5;
else if (num>999)
place=4;
else if (num>99)
place=3;
else if (num>9)
place=2;
else place=1;
printf("位数:%d\n",place);
printf("每位数字为:");
ten_thousand=num/10000;
thousand=(int)(num-ten_thousand*10000)/1000;
hundred=(int)(num-ten_thousand*10000-thousand*1000)/100;
ten=(int)(num-ten_thousand*10000-thousand*1000-hundred*100)/10;
indiv=(int)(num-ten_thousand*10000-thousand*1000-hundred*100-ten*10);
switch(place)
{case 5:printf("%d,%d,%d,%d,%d",ten_thousand,thousand,hundred,ten,indiv);
printf("\n反序数字为:");
printf("%d%d%d%d%d\n",indiv,ten,hundred,thousand,ten_thousand);
break;
case 4:printf("%d,%d,%d,%d",thousand,hundred,ten,indiv);
printf("\n反序数字为:");
printf("%d%d%d%d\n",indiv,ten,hundred,thousand);
break;
case 3:printf("%d,%d,%d",hundred,ten,indiv);
printf("\n反序数字为:");
printf("%d%d%d\n",indiv,ten,hundred);
break;
case 2:printf("%d,%d",ten,indiv);
printf("\n反序数字为:");
printf("%d%d\n",indiv,ten);
break;
case 1:printf("%d",indiv);
printf("\n反序数字为:");
printf("%d\n",indiv);
break;
}
return 0;
}
#include
int main()
{int t,a,b,c,d;
printf("请输入四个数:");
scanf("%d,%d,%d,%d",&a,&b,&c,&d);
printf("a=%d,b=%d,c=%d,d=%d\n",a,b,c,d);
if (a>b)
{ t=a;a=b;b=t;}
if (a>c)
{ t=a;a=c;c=t;}
if (a>d)
{ t=a;a=d;d=t;}
if (b>c)
{ t=b;b=c;c=t;}
if (b>d)
{ t=b;b=d;d=t;}
if (c>d)
{ t=c;c=d;d=t;}
printf("排序结果如下: \n");
printf("%d %d %d %d \n" ,a,b,c,d);
return 0;
}
当型循环
while(i<=100){
sum=sum+i;
i++;
}
直到型循环
do{
printf("%d", i++);
}
while(i<=100);
for(i=1;i<=100;i++){
printf("%d", i);
}
// 求解最小公倍数和最大公约数
// 求最大公约数: 辗转相除法(欧几里得算法)
// 两数乘积等于最大公约数与最小公倍数的乘积
#include
int main(){
int m,n,temp,r,p;
printf("请输入两个正整数 m,n:");
scanf("%d%d", &m, &n);
if(m
// if((c=getchar())!='\n')
#include
int main()
{
char c;
int letters=0,space=0,digit=0,other=0;
printf("请输入一行字符:\n");
while((c=getchar())!='\n')
{
if (c>='a' && c<='z' || c>='A' && c<='Z')
letters++;
else if (c==' ')
space++;
else if (c>='0' && c<='9')
digit++;
else
other++;
}
printf("字母数:%d\n空格数:%d\n数字数:%d\n其它字符数:%d\n",letters,space,digit,other);
return 0;
}
//注意an的求法
#include
int main(){
int a,n,i=1,result=0,an=0;
printf("a,n:");
scanf("%d,%d",&a,&n);
while(i<=n){
an=an+a;
printf("%d\n",an);
result=result+an;
a=a*10;
i++;
}
printf("a+aa+aaa+ …=%d\n",result);
return 0;
}
#include
int main()
{double s=0,t=1;
int n;
for (n=1;n<=20;n++)
{
t=t*n;
s=s+t;
}
printf("1!+2!+...+20!=%22.15e\n",s);
return 0;
}
重点
//水仙花数
#include
#include
int main(){
int i,ge,shi,bai;
for(i=100;i<1000;i++){
ge=i%10;
shi=(i%100)/10;
bai=i/100;
if(i==(pow(ge,3)+pow(shi,3)+pow(bai,3))){
printf("%d ",i);
}
}
return 0;
}
//100以内的完数
#include
int main()
{int m,s,i;
for (m=2;m<1000;m++)
{s=0;
for (i=1;i
//斐波那契数列变形
#include
int main()
{
int i,n=20;
double a=2,b=1,s=0,t;
for (i=1;i<=n;i++)
{
s=s+a/b;
t=a,
a=a+b,
b=t;
}
printf("sum=%16.10f\n",s);
return 0;
}
//牛顿迭代法求平方根
//初值x0=a/2
//注意do……while循环while的条件
#include
#include
int main()
{
float a,x0,x1;
printf("enter a positive number:");
scanf("%f",&a);
x0=a/2;
x1=(x0+a/x0)/2;
do
{x0=x1;
x1=(x0+a/x0)/2;
}while(fabs(x0-x1)>=1e-5);
printf("The square root of %5.2f is %8.5f\n",a,x1);
return 0;
}
重点
//图形输出问题
//分成两部分来看,找每一行空格,*和行号的规律
//注意输出一行后记得输出\n
#include
int main(){
int i,j,k;
for(k=1;k<=4;k++){
for(i=1;i<=4-k;i++){
printf(" ");
}
for(j=1;j<=2*k-1;j++){
printf("*");
}
printf("\n");
}
for(k=1;k<=3;k++){
for(i=1;i<=k;i++){
printf(" ");
}
for(j=1;j<=2*(3-k)+1;j++){
printf("*");
}
printf("\n");
}
return 0;
}
//比赛排序问题
//先逻辑图,判断出正确结果
//编程使用假设的方法,三层循环,判断符合条件的情况
#include
int main(){
char i,j,k;
for(i='X';i<='Z';i++){
for(j='X';j<='Z';j++){
if(i!=j){
for(k='X';k<='Z';k++){
if(k!=i&&k!=j){
if(i!='X'&&k!='X'&&k!='Z'){
printf("A-%c,B-%c,C-%c\n",i,j,k);
}
}
}
}
}
}
return 0;
}
int a[10];
注意
(1)a[10] 下标从0开始到9
(2)
int a[3+5]; // 合法
scanf("%d", &n);
int a[n];
int a[n] 是不合法的,即c语言不允许对数组的大小作动态定义
(3)
void func(int n){
int a[2*n];
}
为函数参数时可以,这种情况称为“可变长数组”
(4)为static存储方式时,不能用“可变长数组”
static int a[2*n]; //非法
a[0] 或 a[2*3]
int a[10]={0,1,2,3,4,5,6,7,8,9}; //注意大括号,逗号
int a[10]={0,1,2,3,4}; // 前5个赋初值,后5个赋初值0
int a[10]={0};
int a[]={0,1,2,3,4}; //数组长度自动为5
float a[3][4]; //可以理解成3行4列矩阵,内存中先顺序存储第一行,再存储第二行
int a[3][4]; //定义3×4二维数组
a[3][4]=3; //不存在a[3][4]元素
注意定义和数组下标范围的区别
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};
char c[10]="China";
#include
char str[]="China\nBeijing"
puts(str);
gets(str);
strcat(str1, str2);
注意:
(1)str1必须足够大,以便容纳连接后的新字符串
(2)连接前两字符串后面都有\0
strcpy(str1,str2); // 将str2复制到str1
strcpy(str1,str2,n); //将str2最前面n个字符复制到str1中
strcmp(str1,str2);
(1)如全部字符相同,则认为两个字符串相等
(2)若出现不相同字符,则以第一队不相同的字符的比较结果为准
函数值:
(1)相等,则返回0
(2)str1 > str2,返回正整数
(3)str1 < str2,返回负整数
strlen(str); //字符长度,不包含\0
#include
#include
int main()
{int i,j,n,a[101];
for (i=1;i<=100;i++)
a[i]=i;
a[1]=0;
for (i=2;i
#include
int main()
{ int a[11]={1,4,6,9,13,16,19,28,40,100};
int temp1,temp2,number,end,i,j;
printf("array a:\n");
for (i=0;i<10;i++)
printf("%5d",a[i]);
printf("\n");
printf("insert data:");
scanf("%d",&number);
end=a[9];
if (number>end)
a[10]=number;
else
{for (i=0;i<10;i++)
{if (a[i]>number)
{temp1=a[i];
a[i]=number;
for (j=i+1;j<11;j++)
{temp2=a[j];
a[j]=temp1;
temp1=temp2;
}
break;
}
}
}
printf("Now array a:\n");
for (i=0;i<11;i++)
printf("%5d",a[i]);
printf("\n");
return 0;
}
//一个数组中元素逆序
//以中间元素为中心,两侧元素互换即可
#include
#define N 5
int main()
{ int a[N],i,temp;
printf("enter array a:\n");
for (i=0;i
重点:杨辉三角
#include
# define N 10
int main(){
int i,j,a[N][N];
for(i=0;i
//图形输出
#include
int main()
{ char a[5]={'*','*','*','*','*'};
int i,j,k;
char space=' ';
for (i=0;i<5;i++)
{ printf("\n");
printf(" ");
for (j=1;j<=i;j++)
printf("%c",space);
for (k=0;k<5;k++)
printf("%c",a[k]);
}
printf("\n");
return 0;
}
//非凯撒密码,对称密码
#include
int main()
{int j,n;
char ch[80];
printf("input cipher code:\n");
gets(ch);
printf("\ncipher code:%s\n",ch);
j=0;
while (ch[j]!='\0')
{ if ((ch[j]>='A') && (ch[j]<='Z'))
ch[j]=155-ch[j];
else if ((ch[j]>='a') && (ch[j]<='z'))
ch[j]=219-ch[j];
else
ch[j]=ch[j];
j++;
}
n=j;
printf("original text:");
for (j=0;j
//strcat实现 不用strlen的方法
//s1[i++]=s2[j++]
#include
int main()
{ char s1[80],s2[40];
int i=0,j=0;
printf("input string1:");
scanf("%s",s1);
printf("input string2:");
scanf("%s",s2);
while (s1[i]!='\0')
i++;
while(s2[j]!='\0')
s1[i++]=s2[j++];
s1[i]='\0';
printf("\nThe new string is:%s\n",s1);
return 0;
}
//strcmp实现
#include
int main()
{ int i,resu;
char s1[100],s2[100];
printf("input string1:");
gets(s1);
printf("\ninput string2:");
gets(s2);
i=0;
while ((s1[i]==s2[i]) && (s1[i]!='\0'))i++;
if (s1[i]=='\0' && s2[i]=='\0')
resu=0;
else
resu=s1[i]-s2[i];
printf("\nresult:%d.\n",resu);
return 0;
}
//strcpy实现 运用了strlen
#include
#include
int main()
{ char s1[80],s2[80];
int i;
printf("input s2:");
scanf("%s",s2);
for (i=0;i<=strlen(s2);i++)
s1[i]=s2[i];
printf("s1:%s\n",s1);
return 0;
}
定义函数别忘了声明函数
数组名作为函数参数时,传递的是数组首元素的地址,也就是说形参的值改变,实参的值也改变
float score[10];
average(score);
float average(float array[10]){
……
}
(1)在一个函数内部定义即为局部变量
(2)形式参数也是局部变量
在函数外部定义
为区别全局变量和局部变量,习惯将全局变量的第一个字母用大写表示
静态存储方式是指在程序运行期间由系统分配的固定的存储空间,动态存储方式是在程序运行期间根据需要进行动态分配
C 的存储类别包括四种:自动(auto),静态(static),寄存器(register),外部(extern)
注意
虽静态局部变量在函数结束调用后仍存在,但其他函数不能调用它。
全局变量都存储在静态存储区中
拓展外部变量的作用域:
//将 A,B,C 使用范围拓展到定义之前
int main(){
extern int A,B,C;
……
}
int A,B,C
file1:
int A;
int main(){
……
}
file2:
extern A;
……
/// 添加static声明
file1:
static int A;
int main(){
……
}
file2:
extern A;
……
//函数递归应用
#include
double P(int n,int x);
int main(){
int n,x;
double result;
printf("n,x:");
scanf("%d,%d",&n,&x);
result=P(n,x);
printf("%f",result);
}
double P(int n,int x){
if(n==0){
return 1;
}
else if(n==1){
return x;
}
else if(n>=1){
return (2*n-1)*x-P(n-1,x)-(n-1)*P(n-2,x)/n;
}
}
![](https://image-1251466963.cos.ap-chengdu.myqcloud.com/qiniu/20200301143808.png)
#include
int main()
{ void convert(int n);
int number;
printf("input an integer: ");
scanf("%d",&number);
printf("output: ");
if (number<0)
{putchar('-');putchar(' '); /* 先输出一个‘-’号和空格 */
number=-number;
}
convert(number);
printf("\n");
return 0;
}
void convert(int n)
{ int i;
if ((i=n/10)!=0)
convert(i);
putchar(n%10+'0');
putchar(32);
}
int *point_1, *point_2;
p=&a;
*p=1;
(1)& 取地址符
(2)* 指针运算符(或间接访问运算符),*p代表指针变量p指向的对象
int *p;
int a[10]={0,1,2,3,4,5,6,7,8,9};
p=a; //将a数组首元素的指针赋给p
或
p=&a[0];
p++; //指向下一个元素地址
p--; //指向前一个元素地址
char *string="I love China";
#include
或 #include
malloc(100); //开辟100字节临时分配空间
p=calloc(50,4); //分配50个4字节空间
free(p); //释放空间
relloc(p,50); //改变分配空间的大小
定义
struct Student{
int num;
char sex;
} student1,student2; // 注意分号
or
struct Student student1,student2;
初始化和使用
student1={11011,'M'};
student.num=10010; //使用 . 引用结构体内变量
struct Student stu_1;
struct Student *p;
p=&stu_1;
引用结构体中变量三种方法:
(1)stu.num
(2)(*p).num
(3)p->num //替代了第二种写法, '->' 称为指向运算符
共享一段内存的结构,后一个数据会覆盖前面的数据
union Data{
int i;
char ch;
float f;
}
一个变量只有几种可能的值
enum Weekday{sun,mon,tue,wed,thu,fri,sat};
一般用法:
typedef int Integer;
结构体;
typedef struct{
int mouth;
int day;
int year;
}Date;
文件类型指针 stdio.h
fopen打开文件
#include
FILE *fp;
fp=fopen("al","r"); //注意双引号
fclose(fp);
fgetc(fp);
fputc(ch,fp);
或
getc(fp); //stdio.h 中宏定义,和fgetc相同
putc(ch,fp);
fgets(str,n,fp);
fputs(str,fp);
fscanf(fp,"%d %f",&i,&f);
fprintf(fp,"%d,%6.2f",i,f);
fread(&stud[i],sizeof(struct Student_type),1,fp);
fwrite(&stud[i],sizeof(struct Student_type),1,fp);
rewind(fp1);
代码
#include "stdio.h"
int main()
{
int a,b;
a=077;
b=a&3;
printf("\40: The a & b(decimal) is %d \n",b);
b&=7;
printf("\40: The a & b(decimal) is %d \n",b);
}
样例输出
: The a & b(decimal) is 3
: The a & b(decimal) is 3
代码
#include "stdio.h"
main()
{
int a,b;
a=077;
printf("%d",a);
b=a|3;
printf("\40: The a & b(decimal) is %d \n",b);
b|=7;
printf("\40: The a & b(decimal) is %d \n",b);
}
样例输出
63 : The a & b(decimal) is 63
: The a & b(decimal) is 63
同 0 异 1
代码
#include "stdio.h"
main()
{
int a,b;
a=7;
b=3;
printf("%d",a^b);
return 0;
}
样例输出
4
代码
#include "stdio.h"
main()
{
int a,b;
a=7;
printf("%x",~a);
return 0;
}
样例输出
fffffff8
代码
#include "stdio.h"
main()
{
int a,b;
a=7;
printf("%x",a>>2);
return 0;
}
样例输出
1
#include 或 #include "math.h"
函数名 | 功能 | 函数原型 |
---|---|---|
abs | 绝对值 | int abs(intx); |
fabs | 绝对值 | double fabs(double x); |
exp | e^x | double exp(double x); |
floor | 不大于x的最大整数 | double floor(double x); |
log | lnx | double log(double x); |
log10 | lgx | double log10(double x); |
pow | x^y | douoble pow(double x, double y); |
sqrt | √x | double sqrt(double x); |
计算log2n,使用换底公式
log(n)/log(2);
#include
函数名 | 功能 | 函数原型 |
---|---|---|
isanum | 判断是否数字 | int isanum(int ch); |
islower | 判断是否小写字母 | int islower(int ch); |
isupper | 判断是否大写字母 | int isupper(int ch); |
#include
# include
void *memset(void *s, int c, unsigned long n);
#include
同一优先级的运算符,结合次序由结合方向所决定。
简单记就是:! > 算术运算符 > 关系运算符 > && > || > 赋值运算符