C语言基础
1.一维数组的定义格式为:
类型说明符 数组名[常量表达式]; 例如: int a[10];
数组是顺序的存储方式 使一个数组所有元素为0 :int a[10]={0};
a[10] : 一个数组或代表数组的首地址
在2目录中编写1.c 目的是打印数组其中元素的地址
#include<stdio.h>
int main()
{
int a[2]={0};
printf("a %p\n",a);
printf("&a %p\n",&a);
printf("a+1 %p\n",a+1);
printf("&a+1 %p\n",&a+1);
return 0;
}
运行结果:
[root@localhost 2]# ./1
a 0xbfcaacdc
&a 0xbfcaacdc
a+1 0xbfcaace0
&a+1 0xbfcaace4
输出格式 %p:打印地址 a+1:跳到下一个元素 & a+1:跳到下一个数组 可分析上图运行结果
二维数组可以写成 int a[3][4]={{1},{0,6},{0,0,0,1}};
打印数组可以写成 printf(“%6d”,a[i][j]);
a[3][4] 数组 a[1] 代表中间那行的首地址
a[1]+1 代表中间一行第二个元素的地址进行取值操作
*(a[1] + 1) *(&a[1][1]) (*(a + 1))[1] *(*(a+1)+1)均可表示a[1][1]元素
a[3][4]数组 可以看成一个一维数组 每一行为一个元素,一个元素又包含四个元素
a:基本单位是行 &a:基本单位是数组 a[0]:基本单位是元素
a+1范围是行,代表第二行,*(a+1)范围从行数变为第二行的四个元素 []有取值的意思
在2目录下编写2.c 输出二维数组元素的地址
#include<stdio.h>
int main()
{
int a[3][4]={1,2,3,4,5,6,7,8,9,10,11,12};
int i,j;
for(i=0;i<3;i++)
{
for(j=0;j<4;j++)
{
printf("a[%d][%d] = %d ",i,j,a[i][j]);
}
printf("\n");
}
printf("a %p\n",a);
printf("a[1] %p\n",a[1]);
printf("a[1]+1 %p\n",a[1]+1);
printf("a[1][1] %d\n",*(a[1]+1));
printf("&a %p\n",&a);
printf("a+1 %p\n",a+1);
printf("&a+1 %p\n",&a+1);
return 0;
}
结果为:
[root@localhost 2]# ./2
a[0][0] = 1 a[0][1] = 2 a[0][2] = 3 a[0][3] = 4
a[1][0] = 5 a[1][1] = 6 a[1][2] = 7 a[1][3] = 8
a[2][0] = 9 a[2][1] = 10 a[2][2] = 11 a[2][3] = 12
a 0xbfa68a6c
a[1] 0xbfa68a7c
a[1]+1 0xbfa68a80
a[1][1] 6
&a 0xbfa68a6c
a+1 0xbfa68a7c
&a+1 0xbfa68a9c
在2目录下编写3.c 用冒泡排序法排序(运用函数调用2)
#include<stdio.h>
void sort(int *a)
{
int i,j,m;
for(i=0;i<5;i++)
{
for(j=0;j<5-i;j++)
{
if(a[j]<a[j+1])
{
m=a[j];
a[j]=a[j+1];
a[j+1]=m;
}
}
}
}
int main()
{
int a[6]={9,5,1,3,2,7};
int i;
sort(a);
for(i=0;i<6;i++)
{
printf(" %d\n",a[i]);
}
return 0;
}
执行结果:
[root@localhost 2]# ./3
9
7
5
3
2
1
man 数字 +... 1:查命令 2:系统调用 3:库函数 q:退出
如 man 1 printf
puts函数
其一般形式为: puts (字符数组)
其作用是将一个字符串(以′\0′结束的字符序列)输出到终端。
char ptr[20]=”hello\nworld”;
puts(ptr);
输出结果:hello
world
4. c输入输出两个数组
#include<stdio.h>
int main()
{
char str[10];
char ptr[10];
scanf("%s %s",str,ptr);
printf("str: %s\n",str);
printf("ptr: %s\n",ptr);
return 0;
}
结果为:
[root@localhost 2]# ./4
giu
vhh
str: giu
ptr: vhh
strcat函数
其一般形式为:strcat(字符数组1,字符数组2)
Strcat的作用是连接两个字符数组中的字符串,把字符串2接到字符串1的后面,结果放在字符数组1中,函数调用后得到一个函数值——字符数组1的地址。
5.c 运用strcat函数
#include<stdio.h>
#include<string.h>
int main()
{
char ptr1[20]="Hello";
char ptr2[10]="world";
strcat(ptr1,ptr2);
puts(ptr1);
return 0;
}
结果:
[root@localhost 2]# ./5
Helloworld
strcpy函数
其一般形式为:strcpy(字符数组1,字符串2)
strcpy是“字符串复制函数”。
作用:是将字符串2复制到字符数组1中去。
可以用str ncpy函数将字符串2中前面若干个字符复制到字符数组1中去。
例如:strncpy(str1,str2,2);作用是将str2中前面2个字符复制到str1中去,然后再加一个\0
6. c 运用strcpy函数
#include<stdio.h>
#include<string.h>
int main()
{
char str1[10]="hello";
char str2[10]="12";
printf("%s \n",str1);
strncpy(str1,str2,2);
printf("%s \n",str1);
return 0;
}
结果:
[root@localhost 2]# ./6
hello
12llo
strcmp函数
其一般形式为:strcmp(字符串1,字符串2)
strcmp的作用是比较字符串1和字符串2。
比较的结果由函数值带回
(1) 如果字符串1=字符串2,函数值为0。
(2) 如果字符串1>字符串2,函数值为一正整数。
(3) 如果字符串1<字符串2,函数值为一负整数。
7.c strcmp的运用
#include<stdio.h>
#include<string.h>
int main()
{
char ptr[10];
char str[10];
scanf("%s %s",ptr,str);
if(!strcmp(ptr,str))
{
printf("yes\n");
}
else if(strcmp(ptr,str)>0)
{
printf("%s > %s\n",ptr,str);
}
else
{
printf("%s < %s\n",ptr,str);
}
return 0;
}
结果:
[root@localhost 2]# ./7
gdgdg
vf
gdgdg < vf
strlen函数
其一般形式为: strlen (字符数组)
strlen是测试字符串长度的函数。函数的值为字符串中的实际长度(不包括 \0在内)。
strlwr函数
其一般形式为:strlwr (字符串)
strlwr函数的作用是将字符串中大写字母换成小写字母。
strupr函数
其一般形式为:strupr (字符串)
strupr函数的作用是将字符串中小写字母换成大写字母。
8. c 看一个字符串是否是另外一个字符串的子串
#include<stdio.h>
#include<string.h>
#include<stdlib.h>
int main()
{
char string[10]={0};
char sub_str[10]={0};
int i;
scanf("%s %s",string,sub_str);
int str_len=strlen(string);
int sub_len=strlen(sub_str);
if(str_len<sub_len)
{
printf("error");
exit(1);
}
for(i=0;i<str_len-sub_len+1;i++)
{
if(!(strncmp(string+i,sub_str,sub_len)))
{
printf("%s is sub_string\n",sub_str);
break;
}
if(i==str_len-sub_len)
{
printf("%s is not sub_string\n",sub_str);
}
}
return 0;
}
结果:
[root@localhost 2]# ./8
hello
el
el is sub_string
9. c 在一个字符串的特定位置插入一个字符
如 abcef 4 d 变为abcdef
#include<stdio.h>
#include<string.h>
int main()
{
char str[50];
char ptr[50];
char tem[50];
char ppp[50];
int i,j,p=0;
printf("input str number ptr\n");
scanf("%s %d %s",str,&i,ptr);
strncpy(tem,str,i-1);
strcat(tem,ptr);
j=i-1;
while((ppp[p]=str[j])!='\0')
{
p++;
j++;
}
strcat(tem,ppp);
strcpy(str,tem);
printf("str is:%s\n",str);
return 0;
}
结果为:
[root@localhost 2]# ./9
input str number ptr
heoworld
3
ll
str is:helloworld
形参与实参
形式参数:定义函数时函数名后面括号中的变量名
实际参数:调用函数时函数名后面括号中的表达式
函数调用的形式:
(1)作为函数语句调用。函数一般无返回值。
(2)作为函数表达式调用。
(3)作为函数参数调用。
10. c max函数的调用
#include<stdio.h>
#include<stdlib.h>
/*int max(int i,int j)
{
return (i>j)?i:j;
}*/
int func(int *i,int *j)
{
(*i)++;
(*j)++;
return 0;
}
int main()
{
int a=5,b=10;
int result;
func(&a,&b);
//result=max(a,b);
//printf("max is %d\n",result);
printf("a is %d\n",a);
printf("b is %d\n",b);
return 0;
}
结果为:
[root@localhost 2]# ./10
a is 6
b is 11
函数调用的步骤:
1. 通过函数名找到函数入口地址 2.给形参分配空间 3.值传递
4. 执行函数体语句 5.返回 6.释放
地址传递方式:
函数调用时,将数据的存储地址作为参数传递给形参
特点:
形参与实参占用同样的存储单元;
“双向”传递;
实参和形参必须是地址常量或变量;
register变量
对于使用频繁的变量,可以使用register声明为寄存器变量,其值存储在CPU中,加快了运行速度。
extern 声明为外部文件 extern 的应用
Main.c
#include<stdio.h>
int num=5;
int main()
{
print();
return 0;
}
Print.c
#include<stdio.h>
extern int num;
void print()
{
printf("num is %d\n",num);
}
执行 gcc main.c print.c -o extern ./extern
结果为:
num is 5
书写.h文件
#ifndef _PRINTF_H_
#define _PRINTF_H_
#endif
static:
1. 限制作用域,修改函数时时静态函数,只能在本文件中被调用。
2. 修饰静态局部变量,只被定义一次,只分配一次内存空间,改变变量生命周期至程序结束。
3. 静态存储变量只能在本文件中使用,不能全局访问。
11. c static的应用
#include<stdio.h>
int add()
{
static int a=0;
a++;
return a;
}
int main()
{
int i;
int result;
for(i=0;i<5;i++)
{
result=add();
printf("result is %d\n",result);
}
return 0;
}
结果为:
[root@localhost 2]# ./11
result is 1
result is 2
result is 3
result is 4
result is 5
#include "stdio.h"
在当前目录和TC指定的目录中找该文件
#include <stdio.h>
在由TC指定的文件目录中找该文件
#define SQR(X) X*X
int k = 2, m = 1;
SQR(k + m);
答案为5 解:2+1X2+1=5
SQR(k + m);变为SQR((k + m)); 结果即为9
面试题:宏函数和自定义函数的优缺点
宏函数的优点:在预处理阶段被执行,只做简单替换,不占用过多的内存空间,叫”时间换空间”,适用于简单处理程序。
宏函数的缺点: 替换需要消耗时间,只做简单替换,不做语法检查,不安全。
#define PRINT printf(“hello\n”);\ \把两行连接在一起
printf(“world”)
自定义函数的优点:在执行的时候被调用,相当于宏变换时间少,函数调用和返回时间少。
自定义函数的缺点:会占用过多内存空间。