创建一个后缀名为.c的源文件,在此文件中写第一个C语言程序
第一个C语言程序
#include
int main(void)
{
printf("hello world");
getchar();
return 0;
}
#include是C语言的预处理指令,用于引入
getchar();库函数,程序需要等待键盘输入回车键才结束
字面量或者说常量,指的是有固定的值的数据。在程序中,常量只能被引用,而不能被更改
a. 整型
整型,或者说整数类型。在printf()函数中,不能直接输出,需要使用%d来占位替换输出
整型有long,int,short,char
%d表示“十进制整数”形式
#include
int main(void)
{
printf("money is %d", 300);
getchar();
}
b. 浮点数
浮点数,或者说小数类型。在printf()函数中,不能直接输出,需要使用%f来占位替换输出
默认情况下,输出浮点数保留小数点后6位数字。%.2f,保留两位小数
#include
int main(void)
{
printf("money is %f", 3.1);
printf("money is %f", -3.123);
getchar();
}
浮点数有:单精度浮点型float,双精度浮点型double。float赋值字面量时,需要以f结尾
输出double要用%lf,也可以用%f,但是不推荐
#include
int main(void)
{
float f = 3.14f;
double d = 3.14;
printf("money is %f", f);
printf("money is %lf", d);
getchar();
return 0;
}
VS2012中执行的是C89标准,变量必须在所有其他代码之前声明
c. 字符型
单引号括起来的字符被称为字符型,注意只能是单个字符被括起来
在printf()函数中,不能直接输出,需要使用%c来占位替换输出
转义字符。比如\n表示换行符,\”代表双引号字符本身,此时不再具有特殊的意义
#include
int main(void)
{
printf("mon\ney");//输出mon (换行) ney
printf("mon\\ney");//输出mon\\ney
getchar();
return 0;
}
d. 字符串
双引号括起来的若干字符被称为字符串,可以直接在printf()函数中输出
字符串的占位符用%s来代替
在C语言中,是没有字符串类型的,字符串本质上是由单个的字符构成
printf()函数中可以使用多个占位符,只要和参数的类型、个数能够对的上即可
一个合法的变量由3部分组成,变量类型,变量名,变量值
变量必须定义才能使用;所有变量要声明在方法的最开始;变量必须初始化之后才能使用;变量不能重名
在c语言中,变量定义的位置可以分为3种
a. 标识符
对变量,函数,数组等命名的字符序列被称为标识符。标识符有以下规定:只能由英文字母,数字,下划线组成;首字符必须是字母或者下划线;大小写敏感;不能全部是关键字
b. 关键字
C语言中,具有特殊用途的单词被称为关键字。比如int,return,break,if,void等
c. 注释
//单行注释
/* */多行注释
变量的赋值方式
每行定义与赋值
int i = 1;
int j = 2;
int k = 3;
一行定义
int i = 1, j = 2, int k;
k = 3;
两个整数相除结果为整数,两个浮点数相除结果为浮点数,如果两个操作数中有一个是浮点数,相除结果为浮点数
#include
int main(void)
{
int i = 1;
int j = 3;
int a = i/j;
printf("a = %d", a);
getchar();
}
//a的输出结果为0
#include
int main(void)
{
float x = 1;
float y = 3;
float z = x/y;
printf("money is %f", z);
getchar();
}
//a的输出结果为0.333333
#include
int main(void)
{
float x = 1.0f/3;
int y = 1/3;
printf("x= %f", x);//0.333333
printf("y= %d", y);//0
getchar();
}
关系表达式
关系表达式的运算结果只有两种:0或者1。关系表达式的结果值是整数类型,c语言是没有boolean类型的值的
#include
int main(void)
{
int x = 3;
int y = 5;
printf("%d\n", x>y);//输出0
printf("%d", x!=y);//输出1
getchar();
}
逻辑运算符
C语言提供的逻辑运算符有以下三种
&& 逻辑与
||逻辑或
!逻辑非(取反)
逻辑与和逻辑或都是双目运算符,需要两个操作数才能进行运算。逻辑非是单目运算符,只需要一个操作数就能运算
条件运算符
条件运算符一般的使用形式为:表达式1?表达式2:表达式3
如果表达式1为真,则选择表达式2,否则选择表达式3
sizeof运算符
sizeof,用于计算变量、字面量、类型所占字节数。该运算符是C语言中唯一一个使用单词作为运算符的
sizeof(类型/字面量/变量)
#include
int main(void)
{
int x = 3;
float f = 3.14f;
double d = 3.14;
printf("%d\n", sizeof(x));//4
printf("%d\n", sizeof(f));//4
printf("%d\n", sizeof(d));//8
printf("%d\n", sizeof(int));//4
printf("%d\n", sizeof(3));//4
getchar();
}
1.赋值语句
2.函数调用语句
3.空语句
4.复合语句。使用{}将多行语句括起来就可以成为复合语句,复合语句中还可以嵌套复合语句
if语句
当if语句后面指定的语句只有一行时,可以不写{}。因为;才代表一行语句的结束
#include
int main(void)
{
int x = 3;
if(x > 1) printf("%d\n", sizeof(3));//输出4
getchar();
}
if语句中的判断,把数值写在变量前面的好处是,可以通过编译来发现错误
//无论a的值为多少,总是会输出no ok,因为a=0是赋值语句,a始终为0
#include
int main(void)
{
int a = 3;
if(a=0){//实际想写a==0
printf("ok");
}else {
printf("no ok");
}
getchar();
}
//此时0=a编译报错,能够发现错误。0==a则没有问题
#include
int main(void)
{
int a = 3;
if(0=a){//编译报错
printf("ok");
}else {
printf("no ok");
}
getchar();
}
switch语句
switch后面跟一个语句块即可,语句块中包含多个以case开头,break结尾的语句
#include
int main(void)
{
int a = 3;
switch (a)//switch中的表达式的运算结果必须是整数类型,long、short、char、int等
{
case 1://case后面只能跟字面量表达式,运算结果也必须是整数类型
{//大括号可有可无
printf("test1");
break;
}
case 2:
printf("test2");
break;
default:
printf("test3");
break;
}
getchar();
}
break非必需,但是如果没有beak,case不会退出,会继续向下执行,直到遇到break为止
#include
int main(void)
{
int a = 1;
switch (a)
{
case 1:
printf("test1");
case 2:
printf("test2");
break;
default:
printf("test3");
break;
}
getchar();
}
输出
test1test2
定义无参函数
类型名 函数名()
{
语句;
}
//或者
类型名 函数名(void)
{
语句;
}
定义有参函数
类型名 函数名(变量类型 变量值)
{
语句;
}
自定义函数一般要放在调用它的函数之前,如果要放在调用它的函数之后,就需要添加函数声明,把函数的声明放到调用之前,函数的实现可以写到调用此函数的函数的后面
为什么会报错? 因为编译器发现一个不认识的函数调用,不知道该函数的返回类型,就假设为int类型,等后面编译的时候编译器看到实际的函数,它认为有两个同名的函数,一个是文件中的函数,一个是编译器假设返回int的函数
//这样写编译是会报错的
#include
int main(void)
{
fun(1);
getchar();
}
void fun(int i){
printf("%d", i);
}
#include
//可以先声明函数,函数的实现可以不写
void fun(int i);
int main(void)
{
fun(1);
getchar();
}
//函数的实现可以写到调用此函数的函数的后面
void fun(int i){
printf("%d", i);
}
疑问,为什么这样就可以,不会报错,可能和版本有关,最好是先声明函数,再写实现
并且int类型的函数,不需要返回值吗?没有返回值的时候,int类型的函数默认返回1
#include
//此时fun函数能够在main函数之后被定义和实现
int main(void)
{
int i = fun(1);
getchar();
}
int fun(int i){
printf("%d", i);
}
一维数组的定义方式为:数据类型 数组名[字面量表达式],比如int arr[10]。
数组长度可以是字面量或字面量表达式(比如int arr[5+5]也可以),但是不能是变量或变量表达式
一维数组的初始化方式可以为int arr[5]={1,2,3,4,5},这种全部初始化的方式
也可以使用部分初始化的方式
#include
void main()
{
//初始化部分值,其余未被初始化的数组元素会被初始化为0
int arr[4]={1,2};
printf("%d\n", arr[0]);
printf("%d\n", arr[1]);
printf("%d\n", arr[2]);
printf("%d\n", arr[3]);
getchar();
}
/*
输出
1
2
0
0
*/
由部分初始化的方式,有种取巧的方式,将一维数组全部初始化为0
int arr[5]={0};
定义数组时,可以不指定数组长度,,编译器会根据初始化列表计算出数组长度
比如:int a[5]={1,2,3,4,5};
可以写为:
int a[ ]={1,2,3,4,5};
[ ]中虽然没有指定数组长度,但系统会根据{ }中数据的个数确定数组 a 长度为 5
sizeof(数组名)就是数组的字节数,所以要获取数组长度,可以:sizeof(数组名)/sizeof(数组类型),或者sizeof(数组名)/sizeof(数组中任一元素)
sizeof(数组名)/sizeof(数组中任一元素)可以自动适应数组的类型,修改数组类型,计算结果也不会有问题
在C语言中,没有字符串类型的数据类型,用的是字符数组来存储字符串
为了区分普通字符数组和字符串,C语言规定以字符’\0’作为字符串结束标志。
char c[] ={'a','b','c'};//普通的字符数组,这个数组的长度为3
char c[] ={'a','b','c','\0'};//字符串,这个数组的长度为4,'\0'也占一个长度
没有’\0’的话,printf()函数输出的不会是字符串本来的样子。和数据在内存中的分布有关,会读到不应该读取到的内存
#include
void main()
{
char c[] = {'c','d','\0'};
//char c[] = "cd";
printf("%s", c);
getchar();
}
简化写法,此时编译器会自动在字符串末尾添加’\0’
char c[] = "test";
如果把’\0’放在数组中间的位置,那printf()函数只会输出数组中’\0’前面的元素,数组本身的长度并没有变化
#include
void main()
{
char c[] = {'c','d','\0','f','g'};//只输出cd
char c1[] = "cd\0fg";//只输出cd
printf("%s\n", c);
printf("%s", c1);
getchar();
}
在C语言中,字符串的有效长度指的是字符串中’\0’之前的字符个数,不包括’\0’,比如
char c1[ ]={‘r’,‘u’,‘p’,‘e’,‘n’,‘g’,’\0’};
c1 字符串有效长度为 6,不包括最后的’\0’。
char c2[ ]=“rupeng”;
c2 字符串有效长度为 6,不包括系统自动添加的’\0’。
char c3[ ]={‘r’,‘u’,‘p’,‘e’,‘n’,‘g’};
c3 字符串有效长度就不一定是6,会读到不应该读取到的内存。
#include
#include
void main()
{
char c[] = {'c','d','f','g'};
char c1[] = "cdfg";
printf("%s\n", strlen(c));//输出4
printf("%s", strlen(c1));//输出4
getchar();
}
需要注意的是, strlen 函数内部只会计算字符串中’\0’之前的字符个数, ’\0’及之后的字符将被忽略。
#include
#include
void main
{
char c[] = "ab\0cd";
printf("%d\n", strlen(c));//输出2
printf("%d\n", sizeof(c)/sizeof(c[0]));//输出6
getchar();
}
在程序的默认设置中, 1 个中文字符占 2 个字节。
#include
#include
void main()
{
char c[] = "何宗玮";
printf("%d\n", strlen(c));//输出6
printf("%d\n", sizeof(c)/sizeof(c[0]));//输出7,包括最后的\0
getchar();
}
%c占位输出,会输出对应的字符;%d占位输出,会输出对应的ASCII码
#include
#include
void main()
{
char c[] = "abcd";
printf("%c\n", c[0]);//输出a
printf("%d\n", c[0]);//输出97,ASCII码
getchar();
}
#include
#include
void main()
{
printf("%d\n", 0);//输出0
printf("%d\n", '\0');//输出0,猜想是\起到了转义的作用
printf("%d\n", '0');//输出48
getchar();
}
字符串转为整型
头文件为include
#include
#include
void main()
{
int i = 123;
char c[] = {'1','2','3'};
int i1 = atoi(c);
printf("%d", i == i1);
getchar();
}
整型转字符串
函数原型char *itoa( int value, char* string,int radix);
value:要转换的整数。
string:要写入转换结果的目标字符数组。要确保目标字符串数组的长度要够用(只能多不能少),如果整数的位数是4位,那目标字符串数组的长度可以为5,因为要为最后的’\0’留地方。
radix:转换的进制,可以是 10 进制、 16 进制等。
#include
#include
void main()
{
int i = 1234;
char c[5] = {0};
itoa(i, c, 10);
printf("%s", c);//输出1234
getchar();
}
sprintf 字符串格式化函数
函数原型
int sprintf( char *buffer, const char *format, [ argument] … );
参数列表
buffer:保存格式化字符串的目标字符缓冲区(或者说目标数组)。 sprintf 会自动在最后加上’\0’
format:格式化后的字符串。 printf 里可以用的占位符, sprintf 里都能用
[argument]…:参数列表
#include
int main(void)
{
char buffer[24]={0};
sprintf(buffer,"name=%s,age=%d","sakura",20);
printf("%s",buffer);
getchar();
return 0;
}