一、认识C语言基本语句(print()语句;scanf()语句)
首先,我们先来记住一个框架,不用理解,先记住
#include<stdio.h>
int main()
{
return 0;
}
接下来我们来打印第一个C语言程序
#include<stdio.h>
int main()
{
printf("Hello,word!\n");
return 0;
}
![](https://i-blog.csdnimg.cn/blog_migrate/e4c03f65091abd0b2875d5691b13c3b8.png)
这里我们就用到了printf语句即标准化输出语句,用来打印我们要输出的东西
程序中的main函数也叫主函数——程序的入口,main函数有且只有一个
定义变量时
int a , b , c ; 或者写成
int a ;
int b ;
int c ;
了解一些C语言基本数据类型
short //短整形 字符串 %s
int //整形 %d
long //长整形
long long //更长的整形
char //字符数据类型 %c
float //单精度浮点数 %f
double //双精度浮点数 %lf
用printf语句输出int、float、double、char型数据
1、
#include<stdio.h>
int main()
{
int a = 5, b, c, d, e, f;
b = a + 2;
c = b - a;
d = a * c;
e = a / d;
f = a % d;
printf("a=%d,b=%d,c=%d,e=%d,f=%d\n", a, b, c,e,f);
return 0;
}
![](https://i-blog.csdnimg.cn/blog_migrate/adc67e42e7339aac3f5088801aae5e5d.png)
printf(" %d might %d is %d \n", a , b , c ); 转换说明的数量要与待打印值的数量相等
%取余 /取整?
2、
#include<stdio.h>
int main()
{
double a, b, c, sum;
a = 3.67;
b = 5.43;
c = 6.21;
sum = (a + b + c) / 3;
printf("a=%lf,b=%lf,c=%lf\n", a, b, c);
printf("sum=%lf\n",sum);
return 0;
}
![](https://i-blog.csdnimg.cn/blog_migrate/726296b7ada26e3b7a2745ff98fb2687.png)
3、
#include<stdio.h>
int main()
{
char a = 'B', b = 'O', c = 'Y';
a = a + 32;
b = b + 32;
c = c + 32;
printf("小写字母依次是%c%c%c\n", a, b, c);
return 0;
}
![](https://i-blog.csdnimg.cn/blog_migrate/050b01b9dbefac00ad5f7d8c433b260a.png)
4.
请编写程序将简言希的英文名“Jane”加密,加密规律是:用原来的字母后面第一个字母代替原来的字母。例如字母"A"后面第1个字母是"B",用"B"代替"A",以此类推。
请编写程序进行上面的加密过程,并用printf语句输出者4个字符。
#include<stdio.h>
int main()
{
char c1 = 'J', c2 = 'a', c3 = 'n', c4 = 'e';
c1 ++;//注释:还可写成c1+=1/c1=c1+1
c2 ++;
c3 ++;
c4 ++;
printf("加密后的英文名是%c%c%c%c", c1, c2, c3, c4);
return 0;
![](https://i-blog.csdnimg.cn/blog_migrate/d549150d6b6ac3049677e4a70fb8553b.png)
拓展:在编写代码时人们常会加上注释,以便他人理解,有两种注释方式
// 用于单行注释
/*
~~~~~~
*/用于单行或多行注释
关于进制问题
a , 默认为10进制 ,10 ,20。
b,以0开头为8进制,045,021。 %o
c.,以0b开头为2进制,0b11101101。
d,以0x开头为16进制,0x21458adf。%x
用scanf语句输入int、float、double、char型
float型
float a,b;
scanf("%f,%f",&a,&b);
double型
double a,b;
scanf("%lf,%lf",&a,&b);
char型
char a,b;
scanf("%c,%c",&a,&b);
Switch语句
例某课成绩原为百分制,现要将其转成等级,规则是:90分以上为A,80-90分为B、70-79分为C、60-69分为D、60分以下为E。请编一程序,分数由键盘输入,输出等级。
#include<stdio.h>
int main()
{
double fenshu;
printf("请输入分数:");
scanf_s("%lf", &fenshu);//注释在某些编译器里需写成scanf才能运行此为vs示范
switch ((int)(fenshu / 10))
{
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;
}
![](https://i-blog.csdnimg.cn/blog_migrate/5e3a6dd5f1065226d5fae9aff2f21cf7.png)
if语句
if(表达式)
{
...
}
else
{
...
}
写个代码来简单应用一下吧😄
输入一个整数,如果该属大于60,则输出”简美女”;如果该数不大于60,则输出“简大美女”。
#include<stdio.h>
int main()
{
int a;
scanf_s("%d", &a);
if (a > 60)
{
printf("简美女\n");
}
else
{
printf("简大美女\n");
}
return 0;
}
输入两个实数a,b,按数值从小到大的顺序输出这两个数。
#include<stdio.h>
int main()
{
double a, b, t;
scanf_s("%lf,%lf", &a, &b); 或者写成
if (a > b) double a,b;
{ scanf("%lf%lf",&a,&b);
t = a; a>b?printf("%f,%f\n",a,b):printf("%f,%f\n",a,b);
a = b; return 0;
b = t;
}
printf("%f,%f\n", a, b);
return 0;
}
if语句 {-1,x<0
有一函数y={ 0,x=0 请编写一个程序,输入一个整数x时,输出相应的y值
{ 1,x>0
#include<stdio.h>
int main()
{
int x,y;
scanf("%d",&x);
if(x<0) 也可这样写if(X>=0)
y=-1; if(x>0)
else y=1;
{ else
if(x>0) y=0;
y=1; else
else y=-1;
y=0;
}
printf("x=%d,y=%d\n",x,y);
return 0;
}
表达式1?表达式2:表达式3
判断表达式1是否正确,若正确执行表达式2否则执行表达式3
看代码
输入一个字符,判断是否未大写字母,若是则将其转成小写字母,若不是,则不转换
#include<stdio.h>
int main()
{
char ch;
scanf("%c",&ch);
ch=(ch>='A'&&ch<='Z')?(ch+32):ch;
printf("%c\n",ch);
return 0;
}
![](https://i-blog.csdnimg.cn/blog_migrate/b3e5c3460156b0fb45f84962bdeea7e5.png)
for 循环
for( ; ; )
{
printf("该循环会永远执行下去!\n");
}
可以用for循环打印一个九九乘法表,去试试吧!时间关系这就不写了😁
do while 循环
do
{
statement(s);
}while( condition );
打印1+2+3+...+100=
#include<stdio.h>
int main()
{
int i=1;
int sum =0;
do{
sum = sum + i;
i++;
}while (i <= 100);
printf("sum = %d\n",sum);
return 0;
}
结果输出sum=5050
while循环
while(condition)
{
statement(s);
}
#include <stdio.h>
int main ()
{
/* 局部变量定义 */
int a = 10;
/* while 循环执行 */
while( a < 20 )
{
printf("a 的值: %d\n", a);
a++;
}
return 0;
}
当上面的代码被编译和执行时,它会产生下列结果:
a 的值: 10
a 的值: 11
a 的值: 12
a 的值: 13
a 的值: 14
a 的值: 15
a 的值: 16
a 的值: 17
a 的值: 18
a 的值: 19
while循环, 先判断后循环
do while循环,先循环后判断
break; 直接结束本次循环
continue; 结束本次循环进入下个循环
嵌套循环:外部循环一次,内部循环一套
数组
数组的分类,一维数组 和 二维数组
二维数组 int a[ ][ ] 行 列 在定义二维数组时可以没有行数但必须有列数
一维数组的初始化
a.全部初始化
int a[5]={1,2,3,4,5};
代表的意思:a[0]=1;a[1]=2;a[3]=4;....
b.部分初始化
int a[5]={2,4,3};初始化赋值不够后面补0
a[0]=2;a[1]=4;a[2]=3;a[3]=0;a[4]=0;...
注意: 只能省略后面元素,可以不初始化,不能中间的不初始化
#include<stdio.h>
int main()
{
int a[5]={1,2,3,4,5};
int i;
for(i=0;i<5;i++)
{
printf("a[%d]=%d\n",i,a[i]);
}
return 0;
}
![](https://i-blog.csdnimg.cn/blog_migrate/0e2b8de1c439c0696627f3ec63bffbc1.png)
#include<stdio.h>
int main()
{
int a[2][2]={ {1,2} , {4,5} };
int i,j;
for(i=0;i<2;i++)
{
for(j=0;j<2;j++)
{
printf("a[%d][%d]=%d ",i,j,a[i][j]);
}
printf("\n");
}
return 0;
}
![](https://i-blog.csdnimg.cn/blog_migrate/4a6957e836fefb24ccbfc14754aee979.png)
字符数组
char c1[] = { 'c', ' ', 'p', 'r','o', 'g' };
char c2[] = "c prog";
char a[][6] = { "hello" , "word" };
字符数组的引用
用字符串方式赋值比用字符逐个赋值要多占1个字节,用于存放字符串结束标志'\0' ;
上面的数组c2在内存中的实际存放情况为:
' c ' | ' ' | ' p ' | ' r ' | ' o ' | ' g ' | ' \0 ' |
注:'\0'是由C编译系统自动加上去的
sizeof可求数组所占的字节数
#include<stdio.h>
int main()
{
char c1[] = { 'c',' ','p','r','o','n','g'};
char c2[] = "c prong";
printf("sizeof(c1)=%d\n",sizeof(c1));
printf("sizeof(c2)=%d\n",sizeof(c2));
printf("%s\n",c2);
return 0;
}
![](https://i-blog.csdnimg.cn/blog_migrate/306d7d51ca5d5d46a3b91f9da602039c.png)
#include<stdio.h>
int main()
{
char str[15];
printf("please input a str :\n");
scanf("%s",str,15);//这里数组名是地址,不用加取地址符 &
printf("str:%s\n",str);
return 0;
}
![](https://i-blog.csdnimg.cn/blog_migrate/9adff7e28260a0a86c1a58809497e144.png)
学完了数组来看两道题吧
求年月日
打字游戏
函数
函数的概念:函数是一组一起执行一个任务的语句。每个 C 程序都至少有一个函数,即主函数 main() ,所有简单的程序都可以定义其他额外的函数。
函数的分类:
从定义角度分类(即函数是谁实现的)
1.库函数(c库实现的)
2.自定义函数(程序员自己实现的函数)
3.系统调用(操作系统实现的函数)
从参数角度分类
1.有参函数
函数又形参,可以是一个,或者多个,参数的类型随便完全取决于函数的功能
int fun(int a,float b,double c)——>形参
{
}
int max(int x,int y)
{
}
2.无参函数
函数没有参数,在形参列表的位置写个void或什么都不写
int fun(void)
{
}
int fun()
{
}
从返回值角度分类
(1)带返回值的函数
在定义函数的时候,必须带着返回值类型,在函数体里,必须有return如果没有返回值类 型, 默认返回整型。
char fun()//定义了一个返回字符数据的函数
{
char b='a';
return b;
}
(2)没返回值的函数
在定义函数的时候,函数名字前面加void
void fun(形参表)
{
;
;
return;
;
}
在函数里不需要return
如果想结束函数,返回到被调用的地方,return;什么都不返回就可以了
定义函数
C 语言中的函数定义的一般形式如下:
return_type function_name( parameter list )
{
body of the function
}
#include<stdio.h>
int max( int x,int y)
{
int z;
if(x>y)
{
z=x;
}
else
{
z=y;
}
return z;
}
void help(void)
{
printf("*********************\n");
printf("打印帮助信息\n");
printf("*********************\n");
}
int main()
{
int num;
num = max(5,10);
printf("num =%d\n",num);
num =max(11,22);
printf("num=%d\n",num);
help();
return 0;
}
![](https://i-blog.csdnimg.cn/blog_migrate/51e943d9d2165586269018e64b3ad6e7.png)
注:在一个程序中,函数只能定义一次
给函数起名时,尽量见名之意,符合c语言命名规则
函数的声明:
对已经定义的函数,进行说明,函数的声明可以声明多次。
#include<stdio.h>
void fun (void)//被调函数在上,主调函数在下,不需要声明
{
printf("hello word!\n");
}
int main()
{
fun();
return 0;
}
#include<stdio.h>
void fun (void);//直接声明法:将被调用的函数的第一行拷贝过去,后面加分号
int main()
{
fun();
return 0;
}
void fun(void)
{
printf("hello word!\n");
}
define
定义宏用define去定义
宏是在预编译的时候进行替换
不带参宏
#define PI 3.14
在预编译的时候如果代码中出现了PI就用3.14去替换
宏的好处:只要修改宏定义,其他地方在预编译的时候就会重新替换。
注意:宏定义后边不要加分号。
宏定义的作用范围,从定义的地方到本文件的末尾。
如果想在中间终止宏的定义范围
#undef PI//终止PI的作用
2.带参宏
#define S(a,b) a*b
注意带参宏的形参a和b没有类型名,
S(2,4)将来在预处理的时候替换成实参替代字符串的形参,其他字符保留,2*4,就是把S(2,4)变成了2*4
指针
指针的概念:
指针也就是内存地址,指针变量是用来存放内存地址的变量。就像其他变量或常量一样,您必须在使用指针存储其他变量地址之前,对其进行声明。
指针变量的定义:
数据类型 * 指针变量名
int * p;//定义了一个指针变量p
指针变量声明的一般形式为:
type *var_name;
在这里,type 是指针的基类型,它必须是一个有效的 C 数据类型,var_name 是指针变量的名称。用来声明指针的星号 * 与乘法中使用的星号是相同的。但是,在这个语句中,星号是用来指定一个变量是指针。以下是有效的指针声明:
int *ip; /* 一个整型的指针 */
double *dp; /* 一个 double 型的指针 */ (指针的分类,此外还要长整型、函数、结构体指针)
float *fp; /* 一个浮点型的指针 */ 数组指针、指针的指针、通用指针 void*
char *ch; /* 一个字符型的指针 */
在32位系统下任何类型的指针变量都是4个字节大小 64位是8个字节
指针只能存放对应类型的变量的地址编号
关于指针的运算符
& 取地址 、 * 取值
例1:
int a=0x1234abcd;
int *p;//在定义指针变量的时候*代表修饰的意思,修饰p是个指针变量。
p=&a;//把a的地址给p赋值,&是取地址符
p保存了a地地址,也可以说p指向了a
int num;
num=*p
分析:
1.在调用的时候,*代表取值的意思,*p就相当于p指向的变量,即a,
2.故num=*p 和 num=a 的效果是一样的。
所以说num 的值为0x1234abcd。
#include<stdio.h>
int main()
{
int a = 100, b = 200;
int* p_1, * p_2 = &b;
p_1 = &a;
printf("a=%d\n", a);
printf("*p_1=%d\n", *p_1);
printf("b=%d\n", b);
printf("*p_2=%d\n", *p_2);
return 0;
}
![](https://i-blog.csdnimg.cn/blog_migrate/7fc0788641d745f1aa35ad3ccd6e03af.png)
指针和变量的关系
打印程序实现a 和b的值调换
#include<stdio.h>
int main()
{
int* p1, * p2, temp, a, b;
p1 = &a;
p2 = &b;
printf("请输入 a 和 b 的值\n");
scanf_s("%d %d", p1, p2);
temp = *p1;
*p1 = *p2;
*p2 = temp;
printf("a =%d b=%d\n", a, b);
printf("*p1 =%d *p2=%d \n", *p1, *p2);
return 0;
}
![](https://i-blog.csdnimg.cn/blog_migrate/46a46d4a2eef601d81d5ebb259171ce9.png)
指针和数组元素的关系
数组元素的引用方法
方法1:数组名[下标]
int a[5];
a[2]=100;
方法2:指针名加下标
int a[5];
int *p;
p=a;
p[2]=100;//因为p和a等价
补充:C语言规定:数组的名字就是数组的首地址,即第0个元素的地址,是个常量。
注意:p和a的不同,p是指针变量,而a是个常量。可用等号给p赋值,但不能给a赋值
p=&a[3];//正确
a=&a[3];//错误
方法3:通过指针变量运算加取值的方法来引用数组的元素
int a[10];
int *p;
p=a;
*(p+2)=100;//也是可以的,相当于a[2]=100
解释:p是第0个元素的地址,p+2是a[2]这个元素的地址。
对第2个元素的地址取值,即a[2]
方法4:通过数组名+取值的方法引用数组的元素
int a[10];
*(a+2)=100;//也是可以的,相当于a[2]=100;
注意:a+2是a[2]的地址。这个地方并没有给a赋值。
通过代码来熟悉一下吧(vs里*86是32位系统,*64是64 位系统)
#include<stdio.h>
int main()
{
int a[5] = { 0,1,2,3,4 };
int* p;
p = a;
printf("a[2]=%d\n", a[2]);
printf("p[2]=%d\n", p[2]);
printf("*(p+2)=%d\n", *(p + 2));
printf("*(a+2)=%d\n", *(a + 2));
printf("p=%p\n", p);
printf("p+2=%p\n", p + 2);
return 0;
}
![](https://i-blog.csdnimg.cn/blog_migrate/2addb5a6f35cb6bdde9a9c0bf810dc0e.png)
指针的运算
1、指针可以加一个整数,往下指向几个它指向的变量,结果还是个地址
2、两个相同类型指针可以比较大小
3、两个相同类型的指针可以做减法
4、两个相同类型的指针可以相互赋值
指针数组
1.指针数组的概念:指针数组本身是个数组,是个指针数组,数组中有若干个相同类型指针变量,这个数组被称为指针数组
2.指针数组的定义方法:
类型说明符 * 数组名 [元素个数];
int *p[5];//定义了一个整型的指针数组p,有5个元素p[0]~p[5],
每个元素都是int*类型的变量
int a;
p[0]=&a;
int b[10];
p[1]=&b[5];
#include<stdio.h>
int main()
{
int* p[5];
int a = 100;
int b[10] = { 1,2,3,4,5,6,7,8,9,0 };
printf("sizeof(p)=%d\n", sizeof(p));
p[0] = &a;
printf("p[0]=%p\n", p[0]);
printf("&a=%p\n", &a);
printf("*p[0]=%d\n", *p[0]);
p[1]= &b[2];
printf("*p[1]=%d\n", *p[1]);
return 0;
}
![](https://i-blog.csdnimg.cn/blog_migrate/e71764fc59aeb164e582ebdd85011a0a.png)
#include<stdio.h>
int main(int argc, const char* argv[])
{
const char* name[5] = { "hello","China","beijing","project","Computer" };
int i;
for (i = 0; i < 5; i++)
{
printf("%s\n", name[i]);
}
return 0;
}
![](https://i-blog.csdnimg.cn/blog_migrate/74b7c8b29daa81834fc82182bb489bc0.png)
指针的指针
int a=0x12345678;
假如:a的地址是 0x00002000
int *p;
p=&a;
则p中存放的是a的地址编号即 0x00002000
因为p也占4个自己内存,也有它自己的地址编号,及指针变量的地址,即指针的指针。
假如:指针变量p的地址编号是0x00003000,这个地址编号就是指针的地址
我们定义一个变量存放p的地址编号,这个变量就是指针的指针
int **q;
q=&p;//q保存了p的地址,也可以说q指向了p
则q里存放的就是0x00003000
#include<stdio.h>
int main(int argc, char* argv[])
{
int a = 0x12345678;
int* p;
int** q;
int*** m;
p = &a;
printf("&a=%p\n", &a);
printf("p=%p\n", p);
q = &p;
printf("&p=%p\n", &p);
printf("q=%p\n", q);
m = &q;
printf("&q=%p\n", &q);
printf("m=%p\n", m);
printf("*p=%x\n", *p);
printf("**q=%x\n", **q);
printf("***m=%x\n", ***m);
return 0;
}
![](https://i-blog.csdnimg.cn/blog_migrate/5e6e825e949902c0395188f97dcfb3ae.png)
字符串的概念及其存储形式
字符串的概念:
字符串就是以'\0'结尾的若干个字符的集合,比如”helloword“。
字符串的地址,是第一个字符的地址。如:字符串”helloword"的地址,其实是字符串中字符'h'的地址。我们可以定义一个字符指针变量保存字符串的地址,比如: char *s="helloword";
字符串的存储形式:数组、文字常量区、堆
1,字符串存放在数组中
char string[100]="I love C!"
2.文字常量区
char *str="I love C!"
3.堆区
char *str=(char*)malloc(10);动态申请了10个字节的存储空间
字符串的可修改性:存放在数组和堆中可修改,文字常量中不可修改(注数组没有被const修饰
初始化:
1.字符数组初始化:
char*buf_aver[20]="hello world";
2.指针指向文字常量区,初始化:
char*buf_point="hello world";
3、指针指向堆区,堆区存放字符串。
不能初始化,只能先给指针赋值,让指针指向堆区,再使用strcpy、scanf等方法把字符串拷贝到堆区。char*buf_heap;
buf_heap=(char*)malloc(15);
strcpy(buf_heap,"helloworld");
scanf(“%s”,buf_heap);
使用时赋值
字符数组:使用scanf或者strcpy
charbuf[20]=”hello world”
buf="hello kitty"; 错误,因为字符数组的名字是个常量,不能用等号给常量赋值。strcpy(buf,"hello kitty"); 正确,数组中的内容是可以修改的
scanf("%s",buf); 正确,数组中的内容是可以修改的
2.指针指向文字常量区
char*buf_point=“hello world”;
1)buf_point="hello kitty"; 正确,buf_point指向另一个字符串
2)strcpy(buf_point,"hello kitty"); 错误,这种情况,buf_point指向的是文字常量区,内容只读。
当指针指向文字常量区的时候,不能通过指针修改文字常量区的内容。
3.指针指向堆区,堆区存放字符串
char*buf_heap;buf_heap=(char*)malloc(15);
strcpy(buf_heap,"helloworld");
scanf(“%s”,buf_heap);
字符串和指针总结:
1、指针可以指向文字常量区
1)指针指向的文字常量区的内容不可以修改
2)指针的指向可以改变,即可以给指针变量重新赋值,指针变量指向别的地方。
2、指针可以指向堆区
1)指针指向的堆区的内容可以修改。
2)指针的指向可以改变,即可以给指针变量重新赋值,指针变量指向别的地方。
3、指针也可以指向数组(非const修饰)
例:charbuf[20]="hello world";
char*str=buf;
这种情况下
1.可以修改buf数组的内容。
2.可以通过str修改str指向的内存的内容,即数组buf的内容
3.不能给buf赋值buf=“hello kitty”;错误的。
4.可以给str赋值,及str指向别处。str=“hello kitty”
数组指针
1、二维数组
二维数组,有行,有列。二维数组可以看成有多个一维数组构成的,是多个一维数组的集合,可以认为二维数组的每一个元素是一个一维数组。
例:
int a[3][5];
定义了一个3行5列的一维数组。
可以认为二维数组a由3个一维数组构成,每个元素是一个一维数组。
回顾:
数组的名字是数组的首地址,是第0个元素的地址,是个常量,数组名字加1指向下个元素
二维数组a中,a+1指向下个元素,即下一个一维数组,即下一行。
2.数组指针的概念:
本身是个指针,指向一个数组,加1跳一个数组,即指向下个数组。
3.数组指针的定义方法:
指向的数组的类型(*指针变量名)[ 指向的数组的元素的个数]
int (*p)[5];// 定义了一个数组指针变量p,p指向的是整型的有5个元素的数组
p+1往下指5个整型,跳过一个有5个整型元素的数组