本文已参与「新人创作礼」活动,一起开启掘金创作之路。
C语言基础
4、控制语句
4.1 if
if-else语句
if语句概述
if (表达式)
语句块1
else
语句块2
常见形式:
1.简化形式
if(表达式) 语句块
例如: if(x>y)printf(“%d”, x);
2.阶梯形式
if(表达式1) 语句块1
else if(表达式2) 语句块2
else if(表达式3) 语句块3
else if(表达式4) 语句块4
...
else 语句块n
注意:
语句块:当有若干条语句时,必须用{…}括起来。
表达式:
一般情况下为逻辑表达式或关系表达式
如:if(a= =b && x= =y) printf(“a=b,x=y”);
也可以是任意类型(包括整型、实型、字符型、指针类型)
如:if(‘a’) printf(“%d”,’a’);
请区分if(x=1)与if(x= =1)的不同。
3.嵌套形式 if() if() 语句块1 else 语句块2 else if() 语句块3 else 语句块4
if语句的嵌套
else总是与它上面的最近的if配对,与书写格式无关。
要实行强行的配对关系可以利用{ }
如:if()
{if() 语句块1}
else 语句块2
例:
#include <stdio.h>
int main()
{
float a = 4,b = 5,c = 2,t;
if(a>b) {t=a;a=b;b=t;}
if(a>c) {t=a;a=c;c=t;}
if(b>c) {t=b;b=c;c=t;}
printf(“%5.2f,%5.2f,%5.2f”,a,b,c);
return 0;
}
4.2 switch
switch语句的基本形式
switch case分支结构
switch(变量/表达式){
case 1:
执行语句;
break;
case 2:
执行语句;
break;
case n:
执行语句;
break;
default:
执行语句;
//break;可以省略不写
}
switch语句的使用: ==每个常量表达式的值必须各不相同,否则将会出现矛盾==。 当表达式的值与case后面的常量表达式值相等时,就执行此case后面的语句。 ==switch中的表达式可以是整型、字符型表达式或枚举==。 case 常量:只起语句标号的作用。 switch语句的使用: break语句用于强行跳出switch体,一般每个case后面应有一个break语句,==default分支后的break可以省略==。 ==多个case可以执行一组语句==。 每个case执行完后需要执行break退出分支结构,否则会从当前执行的分支一直向下执行到break或整个分支的结尾才能结束;
4.3 while/goto
循环结构程序 goto语句构成循环 while构成循环 do-while循环 for循环 1.goto语句
goto语句构成循环
int fun(inta)
{ intresult = 0;
char*buffer = kmalloc(SIZE);
if(buffer == NULL)
return-ENOMEM;
if(condition1) {
while(loop1) {
...
}
result = 1;
goto out;
}
out:
kfree(buffer);
return result;
}
while 当条件表达式成立的时候,执行循环体,直到表达式不成立,结束循环体的执行,开始执行后面内容
基本形式
while (表达式) {
循环体;
}
int i = 1;
while(i<5){
printf("%d\n",i);
i++;
}
大括号里面的内容是循环重复执行的代码
循环变量初始化:一般放在循环体外部进行初始化
循环退出条件:条件判断的表达式
循环变量的修改:无限趋近于退出条件
while(1);//死循环
do-while
基本形式
do {
循环体;
}while(表达式);
注意分号不能省略
执行逻辑:先执行一次循环体,然后进入条件表达式,判断是否成立,如果成立继续执行循环体,不成立退出循环
循环变量初始化:do语句前
循环退出条件:while后的条件表达式中
循环变量修改:放在循环体中
do{
}while(1); while(!0);
//死循环
4.4 for
一般形式 for(expression1; expression2; expression3) { statements;} 执行过程 1.先求解表达式1; 2.求解表达式2,若为真,则执行循环体,然后执行步骤3;若为假,则执行步骤5; 3.求解表达式3; 4.转回执行步骤2; 5.执行for下面的语句。
for语句构成循环
例如:
for(i=1;i<=100;i++)
{
sum=sum+i;
}
for语句构成循环
表达式1可省略,但循环之前应给循环变量赋值;
表达式2可省略,将陷入死循环
表达式3可省略,但在循环体中增加使循环变量值改变的语句
for(;;){
循环体
}//死循环
4.5 循环辅助语句
break 用于从循环体内跳出循环体,即提前结束循环。 break只能用在循环语句和switch语句中。 for(r=1;r<=10;r++){ area=pirr; if(area>100) break; printf(“%f”,area); } gcc -std=c99 filename
5、数组和字符串
1.构造数据类型之一 2.数组是具有一定顺序关系的若干个变量的集合,组成数组的各个变量称为数组的元素 3.数组中各元素的数据类型要求相同,用数组名和下标确定。数组可以是一维的,也可以是多维的
5.1一维数组
所谓一维数组是指只有一个下标的数组。它在计算机的内存中是连续存储的。
C语言中,一维数组的说明一般形式如下:
<存储类型> <数据类型 > <数组名>[<表达式>]
对地址的访问用%p
#include <stdio.h>
int main(int argc, char *argv[])
{
//int i = 6, a[i];
int a[6] = {1, 4, 5}, i, n;
int b[] = {3, 4, 7, 8, 1, 0};
//求b数组中的元素个数
n = sizeof(b) / sizeof(int);
for (i = 0; i < n; i++)
//printf("%p", &a[i]);
printf("%p\n", &b[i]);
//a = a + 1; 错误
//地址常量不能进行加减
printf("%p\n", a);
printf("%d\n", sizeof(a));
--->24
return 0;
}
==注意事项== C语言对数组不作越界检查,使用时要注意 int a[5]; a[5] = 10 × 越界了 关于用变量定义数组维数 int i = 15; int a[i]
5.1.1 一维数组的引用
1.数组必须先定义,后使用 2.只能逐个引用数组元素,不能一次引用整个3.数组 4.数组元素表示形式:数组名[下标] 其中:下标可以是常量或整型表达式
int a[10];
printf(“%d”, a); (×)
for(j=0;j<10;j++)
printf(“%d\t”, a[j]); (√)
5.1.2 一维数组的初始化
1.初始化方式:在定义数组时,为数组元素赋初值 int a[5]={1,2,3,4,5}; 2.说明 A.数组不初始化,其元素值为随机数 B.对static数组元素不赋初值,系统会自动赋以0值
static int a[5];
等价于:a[0]=0; a[1]=0; a[2]=0; a[3]=0; a[4]=0;
C.只给部分数组元素赋初值
int a[5]={6,2,3};
等价于:a[0]=6; a[1]=2;a[2]=3; a[3]=0; a[4]=0;
int a[3]={6,2,3,5,1}; (×)
//全部初始化
int a[]={1,2,3,4,5,6};//编译系统根据初值个数确定数组维数
5.2 二维数组
二维数组的定义 定义方式:==(声明时列数不能省略,行数可以)== 数据类型 数组名[常量表达式][常量表达式]; 元素个数=行数*列数
例int a[3][4];
float b[2][5];
int c[2][3][4];
数组元素的存放顺序
原因:内存是一维的
二维数组:按行序优先
a[0],a[1],a[2]为一维数组名又叫行名
==一维数组名不可以进行改变,是一个地址常量,为该行元素的首地址,且sizeof(a[0])为a[0]这一行元素占用的内存的空间==
a+3是可以的,但是a=a+3 错误
5.2.1 二维数组元素的引用
形式:数组名[下标][下标] 二维数组元素的初始化 第一种:分行初始化 第二种:按元素排列顺序初始化
//全部初始化
int a[2][3]={{1,2,3},{4,5,6}};
//部分初始化
int a[2][3]={{1,2},{4}};--->1,2,0
4,0,0
int a[2][3]={{1,2}};--->1,2,0
0,0,0
//行数省略部分初始化
int a[][3]={{1},{4,5}};--->1,0,0
4,5,0
int a[3][3]={{1},{4,5}};--->1,0,0
4,5,0
0,0,0
int a[3][3]={1,2,3,4};报警--->1,2,3
4,0,0
0,0,0
int a[3][]={{1},{2,3},{4}}; 错误
5.2.2 多维数组
打印杨辉三角的前十行
1
1 1
1 2 1
1 3 3 1
1 4 6 4 1
1 5 10 10 5 1
....
#include <stdio.h>
int main(int argc, char *argv[])
{
int a[10][10] = {{0}};
int i, j;
for (i = 0; i < 10; i++) {
a[i][0] = 1;
for (j = 1; j <= i; j++)
a[i][j] = a[i-1][j-1] + a[i-1][j];
}
for (i = 0; i < 10; i++) {
for (j = 0; j <= i; j++)
//往右边补8个空格
printf("%-8d ", a[i][j]);
putchar('\n');
}
return 0;
}
有一个2×3的矩阵,要求输出其中值最大的元素的值,以及它的行号和列号。
#include <stdio.h>
int main(int argc, char *argv[])
{
int a[2][3] = {{2, 5, 8}, {21, 56, 9}};
int i, j, row, column;
row = column = 0;
for (i = 0; i < 2; i++) {
for (j = 0; j < 3; j++) {
if (a[row][column] < a[i][j]) {
row = i;
column = j;
}
}
}
for (i = 0; i < 2; i++) {
for (j = 0; j < 3; j++)
printf("%5d ", a[i][j]);
putchar('\n');
}
printf("max=%d %d %d\n", a[row][column], row, column);
return 0;
}
5.3字符数组和字符串
5.3.1 字符数组
字符数组是元素的数据类型为字符类型的数组 char c[10], ch[3][4]; 字符数组的初始化 1.逐个字符赋值
例
//以下数组叫字符数组
char ch[5]={'H','e','l','l','o'};
//以下数组叫字符数组又叫字符串
char ch[5]={'B','o','y'};
--->B o y \0 \0
2.用字符串常量
例 char ch[6]={“Hello”};
char ch[6]=“Hello”;
char ch[]=“Hello”;
#include <stdio.h>
int main(int argc, char *argv[])
{
char arr1[] = {'a', 'b', 'c'};
char arr2[6] = {'d', 'e', 'f'};
printf("arr1:%s %p\n", arr1, &arr1[2]);
printf("arr2:%s %p\n", arr2, arr2);
return 0;
}
---->输出结果为:abcdef
def
#include <stdio.h>
int main(int argc, char *argv[])
{
char fruit[][20] = {"banana", "apple", "strawmerry", "watermelen"};
int i, j, n, m;
//计算二维数组的行和列
n = sizeof(fruit) / sizeof(fruit[0]);
m = sizeof(fruit[0]) / sizeof(char);
for (i = 0; i < n; i++) {
printf("%s\n",fruit[i]);
// for (j = 0; j < m; j++)
// putchar(fruit[i][j]);
//putchar('\n');
}
return 0;
}
5.3.2 字符串
C语言中无字符串变量,用字符数组处理字符串 字符串结束标志:‘\0’
例 “hello”共5个字符,在内存占6个字节,字符串长度5
输入一个字符串,然后将其逆序输出 解法一:
#include <stdio.h>
#include <string.h>
#define N 20
int main(int argc, char *argv[])
{
char arr[N] = {0};
int i, n;
printf("Please input a string:");
gets(arr);
n = strlen(arr);
for (i = n-1; i >= 0; i--)
putchar(arr[i]);
putchar('\n');
return 0;
}
解法二:
#include <stdio.h>
#include <string.h>
#define N 20
int main(int argc, char *argv[])
{
char arr[N] = {0};
int i, j, n, ch;
printf("Please input a string:");
gets(arr);
n = strlen(arr);
i = 0;
j = n-1;
while (i < j) {
ch = arr[i];
arr[i] = arr[j];
arr[j] = ch;
i++;
j--;
}
puts(arr);
return 0;
}
C库中实现了很多字符串处理函数 #include <string.h> 几个常见的字符串处理函数 求字符串长度的函数strlen 字符串拷贝函数strcpy 字符串连接函数strcat 字符串比较函数strcmp
5.3.3 strlen
strlen算的是有效长度,不含\0;sizeof是计算占用的总的空间(含有\0) 字符串长度函数strlen 格式:strlen(字符数组) 功能:计算字符串长度 返值:==返回字符串实际长度,不包括‘\0’在内== \xhh表示十六进制数代表的符号 \ddd表示8进制的
例:对于以下字符串,strlen(s)的值为:
char s[10]={‘A’,'0',‘B’,‘C’,‘\0’,‘D’};
char s[10]={‘A’,‘\0’,‘B’,‘C’,‘\0’,‘D’};
char s[ ]=“\t\v\\\0will\n”;
char s[ ]=“\x69\141\n”;
char s[ ]=“\tab\ncnvd\\e”;
答案:4 1 3 3 9
5.3.4 strcpy
字符串拷贝函数strcpy 格式:strcpy(字符数组1,字符串2) 功能:将字符串2,拷贝到字符数组1中去 返值:返回字符数组1的首地址 说明: 1.字符数组1必须足够大 2.拷贝时‘\0’一同拷贝
#include <stdio.h>
#include <string.h>
#define N 30
int main(int argc, char *argv[])
{
char src[] = "makeru";
char dest[N];
int i, n;
//strcpy(dest, src);
i = 0;
n = strlen(src);
printf("n=%d\n", n);
while ( i <= n) {
dest[i] = src[i];
i++;
}
puts(src);
puts(dest);
return 0;
}
5.3.5 strcat
字符串连接函数strcat 格式:strcat(字符数组1,字符数组2) 功能:把字符数组2连到字符数组1后面 返值:返回字符数组1的首地址 说明: 1.字符数组1必须足够大 2.连接前,两串均以‘\0’结束;连接后,串1的 ‘\0’取消,新串最后加‘\0’
#include <string.h>
#include <stdio.h>
int main()
{
char destination[25];
char blank[] = " ", c[]= "C++",turbo[] = "Turbo";
strcpy(destination, turbo);
strcat(destination, blank);
strcat(destination, c);
printf("%s\n", destination);
return 0;
}
----->Turbo C++
#include <stdio.h>
#include <string.h>
#define N 100
int main(int argc, char *argv[])
{
char dest[] = {'a', 'b', 'c'};
char src[N] = ".com.cn";
strcat(dest, src);
printf("dest:%p src:%p\n", dest, src);
puts(src);
puts(dest);
return 0;
}
----->.com.cn
abc.com.cn.com.cn
5.3.6 strcmp
字符串比较函数strcmp
格 式:strcmp(字符串1,字符串2)
功 能:比较两个字符串
比较规则:对两串从左向右逐个字符比较
(ASCII码),直到遇到不同字符或‘\0’为止
返 值:返回int型整数
a. 若字符串1< 字符串2, 返回负整数
b. 若字符串1> 字符串2, 返回正整数
c. 若字符串1== 字符串2, 返回零
5.3.7其他字符串函数
strncpy(p, p1, n) 复制指定长度字符串
#include <stdio.h>
#include <string.h>
#define N 30
int main(int argc, char *argv[])
{
char src[] = "makeru";
char dest[N] = ".com.cn";
strncpy(dest, src, 4);
puts(src);
puts(dest);
return 0;
}
---->makeru
make.cn
strncat(p, p1, n) 附加指定长度字符串
#include <stdio.h>
#include <string.h>
#define N 30
int main(int argc, char *argv[])
{
char src[] = "makeru";
char dest[N] = ".com.cn";
strncat(dest, src, 4);
puts(src);
puts(dest);
return 0;
}
---->makeru
.com.cnmake
strcasecmp忽略大小写比较字符串 strncmp(p, p1, n) 比较指定长度字符串
#include <stdio.h>
#include <string.h>
#define N 30
int main(int argc, char *argv[])
{
char s1[] = "QUIT";
char s2[] = "quit";
printf("%d\n", strncmp(s1, s2, 4));
printf("%d\n", strcasecmp(s1, s2));
return 0;
}
strchr(p, c) 在字符串中查找指定字符 //p为字符串,c为要查找的字符,返回值为第一次出现的c在字符串中的位置 strrchr(p,c)返回最后一次出现的c的位置
#include <stdio.h>
#include <string.h>
int main(int argc, char *argv[])
{
char s1[] = "abas$f$sf";
int ch;
ch = '$';
//printf("%p %p \n", s1, strchr(s1, ch));
//printf("%p %p \n", s1, strrchr(s1, ch));
printf("%d\n", strchr(s1, ch)-s1);
printf("%d \n", strrchr(s1, ch)-s1);
return 0;
}
strstr(p, p1) 查找字符串
#include <stdio.h>
#include <string.h>
int main(int argc, char *argv[])
{
char s[] = "how are you";
char subs[] = "are";
printf("%d\n", strstr(s, subs)-s);
return 0;
}
---->4
isalpha() 检查是否为字母字符 isupper() 检查是否为大写字母字符 islower() 检查是否为小写字母字符 isdigit() 检查是否为数字
#include <stdio.h>
#include <ctype.h>
int main(int argc, char *argv[])
{
int ch;
while ((ch = getchar()) != EOF) {
if (isalpha(ch)) {
if (isupper(ch))
printf("Upper:%c\n", ch);
if (islower(ch))
printf("Lower:%c\n", ch);
}
if (isdigit(ch))
printf("Digit:%d %c\n", ch-'0', ch);
putchar(ch);
}
return 0;
}
tolower() 转换为小写字母字符 ,返回值为转换后的小写字母 toupper() 转换为大写字母字符,返回值为转换后的大写字母
#include <stdio.h>
#include <ctype.h>
int main(int argc, char *argv[])
{
int ch;
while ((ch = getchar()) != EOF) {
if (isalpha(ch)) {
if (isupper(ch)) {
ch = tolower(ch);
}
else {
ch = toupper(ch);
}
printf("%c\n", ch);
}
}
return 0;
}