该文为学习笔记,仅作学习参考,如有错误,望指正!
VMware Workstation虚拟机软件
在虚拟机和宿主机切换鼠标:ctrl+alt;
ubuntu是一个桌面版的Linux系统;
shell终端 ,如下图所示:
打开一个shell终端:
ctrl + alt + t 默认打开的路径是当前用户的家目录(~:代表家目录);
如果希望在当前终端下打开一个相同路径的终端的话,使用:ctrl + shit + n;
ctrl + alt + enter 切换全屏;
shell命令:
cd 目录
:进入到某一目录下 ;
cd ..
:回到上一级目录 依次多次执行,肯定会回到根路径 “/”,这是整个Linux文件系统的最顶层;
TAB 补齐 根据输入的首字母补齐,如果当前目录下存在以输入字母开头的多个文件的话,可以tab两下补齐,如果只有一个以输入字母开头的文件的话,只需要tab一次;
Linux世界中,一切皆文件;
pwd命令用于显示用户在文件系统中的当前位置,该命令没有任何选项和参数,命令执行结果显示为绝对路径名;
mkdir 创建一个文件夹/目录:如果希望创建多级目录的话,可以使用mkdir -p day01/model
;
Linux的文件组织模式犹如一颗倒置的树,所有的目录或者文件都是挂载到根目录下的;
[root@localhost /]# ls
bin boot box dev etc home lib lib64 media mnt opt proc root run sbin srv sudo sys tmp usr var
[root@localhost /]# ls -la
总用量 16
dr-xr-xr-x. 19 root root 266 11月 15 15:08 .
dr-xr-xr-x. 19 root root 266 11月 15 15:08 ..
lrwxrwxrwx 1 root root 7 3月 6 2021 bin -> usr/bin
dr-xr-xr-x. 6 root root 4096 11月 1 14:22 boot
drwxrwxrwx 2 root root 6 11月 1 13:54 box
drwxr-xr-x 20 root root 3920 11月 15 10:31 dev
drwxr-xr-x 106 root root 8192 11月 15 14:47 etc
-rw-r--r-- 1 root root 0 11月 1 13:54 .exectl_all
drwxr-xr-x 3 root root 19 11月 11 17:43 home
lrwxrwxrwx 1 root root 7 3月 6 2021 lib -> usr/lib
lrwxrwxrwx 1 root root 9 3月 6 2021 lib64 -> usr/lib64
drwxr-xr-x 2 root root 6 3月 6 2021 media
drwxr-xr-x 2 root root 6 3月 6 2021 mnt
drwxr-xr-x 2 root root 6 3月 6 2021 opt
dr-xr-xr-x 205 root root 0 11月 15 10:30 proc
dr-xr-x--- 5 root root 218 11月 15 14:51 root
drwxr-xr-x 25 root root 720 11月 15 10:31 run
lrwxrwxrwx 1 root root 8 3月 6 2021 sbin -> usr/sbin
drwxr-xr-x 2 root root 6 3月 6 2021 srv
drwx--x--x 3 root root 16 11月 1 13:56 sudo
dr-xr-xr-x 14 root root 0 11月 15 10:30 sys
drwxrwxrwt 9 root root 180 11月 15 15:08 tmp
drwxr-xr-x 12 root root 144 11月 1 13:52 usr
drwxr-xr-x 19 root root 264 11月 1 14:00 var
ls
列出当前目录下所有文件, 命令与选项之间用空格分隔;
ls -a
列出当前目录下所有文件,包含隐藏文件;
ls -l
列出当前目录下所有文件(不包含隐藏文件)的详细信息;
ls -l file
:在Linux世界,不是以文件的后缀名区分文件的,是通过“b c d - l s p”这些字段来区分的;
drwxrwxr-x:d 目录,- 普通文件;
rwx rwx r-x 代表权限;
第一组权限代表文件所有者(user) 具有的权限 r 读权限 w 写权限 x 可执行权限;
第二组权限代表同组用户(group) 具有的权限 r 读权限 w 写权限 x 可执行权限;
第三组权限代表其他用户(other) 具有的权限 r 读权限 - 没有写权限 x 可执行权限;
ying@ying-VMware-Virtual-Platform:~/桌面$ ls -la
总用量 8
drwxr-xr-x 2 ying ying 4096 11月 15 14:31 .
drwx------ 20 ying ying 4096 11月 19 17:03 ..
. 代表当前路径;
… 代表上一级路径;
cd day02
:切换路径到当前目录下的day02目录,这里省略了“.”,相当于cd ./day02 ;
cd ../..
:切换路径到上两级目录下,三级四级路径依次类推 ;
命令行提示符:
ying@ying-VMware-Virtual-Platform:~/桌面$:
ying:用户名;
ying-VMware-Virtual-Platform:主机名;
:后的`~/桌面`:表示的是当前路径名;
$:代表是一个普通用户
另:
/home/ying:代表当前用户ying的家目录;
“~”:代表家目录
绝对路径与相对路径
从根路径(/)开始写全路径名,这是绝对路径:`/home/linux/Desktop`
以某一路径作参照,相对于此路径在某个位置 ./Desktop 相对路径
cd :在任一目录下都可以直接回到家目录
cd ~ :在任一目录下都可以直接回到家目录
cd - :回到上一次的工作目录
清屏:clear & ctrl + l;
cat file
:在不打开文件的前提下查看文件内容;
cp 复制
复制文件
cp file1 file2:在当前目录下拷贝file1为file2
cp file1 /home/linux:拷贝当前目录下的file1文件到指定目录/home/linux下,文件名仍为file1
cp file1 /home/linux/file2:拷贝当前目录下的file1文件到指定目录/home/linux下,文件名为file2
cp /home/linux/file1 /home/linux/Desktop:拷贝指定目录下的file1文件到指定目录/home/linux/Desktop下
复制目录
复制目录和复制文件类似,只不过要在最后加上 -a
cp dir1 dir2 -a
cp dir1 /home/linux -a
cp /home/linux/dir1 /home/linux/Desktop -a
mv
mv file new_file
:把当前目录下的文件file重命名为new_file
mv file /home/linux
:把当前目录下的文件file移动到/home/linux,当前目录下就没有原文件file,相当于剪切
mv /home/linux/file /home/linux/Desktop/new_file
:把指定目录下的文件file移动到指定目录下,并重命名为new_file,原来目录下就没有原文件file,相当于剪切并重命名
mv dir1 dir2
touch file 如果file不存在,则创建一个空文件;如果file存在,更新file的时间戳
rm file
rm /home/linux/file
rm dir -rf
:删除文件夹
编辑器
vi file
打开时进入一般模式,可以输入:
i:切换到编辑模式,在所在光标前进行输入;
l:在所在光标行首进行输入;
a:在光标所在位置后输入;
A:在光标所在行尾输入;
o:从光标所在的行的下一行插入一行;
O:在光标所在的行的上一行插入一行;
hjkl:方向键左下上右;
x:删除光标所在的一个字符;
dd:删除光标所在行;
ndd:删除光标所在行后n行;
gg:将光标定位到行首;
G:将光标定位到行尾;
u:撤销上一步操作;
ctrl+r:重做;
/...:查找...;
ngg:将光标定位到第n行;
p:在光标所在行后面粘贴;
P:在光标所在行前面进行插入;
yy:复制光标所在行;
nyy:复制光标开始的n行;
r:替换光标所在的字符,输入完 r 之后,直接跟上要替换的字符;
:1,5y:复制第一行到第五行;
esc:从编辑模式退出;
通过输入“:”进入命令行模式
:w 保存
:wq 保存并退出
:q 不保存退出
:q! 强制退出,不保存
:wq! 强制保存并退出
底行模式常用命令:
vsp 文件名:左右分屏打开多个文件进行编辑;
wqa:将所有打开的文件都保存退出;
set number:显示行号;
set nonumber:关闭行号;
noh:取消查找的高亮显示;
%s/aaa/bbb/g:将全文aaa替换为bbb;
10,20s/aaa/bbb/g:将文中10到20行的aaa替换为bbb;
编写一个C程序
vi HelloWorld.c
:创建的c程序文件的后缀一定是".c"
#include stdio.h //添加头文件
int main() //主函数,程序的入口
{
printf("Hello World!\n");
return 0;
}
#:开头行,与处理文件;
#include:包含头文件的关键字;
stdio.h:标准输入输出头文件;(<>:表示引用标准库头文件,编译器会从系统配置的库环境中去寻找;"":一般表示用户自己定义使用的头文件,编译器默认会从当前文件夹中寻找,如果找不到,则到系统默认库环境中去寻找。)
int:函数的返回值类型;
main:主函数,程序的入口,每个函数必须有且仅有一个;
():里面为函数参数;
{}:函数体,即实际要执行的内容;
printf:系统提供的输出函数;
return 0:返回值;
GCC编译器
编程语言分为编译型语言和解释性语言
编译型语言:
在运行之前,需要单独有一个翻译的过程,将人类能识别的高级语言翻译成机器能识别的低级语言。
优点:执行的过程中,就无需每次进行翻译,执行效率相对较高。
缺点:比较依赖编译器的架构和版本,跨平台性能较差。
解释型语言
运行前无需翻译,在执行过程中,由解释器逐条翻译给计算机看。
优点:跨平台性能好。
缺点:每次执行都需要逐条翻译,执行效率相对较低。
编译C程序
gcc HelloWorld.c
如果程序没有错误,默认会在当前目录下生成一个可执行文件a.out
gcc HelloWorld.c -o filename
如果程序没有错误,会在当前目录下生成一个通过“-o”指定文件名的可执行文件
gcc编译器要求源程序的后缀名为 .c
./a.out
:执行编译成功之后的a.out
注释
单行注释 ://
多行注释:
/*
注释的内容
*/
条件注释:
常见的一中
#if 0/1(非0即为真)
注释的内容
#endif
选择条件的注释
#if 0/1(非0即为真)
注释的内容
#else
注释的内容
#endif
嵌套情况
#if 0/1(非0即为真)
...程序段1...
#else
#if 常量b
...程序段2...
#else
...程序段3...
#endif
#endif
实例:
#include //添加头文件
int main() //主函数,程序的入口
{
int x; int y; //声明了两个int型变量x,y
//int x; //单行注释
//int y; //单行注释
#if 1 //条件注释
printf("Hello World!\n");
int b = 40;
/* //多行注释
if(b == 40)
{
b = 99;
//int i = 90;
}
*/
#endif
//i = 100;
return 0;
}
void fun()
{ //作用域
int a = 20;
a = a - 20;
}
[root@localhost learn]# ./a.out
Hello World!
概念区分
程序的设计步骤:编辑 ( vi ) 、编译( gcc )、运行调试
库函数是封装好的,可以直接拿来用,但是在使用库函数,一定要先包含相应头文件来说明,然后才可以使用。如果想知道某个库函数使用的头文件,我们可以使用“man 3 函数名”
注意: |
---|
C标准库 在线速查手册(此部分内容需整理收纳学习) 开放组基本规格 7 年第 2018 期版 (opengroup.org) |
GCC -l选项:手动添加链接库(此部分内容需整理收纳学习) |
GCC调用math.h库时报错的问题分析和解决: 在Linux下使用gcc编译c语言时遇到报错: undefined reference to `sqrt’ 这是因为math.h函数库不在标准库中,使用时需要链接到外部库进行调用。 解决方法是编译时在命令末尾加上 -lm(-l是指定程序链接哪个库,m表示的是数学库) |
GNU的含义:GNU is not Unix
gcc编译源程序,生成可执行文件分为四步:预处理->编译->汇编->链接。
预处理:头文件包含,去注释、宏替换
gcc -E Hello.c -o Hello.i
编译:语法或者词法检查,如果没有错误,才会生成汇编文件;否则显示错误信息
gcc -S Hello.i -o Hello.s
汇编:将汇编文件生成机器码相关的文件(即二进制文件)
gcc -c Hello.s -o Hello.o
链接:链接库文件(即函数),最终生成可执行文件
ld
进制转换
0x12af
= 1 * 16^3 + 2 * 16^2 + 10 * 16^1 + 15 * 16^0
= 4096 + 512 + 160 + 15
= 4783
20 转换二进制: 10100
关键字:关键字就是编译器中已经定义好的一些有特殊函数的单词,直接使用即可。
auto const static extern register volatile sizeof
C 语言是严格区分大小写的,关键字都是小写的。
标识符:是由程序员按照命名规则自行定义的词法符号,用于定义宏名、变量名、函数名和自定义类型名等。
命名规则如下:
{}:作用域,用于分清作用域内的数据只在当前作用域生效
定位语句所在文件名、函数名及行号
#include
int main( )
{
printf("%s,%s,%d\n",__FILE__,__FUNCTION__,__LINE__); //FILE、FUNCTION、LINE:每个前后都是两个下划线
// __FILE__:打印语句所在的文件名
//__FUNCTION__:打印语句所在的函数名
//__LINE__:打印语句所在的行号
return 0;
}
#include
int main()
{
int i = 0;
for(i = 0 ; i < 3; i++)
{
printf("%s,%s,%d\n",__FILE__,__FUNCTION__,__LINE__);
printf("i = %d\n",i);
}
return 0;
}
[root@localhost learn]# ./a.out
tt.c,main,7
i = 0
tt.c,main,7
i = 1
tt.c,main,7
i = 2
数据类型的分类(需再次确认以下分类是否正确)
逻辑类型。只有两个量true和false,表示逻辑真值和逻辑假值。
bool:使用该类型值,就必须加头文件
#include
#include
int main()
{
bool b = -2; //非零既真
if(b) //条件判断,如果if后的()里面的表达式为真,就执行if后的{}里的内容,否则执行else语句
{
printf("It is true!\n");
printf("%d\n",b);
}
else
{
printf("It is false!\n");
printf("%d\n",b);
}
return 0;
}
[root@localhost learn]# ./a.out
It is true!
1
_Bool:使用该类型值,不需要加任何头文件,其值非零既真
#include
int main()
{
_Bool b = 2;
if(b)
{
printf("It is true!\n");
}
else
{
printf("It is false!\n");
}
return 0;
}
[root@localhost learn]# ./a.out
It is true!
char类型:占有一个字节,一个字节占有8位,默认有符号,决定了char表示的数据范围 (-128~127),最高位是符号位,1 代表负数,0 代表正数;
char a = 97=0110 0001;
singed char:表示的数据范围是 (-128 – 127),最高位为符号位;
unsigned char:表示的数据范围是 (0 – 255), 最高位也参与运算;
#include
int main()
{
char a = 128;
a = 90;
printf("%d\n",a);
unsigned char c2= -1;
printf("%d\n",c2);
return 0;
}
[root@localhost learn]# ./a.out
90
255
字符常量:是指一个单一字符, 其表示形式是由两个单引号包括的一个字符。字符常量的值就是该字符的ASCII码值,实际运算是拿相对应的ASCII来参与运算。
#include
int main()
{
char a = 10;
char b = 20;
a = 'b'; //字符常量赋值给变量a
char c = 'a' + 1;
char cc = 'A';
cc = 'A' + 32;
printf("%d\n",c);
printf("%c\n",c);
printf("%d\n",cc);
printf("%c\n",cc);
/*
'a' //字符常量a
"a" //字符串常量a
*/
return 0;
}
[root@localhost learn]# ./a.out
98
b
97
a
计算机中数据的存储方式,实际按照数据的补码形式存储
singed 正数 97 | 负数 -97 |
---|---|
原码 0110 0001 | 原码 1110 0001 |
反码 0110 0001 | 反码 1001 1110 符号位不变,剩余位按位取反 |
补码 0110 0001 | 补码 1001 1111 反码+1 |
char a = 128; 存储时只看数值,取出是看数据类型 | unsigned char c2= -1; |
---|---|
原码:1000 0000 | 原码: 1000 0001 |
反码:1000 0000 | 反码: 1111 1110 |
补码:1000 0000 | 补码: 1111 1111 |
原码: 1000 0000 | 原码: 1111 1111 |
反码: 1111 1111 | 反码: 1111 1111 |
补码: 1000 0000 取出时: -128 | 补码:1111 1111 取出时: 255 |
#include
int main()
{
float f = -3243243243243243212.341234565686; //float默认保留小数点后六位
//printf("%.7f\n",f);
printf("%e\n",f);
return 0;
}
[root@localhost ~]# ./a.out
-3.243243e+18
字符串常量:是指用双引号括起来的多个字符或一个字符来表示的数据。
#include
int main()
{
char str1[] = "Hello"; //字符串常量赋值给字符数组
char *str2 = "Hello"; //字符串常量赋值给字符指针
/*
'a' //只包含一个字符常量a
"a" //除了包含一个字符常量a之外,还有一个字符串结束符‘\0’
*/
char c1 = 'a';
char *c2 = "a";//c2 指向字符串的首地址
int i = 0;
for(i = 0; i < 2; i++)
{
//i = 0 时,取字符串的第一个字符;
//i = 1 时,取值符串的第二个字符.
printf("%d\n",*(c2+i));
}
return 0;
}
[root@localhost learn]# ./a.out
97
0
标识符常量
#define N (8+6):原样替换,可以使用预处理查看替换结果(只关心他有没有定义过,无关于定义的内容);
#include
#define N (8+8)
#define M int main(){int a = N * N; printf("a = %d\n",a);return 0;}
题目:1个水分子的质量约为3.0*10^-23克。1夸脱水大约是950克。编写一个程序,提示用户输入水的夸脱数,并显示水分子数量。(使用scanf函数)
#include
#include
int main()
{
double water_molecule;
int quart_number;
printf("请输入水的总夸脱数:\n");
scanf("%d",&quart_number);
water_molecule=(quart_number*950)/(3.0*pow(10,-23));
printf("%d夸脱数的水分子数为%e\n",quart_number,water_molecule);
return 0;
}
[root@localhost ~]# gcc water_molecule.c
[root@localhost ~]# ./a.out
请输入水的总夸脱数:
166
166夸脱数的水分子数为5.256667e+27
[root@localhost ~]# gcc model.c -o test
[root@localhost ~]# ./test
AAA is define
BBB is true
强制类型转换
注意:
强制转换是指在某次运算中,通过某种方式将变量的类型转化为其他类型参与运算,简称强转。
显示强转
格式:新的类型名 变量名
int a = 7;
int b = 2;
float c = (float)a / (fload)b;
隐式强转
隐式强转是编译器根据上下文自动推导来的。如果编译器认为本次强转是安全的,则可以直接通过;若编译器认为不安全,则可能会给一个警告,具体取决于编译器的严谨程度。
#include
int main()
{
float a = 3.1415;
int b = a;
printf("b = %d\n", b);
return 0;
}
有符号和无符号参与运算时,会将有符号数隐式强转为无符号数参与运算。
signed int a = -20;
unsigned int b = 10;
a + b 的结果是大于零的;
变量说明的一般形式是:<存储类型> <数据类型 > <变量名> ;
#include
#define ARCH
int main()
{
#ifdef ARCH
printf("ARM!\n");
#endif
return 0;
}
#include
#define AAA
#define BBB 1
int main()
{
#ifdef AAA // ifdef能过,是因为这种带#的,都只关心他有没有定义过,无关于定义的内容
printf("AAA is define\n");
#endif
if ( 1 == BBB)
{
printf("BBB is true\n");
}
return 0;
}
register:寄存器存储类型,速度快,但是寄存器甚少,不一定能申请到。
#include
int main()
{
register int i,j;
for(i = 0; i < 3; i++)
{
for(j = 0; j < 2; j++)
{
printf("%d\n", i+j);
}
}
return 0;
}
[root@localhost learn]# ./a.out
0
1
1
2
2
3
static:声明变量,最主要功能是隐藏,其次因为 static 变量存放在静态存储区,所以它具备持久性和默认值 0x00
的特性。
静态局部变量一般的使用场景:需要保留函数上一次调用结束时的值;如果初始化后,变量只会被引用而不会改变其值,则这时用静态局部变量比较方便,以免每次调用时重新赋值。
共有两种变量存储在静态存储区:全局变量和 static 变量,内存中所有的字节默认值都是 0x00。演示示例如下所示:
#include
static int g_x;
int g_y;
int main(void)
{
static int x;
printf("g_x:%d\ng_y:%d\nx:%d",g_x,g_y,x);
return 0;
}
[root@localhost ~]# ./a.out
g_x:0
g_y:0
x:0
extern:声明的变量,说明它不是在当前文件中声明的,而是在其他文件中声明的全局变量。extern 称为外部参照引用型,使用extern 说明的变量是想引用在其它文件中函数体外部说明的变量。
#include
int main()
{
extern int a;
printf("a = %d\n",a);
return 0;
}
数据类型与所占内存空间大小息息相关。
所谓表达式是指由运算符、运算量和标点符号组成的有效序列,其目的是用来说明一个计算过程。表达式可以独立形成语句,该语句称为表达式语句。
表达式语句的一般形式为:<表达式> ;
C 提供的算术运算符:+、-、*、/、%
;注意:浮点数不能参加 % 运算;
自增自减运算符++、--
++a
和 a++
都是对 a 自增1,但是有什么区别呢?
a++
:先使用 a 的值,再对a自增1;++a
:先对 a 自增1,然后在使用 a 的值。#include
int main()
{
int a = 10;
int b = 3;
printf("%d\n", a + b);
printf("%d\n", a - b);
printf("%d\n", a * b);
printf("%d\n", a / b);
printf("%d\n", a % b);
printf("%d\n",a++); // a++<=>先打印a再执行a = a + 1操作;
printf("%d\n",++a); // ++a<=>先执行a = a + 1后,再打印a的值;
printf("%d\n",a);
return 0;
}
[root@localhost ~]# gcc model.c
[root@localhost ~]# ./a.out
13
7
30
3
1
10
12
12
赋值运算符实例
#include
int main()
{
int a = 10;
int b,c;
b = c = a;
printf("%d,%d,%d\n",a,b,c);
a += b;
printf("%d,%d,%d\n",a,b,c);
a = a + b;
printf("%d,%d,%d\n",a,b,c);
return 0;
}
[root@localhost ~]# gcc model.c 已写入
[root@localhost ~]# ./a.out
10,10,10
20,10,10
30,10,10
逗号运算符
用逗号链接多个表达式,从左到右每一个都会执行,但只取最后一个表达式的结果就是整个逗号运算符表达式的结果。
格式:(表达式1,表达式2, …, 表达式n);
#include
int main()
{
int a = 10, b = 20, c = 30;
int a1, b1, c1;
c = (a += 3, b += 6, a + b);
printf("a = %d\n",a);
printf("b = %d\n",b);
printf("c = %d\n",c);
return 0;
}
[root@localhost ~]# gcc model.c
[root@localhost ~]# ./a.out
a = 13
b = 26
c = 39
关系运算符:
关系运算符运算之后都是会得到一个逻辑值: 真 or 假;
关系运算符 == 是判断是否相等的,= 赋值运算符,如果担心把 a == 10 写错成 a = 10,可以直接写成10 == a ,这样如果误写成“10 = a”, 编译阶段就可以检查错误!
#include
int main()
{
int a = 19, b = 10;
if(10 == a)
{
printf("a == b\n");
}
else
{
printf("a != b\n");
}
printf("%d\n",a = b);
return 0;
}
[root@localhost ~]# gcc model.c
[root@localhost ~]# ./a.out
a != b
10
逻辑与&&
运算符的运算规律:一假即假,同真为真
短路法则:逻辑与&&
运算时,左边为假,决定了运算结果一定为假,所以右边运算量就不需要运算了!
逻辑或||
运算符的运算规律:一真即真,同假为假
短路法则:逻辑与&&
运算时,左边为真,决定了运算结果一定为真,所以右边运算量就不需要运算了!
逻辑非!
:单目运算符,表示逻辑取反的意思,真变假,假变真。
注意:C 语言中不允许写类似10
(10
#include
int main()
{
int a = 9, b = 10;
printf("%d\n",!(a < b));
printf("%d\n",(a > 0 && a < b));
printf("%d\n",((a < 0) || (a = 20))); // 注意:此处为赋值
printf("a = %d\n",a);
return 0;
}
[root@localhost ~]# gcc model.c
[root@localhost ~]# ./a.out
0
1
1
a = 20
位逻辑与&
运算符的运算规律:一零即零,同一为一;
位逻辑或|
运算符的运算规律:遇一为一,同零为零;
位逻辑异或^
运算符的运算规律:相同为0,不同为1;
按位取反~
运算符的运算规律:按位取反,0变1,1变0;
按位左移<<
:整个数据向左移动,舍弃高位,低位补0;
按位右移>>
:整个数据向右移动,舍弃低位,高位补0;
#include
int main()
{
char a = 8, b = 3;
// 8
// 0000 1000
// 3
// 0000 0011
// &
// 0000 0000
printf("%d\n",a & b);
// 0000 1000
// 0000 0011
// |
// 0000 1011
//
printf("%d\n",a | b);
// 0000 1000
// 0000 0011
// ^
// 0000 1011
printf("%d\n",a ^ b);
//0000 1000
//0010 0000
printf("%d\n",a << 2);
return 0;
}
[root@localhost ~]# gcc model.c
[root@localhost ~]# ./a.out
0
11
11
32
m >> n:>> 导致数据变小,结果为 原来数m / 2的n次方
m << n:<< 导致数据变大,结果为 原来数m * 2的n次方
条件运算符...?...:...
:是一个三目运算符
一般形式是: <表达式1> ? <表达式2> : <表达式3>
首先执行表达式1,如果表达式1为真,执行表达式2;否则,执行表达式3
#include
int main()
{
int a = 10, b = 9;
int max;
(a > b && a > 8) ? (max = a) : (max = b);
(a < b) ? (a) : (b = 20);
printf("max = %d\n",max);
printf("b = %d\n",b);
return 0;
}
[root@localhost ~]# gcc model.c
[root@localhost ~]# ./a.out
max = 10
b = 20
sizeof:是C语言中保留关键字,也可以认为是一种运算符,单目运算符,用于计算所占字节长度。
sizeof 运算符的一般形式如下:
sizeof(<类型或变量名>) ,注意:它只针对数据类型,而不针对变量!
注意:64位系统将程序按32位编译,需要加编译选项-m32
。
#include
int main()
{
char a ;
short b;
long c;
float f;
double d;
char array[2];
printf("%d %d\n",sizeof(char),sizeof(a));
printf("%d %d\n",sizeof(short),sizeof(b));
printf("%d %d\n",sizeof(long),sizeof(c));
printf("%d %d\n",sizeof(float),sizeof(f));
printf("%d %d\n",sizeof(double),sizeof(d));
printf("%d %d\n",sizeof(char),sizeof(array[0]));
return 0;
}
[root@localhost ~]# gcc model.c
[root@localhost ~]# ./a.out
1 1
2 2
8 8
4 4
8 8
1 1
格式化输入函数:scanf(“格式控制串”,地址表);
注意:
%d:格式化输入一个十进制整数,TAB、空格、回车可以作为分隔符,可以多个空格或者多个回车和TAB组合;
#include
int main()
{
int a = 0, b = 0;
int num;
if( 2 == (num = scanf("%d%d",&a,&b)))
{
printf("a = %d\n",a);
printf("b = %d\n",b);
}
printf("num = %d\n",num);
printf("a = %d\n",a);
return 0;
}
[root@localhost ~]# gcc model.c
[root@localhost ~]# ./a.out
4 9
a = 4
b = 9
num = 2
a = 4
%c:用“%c”格式符时,TAB、空格、回车和转义字符作为有效字符输入;
#include
int main()
{
char c1,c2;
scanf("%c%c",&c1,&c2); // %c %c中间的空格可匹配中间输入的多个TAB、空格、回车和转义字符
printf("%d\n",c1);
printf("%d\n",c2);
return 0;
}
[root@localhost ~]# ./a.out
a
b
97
98
因为%c
把TAB、空格、回车当做有效字符来处理,如果想要处理这些垃字符的话,可以:
scanf("%c%*c%c",&c1,&c2)
:只能处理一个TAB、空格、回车;
scanf("%c %c",&c1,&c2)
:%c %c中间保留空格,可处理多个TAB、空格、回车;
scanf("%c,%c",&c1,&c2)
:这里把逗号当做分隔符,要求输入时,必须输入,
;
getchar()
可用于回收垃圾字符;
全局变量与局部变量
#include
int c = 9;
int main()
{
int a = 10 , b = 20;
c = a + b;
printf("%d\n", c);
return 0;
}
[root@localhost ~]# gcc model.c
[root@localhost ~]# ./a.out
30
输入两个整数,实现两个数的交换
#include
int main()
{
int a,b,c;
printf("please input two numbers a and b:");
scanf("%d%d",&a,&b);
c=a;
a=b;
b=c;
printf("the numbers are:\na=%d\nb=%d\n",a,b);
return 0;
}
[root@localhost ~]# gcc model.c
[root@localhost ~]# ./a.out
please input two numbers a and b:17 21
the numbers are:
a=21
b=17
输入三角形的边长,求面积
sqrt 函数加头文件math.h,编译的时候需要加上 -lm,即gcc -test.c -o test -lm;
#include
#include
int main(){
int a, b, c;
float p, S;
printf("请输入三角形三边长:\n");
scanf("%d %d %d",&a, &b, &c);
p = (a + b + c) / 2;
S = sqrt(p*(p-a)*(p-b)*(p-c));
printf("%d,%d,%d组成的三角形面积为:%f\n",a, b, c, S);
return 0;
}
[root@localhost ~]# ./a.out
请输入三角形三边长:
1 2 3
1,2,3组成的三角形面积为:0.000000
[root@localhost ~]# ./a.out
请输入三角形三边长:
3 4 5
3,4,5组成的三角形面积为:6.000000
输出百位数中个位、十位与百位数相加之和
#include
int main(){
int num, a, b, c;
printf("请输入一个百位数字进行计算个位、十位、百位相加:\n");
scanf("%d",&num);
if(!((num > 99) && (num <1000))){
printf("输入错误的数据,程序异常退出!\n");
return 0;
}
a = num % 10;
b = (num / 10) % 10;
c = num / 100;
printf("%d的个位、十位、百位相加为:%d\n",num,a+b+c);
return 0;
}
[root@localhost ~]# gcc model.c
[root@localhost ~]# ./a.out
请输入一个百位数字进行计算个位、十位、百位相加:
1000
输入错误的数据,程序异常退出!
[root@localhost ~]# ./a.out
请输入一个百位数字进行计算个位、十位、百位相加:
167
167的个位、十位、百位相加为:14
scanf
:%s - 输入一个字符串,用字符数组来存储
#include
int main()
{
char str[10]; //声明char类型长度为10的字符数组,数组名是数组首地址
scanf("%s",str);
printf("%s\n",str);
return 0;
}
[root@localhost ~]# gcc model.c
[root@localhost ~]# ./a.out
你好!
你好!
TAB、空格、回车都是分隔符。
scanf("%[^\n]",str1)
:除了\n
之外都可以作为字符串的有效字符进行输入;
#include
int main()
{
char str1[20];
char str2[20];
scanf("%[^\n]%s",str1,str2);
printf("str1 = %6s, str2 = %s\n",str1,str2);
return 0;
}
[root@localhost ~]# gcc model.c
[root@localhost ~]# ./a.out
lslslsl lslsls
tttttttt
str1 = lslslsl lslsls, str2 = tttttttt
#include
int main()
{
char str1[20];
scanf("%6s",str1);
printf("str1 = %s\n",str1);
return 0;
}
[root@localhost ~]# gcc model.c
[root@localhost ~]# ./a.out
lslslslslslsls
str1 = lslsls
scanf("%md",&a)
:指定数据宽度,遇到空格和不可转换字符结束;
scanf("%2d",&a)
:读一个两位整数
#include
int main()
{
int a;
scanf("%2d",&a);
printf("a = %d\n",a);
return 0;
}
[root@localhost ~]# gcc model.c
[root@localhost ~]# ./a.out
321
a = 32
scanf("%2c",&a)
:一次读取两个字符,但是只把第一个字符存储到指定的地址中, 如果在这个scanf后紧跟一个scanf("%c",&b)
, 这时b中存的是第三个字符
#include
int main()
{
int a;
char str1[10],str2[10];
scanf("%3c",str1);
scanf("%2c",str2);
printf("str1 = %s\n",str1);
printf("str2 = %s\n",str2);
return 0;
}
[root@localhost ~]# gcc model.c
[root@localhost ~]# ./a.out
webdsqqqq
str1 = web
str2 = ds
printf
格式说明符
格式:printf("格式控制串",输出表);
功能:按指定格式向显示器输出数据;
输出表:要输出的数据;
格式控制串:包含两种信息;
printf("Hello World!\n")
:普通字符Hello World!原样输出;printf("%s\n","Hello World!")
:按照%s指定格式输出;
#include
int main()
{
int a = 10;
printf("Hello World!\n");
printf("%s\n","Hello World!");
printf("%d\n",a);
printf("%#x\n",a);
printf("%#o\n",a);
printf("%c\n",a);
printf("%f\n",a);
printf("%%\n");
return 0;
}
[root@localhost ~]# gcc model.c
[root@localhost ~]# ./a.out
Hello World!
Hello World!
10
0xa
012
0.000000
%
printf
附加格式说明符
m:控制输出数据的域宽,如果长度
n:实数而言,控制小数点后输出的位数(四舍五入),字符串而言,实际输出的字符个数
m.n:输出实数时,保留小数点后n为,数据长度为m,但是小数点占有数据长度的一位;输出字符串时,控制实际输出n个字符,但是要求数据输出域宽为m,如果长度
printf("%-+010.5f\n",f);
保留小数点后五位,四舍五入;输出的数据域宽是10,如果长度< 10,左边补空格;但是我们这里有 0 ,所以补0;但是输出时要求输出 +, 这个 + 占一位。
#include
int main()
{
int a = 12;
float f = 12.345678;
printf("%-+4d\n",a);
printf("%+010.5f\n",f);
printf("%.4s\n","Hello!");
printf("%3.4s\n","Hello!");
return 0;
}
[root@localhost ~]# gcc model.c
[root@localhost ~]# ./a.out
+12
+012.34568
Hell
Hell
字符输入函数getchar
格式: getchar( );
功能:从键盘读一字符;
返回值:正常,返回读取的代码值;出错或结束键盘输入,返回-1;
getchar()
读取一个字符,TAB、回车、空格都是有效字符;
字符输出函数putchar
格式: putchar(c);
参数: c为字符常量、变量或表达式;
功能:把字符c输出到显示器上,不自带换行功能,可使用putchar(10);
进行换行;
返回值:正常,为显示的代码值;putchar( c );
输出字符c,这里c可以是字符,也可以是字符所对应的ASCII值。
#include
int main()
{
char c = getchar();
printf("the number = %d\n",c);
c = getchar();
putchar(c);
putchar(10);
printf("the number = %d\n",c);
return 0;
}
[root@localhost ~]# gcc model.c
[root@localhost ~]# ./a.out
abcd
the number = 97
b
the number = 98
字符串输入函数gets
(不推荐使用,或被弃用,不安全)
格式: char * gets(char *s);
功能:从键盘输入一以回车结束的字符串放入字符数组中,并自动加'\0'
;
#include
int main()
{
char str1[10];
gets(str1);
int i = 0;
for( i = 0; i < 11; i++)
{
printf("%d\n",str1[i]);
}
return 0;
}
[root@localhost ~]# gcc model.c
model.c: 在函数‘main’中:
model.c:5:2: 警告:implicit declaration of function ‘gets’; did you mean ‘fgets’? [-Wimplicit-function-declaration]
gets(str1);
^~~~
fgets
/usr/bin/ld: /tmp/ccSwYBNz.o: in function `main':
model.c:(.text+0x15): 警告:the `gets' function is dangerous and should not be used.
字符串输出函数puts
格式: puts(const char *s);
功能:向显示器输出字符串(输出完,换行)
说明:字符数组必须以'\0'
结束,相当于printf("%s\n",s);
#include
int main()
{
char a[] = {'1','a','\0','b','c','\0'};
puts(a);
printf("%s\n",a);
printf("%s\n","Hello!");
return 0;
}
[root@localhost ~]# gcc model.c
[root@localhost ~]# ./a.out
1a
1a
Hello!
if 语句
格式:if (表达式) 语句块1 else语句块2
if条件判断,如果表达式的结果为真,执行语句块1,如果为假,执行语句块2
表达式是要得到逻辑值:真或者假
在语句块内,当有若干条语句时,必须用{…}括起来,如果只有一条语句,可以省略括号{}不写
if可以单独存在,但是else不可以单独存在;并且else找就近的if;else和if之间 不可以隔多个语句。
以下是合法的
if('a'){
printf("a = %d\n",a);
printf("a = %d\n",a);
}else
printf("b = %d\n",b);
以下是非法的
if('a')
printf("a = %d\n",a);
printf("a = %d\n",a);
else
printf("b = %d\n",b);
model实例如下:
#include
int main()
{
int a = 0 , b = 0 ,max = 0;
puts("Please input two number:");
if(scanf("%d%d",&a,&b) == 2){
if(a > b){
max = a;
}else{
max = b;
}
}else{
puts("Input error!");
}
printf("max = %d\n",max);
return 0;
}
[root@localhost ~]# gcc model.c
[root@localhost ~]# ./a.out
Please input two number:
21 47
max = 47
#include
int main()
{
int a = 9, b = 10;
if('a'){
printf("a = %d\n",a);
printf("a = %d\n",a);
}else if(a > 8){
printf("b = %d\n",b);
printf("b = %d\n",b);
}else{
}
if('d'){
printf("hello!\n");
}
printf("b = %d\n",b);
printf("b = %d\n",b);
return 0;
}
[root@localhost ~]# gcc model.c
[root@localhost ~]# ./a.out
a = 9
a = 9
hello!
b = 10
b = 10
switch
语句
格式:
switch (表达式)
{
case 常量表达式1:语句块1;break;
case 常量表达式2:语句块2; break;
….
case 常量表达式n:语句块n; break;
default :语句块n+1
}
注意:
#include
int main()
{
switch('A'+2)
{
case 'B':puts("B");break;
case 'C':puts("C");break;
case 'D':puts("D");break;
case 'A':puts("A");break;
default:puts("END!");
}
return 0;
}
[root@localhost ~]# gcc model.c
[root@localhost ~]# ./a.out
C
题目:外部输入学生整数成绩,输出评分
90 - 100 A
80 - 89 B
70 - 79 C
60 - 69 D
0 - 60 E
if 语句实现
#include
int main()
{
int score;
puts("Please input one score:");
if(scanf("%d",&score) == 1){
if(score >=0 && score <= 100){
if(score >=90){
puts("A!");
}else if(score >=80){
puts("B!");
}else if(score >= 70){
puts("C!");
}else if(score >= 60){
puts("D!");
}else{
puts("E!");
}
}else{
puts("score is [0-100]");
}
}
else{
puts("Input error!");
}
return 0;
}
[root@localhost ~]# gcc model.c
[root@localhost ~]# ./a.out
Please input one score:
66
D!
[root@localhost ~]# ./a.out
Please input one score:
90
A!
swith 语句实现
#include
int main()
{
int score;
puts("Please input score:");
if(scanf("%d",&score) == 1){
if(score >=0 && score <= 100){
switch(score/10){
case 10:
case 9:puts("A!");break;
case 8:puts("B!");break;
case 7:puts("C!");break;
case 6:puts("D!");break;
default:puts("E!");break;
}
}
}
return 0;
}
[root@localhost ~]# gcc model.c
[root@localhost ~]# ./a.out
Please input score:
77
C!
题目:输入三个数:按照从小到大的顺序进行排列
int a = 10, b = 5, c = 20;
...
a = 5, b = 10, c = 20
#include
int main(){
int a, b, c, min, mid, max;
printf("请输入三个数字,以便从小到大进行排序:");
if(scanf("%d %d %d", &a, &b, &c) != 3){
printf("输入数据无效,请输入三个有效数字进行排序!");
return 0;
}
min = a < b ? a : b;
min = min < c ? min : c;
max = a > b ? a : b;
max = max > c ? max : c;
if ((a > min) && (a < max)){
printf("从小到大排序为:%d %d %d\n", min, a, max);
}else if((b > min) && (b < max)){
printf("从小到大排序为:%d %d %d\n", min, b, max);
}else{
printf("从小到大排序为:%d %d %d\n", min, c, max);
}
return 0;
}
[root@localhost ~]# ./a.out
请输入三个数字,以便从小到大进行排序:11 96 2
从小到大排序为:2 11 96
题目:输入年,判断是闰年(leap year)还是平年(nonleap year)
闰年:能够被4整除但是不能被100整除 或者 能够被400整除
#include
int main()
{
int x;
printf("please input year:");
scanf("%d",&x);
if((x%400==0||x%4==0)&&x%100!=0)
{
printf("今年是闰年\n");
}
else
{
printf("今年是平年\n");
}
return 0;
}
[root@localhost ~]# gcc model.c
[root@localhost ~]# ./a.out
please input year:2018
今年是平年
[root@localhost ~]# ./a.out
please input year:2040
今年是闰年
for 循环一般格式:
for(expression1; expression2; expression3)
{
循环体;
}
for 循环执行过程:
先求解表达式1; (一般表达式1都是一个赋值语句)。
求解表达式2,若为真,进入循环,执行循环体一次,然后再去执行表达式3;若为假,循环结束,执行循环后的语句。
表达式2一般是条件判断,会得到逻辑值。
表达式3一般是一个自增或者自减运算,是一个改变变量的语句。执行完表达式3,然后再去跳到表达式2去执行,若为真,进入循环,执行循环体一次,然后再去执行表达式3;直到表达式2为假,循环结束。
注意:
for 循环实例如下:
#include
int main()
{
int i = 0;
for( ; i <= 5; ){
i++;
printf("i = %d\n",i);
}
printf("iiiiiii = %d\n",i);
return 0;
}
[root@localhost ~]# gcc model.c
[root@localhost ~]# ./a.out
i = 1
i = 2
i = 3
i = 4
i = 5
i = 6
iiiiiii = 6
#include
int main()
{
int array[5];
int i;
for(i = 0; i < sizeof(array) / sizeof(int); i++)
{
printf("请输入数组array的第%d个数据:",i);
scanf("%d",&array[i]);
}
for(i = 0; i < sizeof(array) / sizeof(int); i++)
{
printf("array[%d] = %d\n",i,array[i]);
}
return 0;
}
[root@localhost ~]# gcc model.c
[root@localhost ~]# ./a.out
请输入数组array的第0个数据:1
请输入数组array的第1个数据:2
请输入数组array的第2个数据:3
请输入数组array的第3个数据:4
请输入数组array的第4个数据:5
array[0] = 1
array[1] = 2
array[2] = 3
array[3] = 4
array[4] = 5
#include
int main()
{
int i = 0 , j = 0;
for( i = 0; i < 4; i++)
{
printf("i = %d\n",i);
for(; j < 5; j++)
{
printf("j = %d\n",j);
}
putchar(10);
}
return 0;
}
[root@localhost ~]# gcc model.c
[root@localhost ~]# ./a.out
i = 0
j = 0
j = 1
j = 2
j = 3
j = 4
i = 1
i = 2
i = 3
#include
int main()
{
int i = 0, j = 0;
char c;
for(i = 0 ; i < 6; i++) // 外层循环控制输出行数
{
c = 'F';
for(j = 1; j <= i ; j++) // 内层循环控制列数
{
putchar('_');
}
for(j = 0 ;j <= i ; j++ )
{
putchar(c-j);
}
putchar('\n');
}
return 0;
}
[root@localhost ~]# gcc model.c
[root@localhost ~]# ./a.out
F
_FE
__FED
___FEDC
____FEDCB
_____FEDCBA
题目:九九乘法表
#include
int main()
{
int i ,j;
for(i = 1 ; i <= 9 ;i++)
{
for(j = 1; j <= i; j++)
{
printf("%d * %d = %d\t",j,i,i*j);
}
putchar(10);
}
return 0;
}
[root@localhost ~]# gcc model.c
[root@localhost ~]# ./a.out
1 * 1 = 1
1 * 2 = 2 2 * 2 = 4
1 * 3 = 3 2 * 3 = 6 3 * 3 = 9
1 * 4 = 4 2 * 4 = 8 3 * 4 = 12 4 * 4 = 16
1 * 5 = 5 2 * 5 = 10 3 * 5 = 15 4 * 5 = 20 5 * 5 = 25
1 * 6 = 6 2 * 6 = 12 3 * 6 = 18 4 * 6 = 24 5 * 6 = 30 6 * 6 = 36
1 * 7 = 7 2 * 7 = 14 3 * 7 = 21 4 * 7 = 28 5 * 7 = 35 6 * 7 = 42 7 * 7 = 49
1 * 8 = 8 2 * 8 = 16 3 * 8 = 24 4 * 8 = 32 5 * 8 = 40 6 * 8 = 48 7 * 8 = 56 8 * 8 = 64
1 * 9 = 9 2 * 9 = 18 3 * 9 = 27 4 * 9 = 36 5 * 9 = 45 6 * 9 = 54 7 * 9 = 63 8 * 9 = 72 9 * 9 = 81
题目:输出1000以内的水仙花数(个位、十位、百位数的各个位数的立方和与原数值相等)
#include
int main(){
int ge, shi, bai, sum;
int i = 0;
for(; i < 1000; i++){
ge = i % 10;
shi = (i / 10) % 10;
bai = i / 100;
sum = (ge * ge * ge) + (shi * shi * shi) + (bai * bai * bai);
if(i == sum){
printf("%d 是水仙花数\n",i);
}
}
return 0;
}
[root@localhost ~]# gcc model.c
[root@localhost ~]# ./a.out
0 是水仙花数
1 是水仙花数
153 是水仙花数
370 是水仙花数
371 是水仙花数
407 是水仙花数
题目:1到10的累加和
#include
int main()
{
int i = 0;
int sum = 0;
loop:
if(i++ < 10)
{
sum += i;
goto loop;
}
printf("sum = %d\n",sum);
END:
puts("This is End!");
return 0;
}
[root@localhost ~]# gcc model.c
[root@localhost ~]# ./a.out
sum = 55
This is End!
#include
int main()
{
int sum = 0,i = 0;
for(i = 1; i <= 10 ;i++)
{
sum += i;
}
printf("sum = %d\n",sum);
}
[root@localhost ~]# gcc model.c
[root@localhost ~]# ./a.out
sum = 55
while 语句构成循环的一般形式
while (表达式) //直到表达式为假,循环才真正结束
{
statatments;
}
#include
int main()
{
int i = 10;
int sum = 0;
while(i--)
{
sum += i;
printf("i = %d\n",i);
}
printf("sum = %d\n",sum);
return 0;
}
[root@localhost ~]# gcc model.c
[root@localhost ~]# ./a.out
i = 9
i = 8
i = 7
i = 6
i = 5
i = 4
i = 3
i = 2
i = 1
i = 0
sum = 45
do-while语句构成循环一般形式
do{
statatments;
}while(表达式); //后面是有一个分号的
goto:标号,直接跳转到标号所在的位置,灵活度很大,破坏程序正常执行过程,所以慎用!
#include
int main()
{
int i = 0;
for( i = 0; i< 10; i++)
{
if(3 == i)
{
goto END;
}
printf("i = %d\n",i);
}
END:
puts("This is End!");
return 0;
}
[root@localhost ~]# gcc model.c
[root@localhost ~]# ./a.out
i = 0
i = 1
i = 2
This is End!
#include
int main()
{
int i = 0;
int sum = 0;
loop:
if(i++ < 10)
{
sum += i;
goto loop;
}
printf("sum = %d\n",sum);
END:
puts("This is End!");
return 0;
}
[root@localhost ~]# gcc model.c
[root@localhost ~]# ./a.out
sum = 55
This is End!
break语句用于从循环体内跳出,即提前结束循环。break只能用在循环语句和switch语句中跳出switch循环。
continue语句结束只是本次循环,后续循环继续执行。
continue与break的区别:continue只结束本次循环,而break终止本层循环.
#include
int main()
{
int i , j;
for(i = 0 ; i < 5; i++)
{
printf("i = %d\n",i);
for(j = 0; j < 4; j++ )
{
if(1 == j)
{
// printf( "########j = %d\n",j);
// break; //结束break所在的那个 整个循环
continue; //结束当前这一次循环
// goto end;
}
printf("j = %d\n",j);
}
printf("This is End!\n");
}
end:
printf("fffff!\n");
return 0;
}
[root@localhost ~]# gcc model.c
[root@localhost ~]# ./a.out
i = 0
j = 0
j = 2
j = 3
This is End!
i = 1
j = 0
j = 2
j = 3
This is End!
i = 2
j = 0
j = 2
j = 3
This is End!
i = 3
j = 0
j = 2
j = 3
This is End!
i = 4
j = 0
j = 2
j = 3
This is End!
fffff!
#include
int main()
{
int i , j;
for(i = 0 ; i < 5; i++)
{
printf("i = %d\n",i);
for(j = 0; j < 4; j++ )
{
if(1 == j)
{
// printf( "########j = %d\n",j);
break; //结束break所在的那个 整个循环
//continue; //结束当前这一次循环
// goto end;
}
printf("j = %d\n",j);
}
printf("This is End!\n");
}
end:
printf("fffff!\n");
return 0;
}
[root@localhost ~]# gcc model.c
[root@localhost ~]# ./a.out
i = 0
j = 0
This is End!
i = 1
j = 0
This is End!
i = 2
j = 0
This is End!
i = 3
j = 0
This is End!
i = 4
j = 0
This is End!
fffff!
return:结束函数
#include
int main()
{
int i = 0, j = 0;
for(i = 0; i < 4; i++)
{
for(j = 0; j< 5; j++)
{
printf("ii = %d\tjj = %d\n",i,j);
}
printf("i = %d\tj = %d\n",i,j);
return -1; //结束函数
}
return 0;
}
[root@localhost ~]# gcc model.c
[root@localhost ~]# ./a.out
ii = 0 jj = 0
ii = 0 jj = 1
ii = 0 jj = 2
ii = 0 jj = 3
ii = 0 jj = 4
i = 0 j = 5
数组:构造数据类型之一 int a[6]
数组是具有一定顺序关系的若干个变量的集合,组成数组的各个变量称为数组的元素。
数组中各元素的数据类型要求相同,用数组名和下标确定。数组可以是一维的,也可以是多维的。声明了一个数组,数组的数据类型是 int,也就代表这个数组中的元素都是 int 数据类型:
a 是一维数组的数组名,遵循标识符的命名规则;
[] 代表这是一个一维数组;
10 代表这个一维数组可以存储10个元素;
数组是具有一定顺序关系的若干个变量的集合;
数组的每个元素在内存当中是地址空间连续的;
数组名表示这个数组在内存中存放的那片连续内存的首地址,是地址常量;
每个元素所占有的地址空间大小是由数据类型决定的;
编译时分配连续内存,内存字节数 = 数组维数 * sizeof(元素数据类型);
#include
int main()
{
int a[10];
printf("%d\n",10 * sizeof(int));
return 0;
}
[root@localhost ~]# gcc model.c
[root@localhost ~]# ./a.out
40
#include
int main()
{
int a[] = {1,4,5,3}; //全部初始化
//a[0] = 1; //部分初始化,没有被初始化的元素默认值为零
//a[1] = 4;
//a[2] = 5;
//a[3] = 3;
int i;
for(i = 0; i< 4; i++)
{
printf("%d\n",a[i]);
}
return 0;
}
[root@localhost ~]# gcc model.c
[root@localhost ~]# ./a.out
1
4
5
3
题目:计算Fibonacci数列前10项并逆序给出结果。(某一项等于前两项的数据和)
ex:1 1 2 3 5 8 13 21 34 55
#include
int main()
{
int i;
int a[10];
a[0] = a[1] = 1;
for(i = 2; i < 10; i++)
{
a[i] = a[i-1] + a[i-2];
}
printf("Fibonacci 数列前10项逆序输出为:");
for(i = 9; i >=0 ; i--)
{
printf("%d\t", a[i]);
}
return 0;
}
[root@localhost ~]# gcc model.c
[root@localhost ~]# ./a.out
Fibonacci 数列前10项逆序输出为:55 34 21 13 8 5 3 2 1 1
冒泡排序
a[0]>a[1]
,则交换;然后比较第二个数与第三个数;依次类推,直至第n-1个数和第n个数比较为止——第一趟冒泡排序,结果最大的数被安置在最后一个元素位置上;ex:5,1,3,8,7
5 > 1 1 5 3 8 7
5 > 3 1 3 5 8 7
5 > 8 1 3 5 8 7
8 > 7 1 3 5 7 8
#include
#define Size 5
typedef int ElemType;
void BubbleSort(ElemType arr[]){
for (int i = 0; i < Size; i++)
{
for (int j = 0; j < Size - i - 1; j++)
{
if (arr[j] > arr[j + 1])
{
ElemType temp = arr[j];
arr[j] = arr[j + 1];
arr[j + 1] = temp;
}
}
}
}
int main()
{
ElemType a[Size]={5,1,3,8,0};
BubbleSort(a);
for(int i = 0; i < Size; i++)
printf("a[%d] = %d\n", i, a[i]);
return 0;
}
[root@localhost ~]# gcc model.c
[root@localhost ~]# ./a.out
a[0] = 0
a[1] = 1
a[2] = 3
a[3] = 5
a[4] = 8
简单选择法排序
本质:依次比较第一个数和后续所有数据,找到最大/小数据进行交换,将最大/小数据放到最后,以此类推,循环找到最大或最小数据进行排序;
#include
#define Size 5
typedef int ElemType;
void SelectionSort(ElemType arr[]){
for (int i = 0; i < Size - 1; i++)
{
int minIndex = i;
for (int j = i + 1; j < Size; j++)
{
if (arr[j] < arr[minIndex])
{
minIndex = j;
}
}
ElemType temp = arr[i];
arr[i] = arr[minIndex];
arr[minIndex] = temp;
}
}
int main()
{
ElemType a[Size]={5,1,3,8,0};
SelectionSort(a);
for(int i = 0; i < Size; i++)
printf("a[%d] = %d\n", i, a[i]);
return 0;
}
[root@localhost ~]# ./a.out
a[0] = 0
a[1] = 1
a[2] = 3
a[3] = 5
a[4] = 8
1000以内的所有完数。( 完数:完美的数,一个数的所有因子,除去它本身相加还等于这个数,则这个数称之为完数)
#include"stdio.h"
int main()
{
int j,k,sum;
for(k=2;k<=1000;k++)
{
sum =0;
for(j=1;j<k;j++)
{
if(k%j==0)
sum+=j;
}
if(sum==k)
{
printf("%d\n",k);
}
}
return 0;
}
[root@localhost ~]# gcc model.c
[root@localhost ~]# ./a.out
6
28
496
求100以内所有的质数。(质数:只能够1和它本身整除)
#include"stdio.h"
int main()
{
int s,i,j;
for(i=3;i<=100;i++)
{
for(s=0,j=2;j<i;j++)
{
if(i%j==0)
{
s=1;
break;
}
}
if(s!=1)
printf("%d ",i);
}
return 0;
}
[root@localhost ~]# gcc model.c
[root@localhost ~]# ./a.out
3 5 7 11 13 17 19 23 29 31 37 41 43 47 53 59 61 67 71 73 79 83 89 97
从外部输入数组元素,找出数组里面的最大值
#include"stdio.h"
int main()
{
int a[10],i,j,t;
printf("input 10 numbers:\n");
for (i=0; i<10; i++)
scanf("%d",&a[i]);
for (i=0; i<10; i++)
{
t=i;
for (j=i+1; j<10; j++)
{
if(a[t]<a[j])
t=j;
}
printf("max num is:%d\n",a[t]);
break;
}
return 0;
}
[root@localhost ~]# gcc model.c
[root@localhost ~]# ./a.out
input 10 numbers:
17 2 4 5 9 21 23 22 7 9
max num is:23
gdb调试方法:https://www.cnblogs.com/life2refuel/p/5396538.html
区分:
字符串常量:
char *a = "Hello World!"
(默认带’\0’);
char a[] = "Hello World"
(字符数组默认加’\0’);
字符常量: char a = 'H'
(字符常量不带’\0’);
二维数组一般形式如下:
<存储类型> <数据类型> <数组名>[<常量表达式1>][<常量表达式2>];
int a[3][4]
:声明了一个int型的二维数组,每个数组成员的数据类型是int,这个数组有 3 * 4 = 12个成员,二维数组也是通过数组名+下标的方式表示数组的元素。二维数组是按行序优先 。
int a[3][4]
:这是一个3行四列的数组,总共有三行,每行有四列 ,下标也是从0开始
第一行:
a[0][0] a[0][1] a[0][2] a[0][3]
第二行:
a[1][0] a[1][1] a[1][2] a[1][3]
第三行:
a[2][0] a[2][1] a[2][2] a[2][3]
#include
int main()
{
//int a[2][3] = {{2,5,12},{4,6,7}}; //全部初始化
//int a[2][3] = {2,5,12,4,6,7}; //全部初始化
//int a[2][3] = {{2,5,12},{4,7}}; //按行部分初始化
//int a[2][3] = {2,5,12,4,7}; //部分初始化
#if 0
int a[2][3];
a[0][0] = 2;
a[0][1] = 5;
a[0][2] = 12;
a[1][0] = 4;
a[1][1] = 7;
a[1][2] = 0;
#endif
//int a[2][3] = {{2,5,12},{6,7}}; //全部初始化
//int a[][3] = {6,2,5,12,7}; //部分初始化
int a[2][3]; //部分初始化
int i,j;
for(i = 0; i < 2; i++) //行数
{
for(j = 0; j < 3; j++) //列数
{
printf("a[%d][%d] = %d\n",i, j, a[i][j]);
}
}
return 0;
}
[root@localhost ~]# gcc model.c
[root@localhost ~]# ./a.out
a[0][0] = 4198832
a[0][1] = 0
a[0][2] = 4198464
a[1][0] = 0
a[1][1] = -1491004464
a[1][2] = 32766
#include
int main(){
int i = 0;
char a[5]={'a','b','5','8','9','\0'};
for(i = 0; i < 6; i++){
printf("%p\n", &a[i]);
}
printf("%s\n", a);
for(i = 0; i < 5; i++){
putchar(a[i]);
}
putchar(10);
return 0;
}
[root@localhost tt]# gcc tt.c
tt.c: 在函数‘main’中:
tt.c:4:33: 警告:数组初始值设定项中有多余的元素
char a[5]={'a','b','5','8','9','\0'};
^~~~
tt.c:4:33: 附注:(在‘a’的初始化附近)
[root@localhost tt]# ls
a.out tt.c
[root@localhost tt]# ./a.out
0x7fff19b4bdb7
0x7fff19b4bdb8
0x7fff19b4bdb9
0x7fff19b4bdba
0x7fff19b4bdbb
0x7fff19b4bdbc
ab589
ab589
#include
int main(){
int a[2][3];
int i, j;
for(i = 0; i < 2; i++){
for(j = 0; j < 3; j++){
scanf("%d", &a[i][j]);
}
}
int max=a[0][0];
int l, r;
for(i = 0; i < 2; i++){
for(j = 0; j < 3; j++){
if(max < a[i][j]){
max = a[i][j];
l = i;
r = j;
}
}
}
printf("l = %d\tr=%d\n", l+1, r+1);
return 0;
}
[root@localhost tt]# gcc tt.c
[root@localhost tt]# ./a.out
1
2
3
4
5
6
l = 2 r=3
#include
int main(){
char a[10] = {0};
int len = 0, i = 0;
while(len < 10 && (a[len++] = getchar()) != '\n');
for(i = 0; i < len - 1; i++){
putchar(a[i]);
putchar(32);
printf("%d\t", a[i]);
}
putchar('\n');
return 0;
}
[root@localhost tt]# gcc tt.c
[root@localhost tt]# ./a.out
1
1 49
[root@localhost tt]# ./a.out
5
5 53
[root@localhost tt]# ./a.out
[root@localhost tt]# ./a.out
b
b 98
二维数组,行数可以省略,列数不可以省略;
二维数组的初始化基本与一维数组类似,主要有以下几种方式:
二维数组在内存中是按照一维的方式存放的,所以,二维数组最后都可以转换为一维数组操作。
#include
int main()
{
char fruit[][7] = {"Apple","Orange","Grape","Pear","Peach"};
int i,j;
for(i = 0; i < 5; i++)
{
for(j = 0; j < 7; j++)
{
putchar(fruit[i][j]);
putchar(32);
}
}
putchar('\n');
return 0;
}
[root@localhost tt]# gcc tt.c
[root@localhost tt]# ./a.out
A p p l e O r a n g e G r a p e P e a r P e a c h
字符串连接函数 strcat
格式:strcat(字符数组1,字符数组2)
#include
#include
int main()
{
char str1[20] = "Hello"; //一维数组的数组名是一个地址常量,代表一维数组的首地址
char str2[]= "World";
//返回字符数组1的首地址
//printf("%s\n",strcat(str1,str2)); //得到一个新的字符串,字符串的内容都存在字符数组1里面
//字符数组1要足够大,能够存下字符数组1 + 字符数组2
//printf("%s\n",str1);
puts(strcat(str1,str2));
puts(str1);
return 0;
}
[root@localhost tt]# gcc tt.c
[root@localhost tt]# ./a.out
HelloWorld!
HelloWorld!
字符串拷贝函数 strcpy
格式:strcpy(字符数组1,字符串2);
说明:字符数组1必须足够大,拷贝时‘\0’一同拷贝,不能使用赋值语句为一个字符数组赋值
#include
#include
int main()
{
char dest[20]= "abc";
strcpy(dest,"Hello"); //把字符串拷贝到字符数组中
puts(dest); //返回字符串实际长度,虽然dest字符数组在内存中占6个字节
int num = strlen(dest); //strlen函数求字符串长度,是不包括‘\0’在内,所以字符串长度为5
printf("num = %d\n",num);
return 0;
}
[root@localhost tt]# gcc tt.c
[root@localhost tt]# ./a.out
Hello
num = 5
字符串长度函数strlen格式:strlen
(字符数组)
字符串比较函数 strcmp
格式:strcmp(字符串1,字符串2);
功能:比较两个字符串;
比较规则:对两串从左向右逐个字符比较(ASCII码),直到遇到不同字符或‘\0’为止;
返回值:返回int型整数
若字符串1 < 字符串2, 返回负整数;
若字符串1 > 字符串2,返回正整数;
若字符串1== 字符串2, 返回零;
说明:字符串比较不能用“==”,必须用 strcmp
#include
#include
int main()
{
//str1 和 str2 逐个字符比较,实际比较的是相应字符的ASCII值
//如果相应的两个字符不一样,ASCII值比较:
//字符1 《 字符2 返回负整数
//字符1 》 字符2 返回正整数
char str1[] = "Hedl";
char str2[] = "Hello";
int result = strcmp(str1,str2);
printf("%d\n",result);
return 0;
}
[root@localhost tt]# gcc tt.c
[root@localhost tt]# ./a.out
-8
输入一个字符串,然后将其逆序输出
#include
int main(){
int i = 0;
char s[100];
printf("请输入一个字符串:");
gets(s);
while(s[i] != '\0'){
i++;
}
for(; i >= 0; i--){
printf(" %c ", s[i]);
}
return 0;
}
[root@localhost ~]# gcc tt.c
tt.c: 在函数‘main’中:
tt.c:6:2: 警告:implicit declaration of function ‘gets’; did you mean ‘fgets’? [-Wimplicit-function-declaration]
gets(s);
^~~~
fgets
/usr/bin/ld: /tmp/cc1oEZCj.o: in function `main':
tt.c:(.text+0x2b): 警告:the `gets' function is dangerous and should not be used.
[root@localhost ~]# ./a.out
请输入一个字符串:hello world!
! d l r o w o l l e h
实现strlen函数的功能
#include
int main()
{
int i=0;
char s[100];
printf("请输入一个字符串:");
gets(s);
while(s[i]!='\0')
{
i++;
}
printf("%d\n",i);
return 0;
}
[root@localhost ~]# gcc tt.c
tt.c: 在函数‘main’中:
tt.c:6:2: 警告:implicit declaration of function ‘gets’; did you mean ‘fgets’? [-Wimplicit-function-declaration]
gets(s);
^~~~
fgets
/usr/bin/ld: /tmp/ccc0ClTI.o: in function `main':
tt.c:(.text+0x2b): 警告:the `gets' function is dangerous and should not be used.
[root@localhost ~]# ./a.out
请输入一个字符串:nihaoya
7
实现strcpy函数的功能(s2开辟空间过大会打印乱码)
#include
int main()
{
char s1[]="helloworld";
char s2[100];
int i;
for(i=0;i<sizeof(s1);i++)
{
s2[i]=s1[i];
}
s2[i]='\0';
for(i=0;s2[i]!='\0';i++)
{
printf(" %c ",s2[i]);
}
return 0;
}
[root@localhost ~]# gcc tt.c
[root@localhost ~]# ./a.out
h e l l o w o r l d
杨辉三角
#include
#define N 10
int main()
{
int i,j;
int a[N][N] = {0};
for(i = 0; i< N; i++)
{
a[i][0] = 1;
}
for(i = 1; i < N; i++)
{
for(j = 1; j <= i ;j++)
{
a[i][j] = a[i-1][j -1] + a[i-1][j];
}
}
for(i = 0; i < N; i++)
{
for(j = 0; j <=i; j++)
{
printf("%d\t",a[i][j]);
}
putchar(10);
}
}
[root@localhost ~]# gcc tt.c
[root@localhost ~]# ./a.out
1
1 1
1 2 1
1 3 3 1
1 4 6 4 1
1 5 10 10 5 1
1 6 15 20 15 6 1
1 7 21 35 35 21 7 1
1 8 28 56 70 56 28 8 1
1 9 36 84 126 126 84 36 9 1
在计算机内部存储器(简称内存)中,每一个字节单元,都有一个编号,称为地址。
在C语言中,内存单元的地址称为指针,专门用来存放地址的变量,称为指针变量(pointer variable)。翻译过来就是,指针变量专门用来存放地址的,有了地址,我们才能去操作内存!
一般形式如下:<存储类型> <数据类型> *<指针变量名> ;指针说明时指定的数据类型不是指针变量本身的数据类型,而是指针目标的数据类型。简称为指针的数据类型。
*
有两种用意:
int *p = &a;
*
是在声明一个指针变量 *
;*p = 90;
*
取内容,是对 p
指向的那片内存空间赋值;指针的算术运算实质就是地址运算:
p + n
地址就是 : p + n * sizeof(数据类型);p - n
地址就是 : p - n * sizeof(数据类型);p++ =》p = p + 1
: 最后也是转化成 p + 1 * sizeof(数据类型),只不过最后要改变p的值;二维数组名代表数组的起始地址,数组名加1,是移动一行元素。因此,二维数组名常被称为行地址、行指针。存储行地址的指针变量,叫做行指针变量。
int a[2][3]; int (*p)[3] = a;
p
就是一个行指针,p+1
移动的是一行。*(p+1)
这个*
号是将行指针降级为列指针,*(p+1)+1
就是移动一个元素 ;
char数据类型的指针变量称为字符指针变量;
指针数组:是指由若干个具有相同存储类型和数据类型的指针变量构成的集合。指针变量数组的一般说明形式:<存储类型> <数据类型> *<指针变量数组名>[<大小>];
函数:是一个完成特定功能的代码模块,其程序代码独立,通常要求有返回值,也可以是空值。
一般形式如下:
<数据类型> <函数名称>( <形式参数说明> ){
语句序列;
return[(<表达式>)];
}
指针函数:是指一个函数的返回值为地址量的函数。(括号中的后读,猪脚总是最后登场):int *f(x,y);
指针函数的定义的一般形式如下:
<数据类型> *<函数名称>(<参数说明>){
语句序列;
}
函数指针:是用来存放函数的地址,这个地址是一个函数的入口地址。函数指针变量说明的一般形式如下:<数据类型> (*<函数指针名称>)(<参数说明列表>);int (*f) (int x);