【C语言程序设计】C语言知识点汇总1——变量、运算符、格式化输入输出、函数

简介: 【C语言程序设计】C语言知识点汇总1——变量、运算符、格式化输入输出、函数

1 C语言概述


这一章无重点内容。


1.1 ASCII

第一部分是:ASCII非打印控制字符;

第二部分是:ASCII打印字符;

第三部分是:扩展ASCII打印字符


ASCII表上的数字0–31分配给了控制字符,用于控制像打印机等一些外围设备。例如,12代表换页/新页功能。此命令指示打印机跳到下一页的开头。(参详ASCII码表中0-31)


记忆:48-0;65-A;97-a;先大写后小写

image.png

image.png

image.png


特殊字符解释

image.png


2 数据类型、运算符与表达式


2.1 标识符

标识符:用来标识常量、变量、函数等字符序列;


组成:

  • 只能有字母、数字、下划线组成,且第一个字符必须是字母或下划线
  • 区分大小写


2.2 关键字

关键字:C语言中已经被预先定义并使用的标识符,总共有32个(下文罗列关键字带注释为不理解的部分,需要另外花时间)


数据类型关键字:

  • void
  • char
  • float
  • double


类型修饰符

  • short
  • long
  • sighed
  • unsighed


复杂类型关键字

  • struct
  • union:共用体声明
  • enum:枚举声明:

https://blog.csdn.net/xingjiarong/article/details/47275971

  • typedef:声明类型别名
  • sizeof:得到特定类型或特定类型变量的大小


存储级别关键字

  • auto:指定为自动变量,由编译器自动分配及释放,通常在栈上分配
  • static:作为静态变量,分配在静态变量区,修饰函数时,指定函数作用域为文件内部
  • register:寄存器变量
  • extern :指定对应变量为外部变量,提示编译器遇到此变量和函数时在其他模块中寻找其定义:

https://blog.csdn.net/xingjiarong/article/details/47656339

  • const:与volatile合称“CV特性”,指定变量的值不可被当前线程/进程改变

https://blog.csdn.net/xingjiarong/article/details/47282255

  • volatile:指定变量的值有可能会被系统或其他进程/线程改变,强制编译器每次从内存中取得该变量。


A跳转结构

  • return
  • continue
  • break
  • goto


B分支结构

  • if
  • else
  • switch
  • case
  • default


C循环结构

  • do
  • for
  • while


特殊的标识符:他们没被列入关键字,却也有特定的含义。

如:define、include、under、if


new的用法:

使用new运算符时必须已知数据类型,new运算符会向系统堆区申请足够的存储空间,如果申请成功,就返回该内存块的首地址,如果申请不成功,则返回零值。


一般使用格式:


格式1:指针变量名=new 类型标识符;


格式2:指针变量名=new 类型标识符(初始值);


格式3:指针变量名=new 类型标识符 [内存单元个数];


int *a=new int;
int *a = new int(5); 作用同上,但是同时将整数空间赋值为5
int *a=new int [5];


2.3 整型常量

  1. 了解各个进制的表示范围
  2. 0开头八进制,0x开头16进制(八进制不能出现>8)


2.4 实型常量

这类题易错重点关注


表示方式:


  1. 十进制表示形式:
  • .123
  • 123.0
  • 0.0
  • 123.


  1. (*)指数表示形式(e或E之前必须有数字,且指数必须为整数:指数是e后面的哦!)
  • 12.3e3:12.3*10^3
  • 123e2:123*10^2
  • 78e-1:78*10^-1


2.5 字符型常量与字符串常量

区别

  • 形式上:单双引号的区别,并且字符串尾后者多一个’\0’,(区分问法是所占空间还是长度)
  • 赋值
//字符串数组,只能在定义的时候,通过=赋初值,如果先定义,在赋值就不可以
{
    1. 定义的时候直接用字符串赋值
    char a[10]="hello";
//注意:不能先定义再给它赋值,如char a[10]; a[10]="hello";这样是错误的。
    2. 对数组中字符逐个赋值
    char a[10]={'h','e','l','l','o'};
//字符串可以赋值给字符指针变量,或者将字符串用字符数组保存。
    3. 先定义,后利用strcpy赋值
  char a[10];
  strcpy(a, "hello");
//strcpy是一种C语言的标准库函数,strcpy把含有'\0'结束符的字符串复制到另一个地址空间,返回值的类型为char*。
//函数实现还是通过数组一个个操作赋值。
}
//单字符赋值,可通过数组下标方式或指针方式,引用数组元素,进行
{
    char a[10];
  char ch='a';
  for(i=0;i<10;i++)
     a[i]=ch+i ; //可通过数组下标引用数组元素,完成赋值
  char *p;
  for(p=a; p<a+10; p++)
    *p=ch++; //通过指针对数组相应元素赋值
}


2.6 (*)不同变量所占空间

在不同及其中所占空间可能有不同,但大小关系(char1<int2<=short2<=long4<=float4<double8)


2.7 (*)运算符的优先级

a1ef6afec6954268b887ac2009165b6e.jpg


3.9 位运算符与位运算表达式

  • 逻辑运算符:!优先于&&优先于||
  • 位运算符

按位非(取反)~

&

|

按位异或:^

左移:右边低位补零

int a=15,x;
x=a<<2;//求x
a:00001111
a<<2:
00111100


  • 右移:>>

若a是有符号数,则高位补符号位

若a是无符号数,则高位补0

char a=-4,b=4,x,y;
x=a>>2;
y=b>>2;
a:11111100(负数的补码形式不要忘)
a>>2:11111111,十进制为-1;

 

2.10 数据类型转换

自动转换:将复制运算符的右边数据转换为左边变量的数据类型,然后赋值


3 格式化输入输出语句


许多小细节,令人抓狂


3.1 printf

1 打印整数

d格式符:用来输出十进制(decimal)


  • md:输出宽度占m个字符

若小于m,左端补空格,若大于m,则按照实际位数输出

-md为左对齐

  • +d:数据带有正负号
  • 0md:如有前导空格,以0补齐(注意是在前面哦)
  • ld:输出长整型数据,同样可以指定宽度
  • *:动态域宽设置
int y=-3456;
  printf("%8d\n",y);//1
  printf("%+8d\n",y);//2
  printf("%08d\n",y);
  printf("y=%-8d",y);
  printf("y=%-08d\n",y);  
//output
   -3456
   -3456
-0003456
y=-3456   y=-3456
//在devc++中跑完之后发现,这里添加1,2两句效果相同;期初我认为+是不是不起作用了,将y的数值改为正数可发现1式无+,2式有+
//最后两句都有4个空格


/*动态域宽设置*/
int i=1;
printf("##%*d\n",i,i);
i++;
printf("##%*d\n",i,i);
i++;
printf("##%*d",i,i);
//output
##1
## 2
##  3
/*注意这里的*不是指空格的数量,如其名动态域宽设置,设置的为其域宽,当i等于1时其宽度为1*/


o格式符:以八进制(octal)形式输出整数

在前面添加#号,可以使数字按照八进制(0。。。)的形式输出


x格式符:以十六进制(hexadecimal)形式输出整数

在前面添加#号,同理


u格式符:以无符号(unsigned)十进制数输出


注:以上长整型,同样加’l’


//十六进制同理
  int y=123;
  printf("y=%8o\n",y);
  printf("%#8o",y);


short y=-1;
  printf("unsigned=%u",y);
//output
unsigned=4294967295;
//不难发现,负数在计算机内以补码形式存储,所以输出成无符号位的数字,需要把原先二进制转化为10进制


/*3.42 turb C 标准,16位微机中int=short=2byte */
  int x,y,z;
  long m;
  y=(x=32767,x-1);//逗号运算符从左往右
  z=m=0xffff;
//output
y=32766;
z=-1;
m=65535;
//int两个字节,16——>二进制(11111111),计算机中有符号表示为-1,如果int输出为%u,同样是65535;


2 打印浮点数

f格式符


  • mf:
  • m.nf

整个输出占m个字符宽度,右对齐(若超出则按原样输出)

小数部分截短至n个字符

可直接用.nf

  • 同样可以在前面添加**+,-,0**


注意点:

  1. 默认小数点后六位
  2. 单精度精确到8位,双精度精确到16位。
  3. float和double都会被转换成double然后送给printf函数 所以其实用%f还是%lf输出其实并不重要,输入时,%lf表示地址对应的是8字节的double,%f表示地址对应的是4字节的float……存储方式都不一样,混用了肯定会出问题
printf("%f",1.12345678);
//实际输出为1.123457,因为保留6位有效数字,所以第七位要四舍五入到第六位。
printf("%.18f\n",1.12345678901234567890);
//下方实数末尾的f表示单精度浮点数,只存储7位有效数字
printf("%.18f\n",1.12345678901234567890f);


g格式符:(自动选择)

采用g格式符输出数据时

  • 当数据<=10-5或>=107时,按指数方式输出
  • 否则按小数方式输出
double a=1000000000; 
 double b=123.456; 
 printf("%e\n",a);
 printf("%f\n",a);
 printf("%g\n",a);
 printf("%e\n",b);
 printf("%f\n",b);
 printf("%g\n",b);


e格式符:以十的指数形式输出


3 打印字符、字符串

c格式符:用来输出一个字符(character)


printf("\n*s1=%15s*","chinabeijing");
printf("\n*s21=%-5s*","chi");
//output
*s1=   chinabeijing*
*s21=chi  *
/*凡是设置了字符宽度,默认情况下就是右对齐,若前面有负号才改为左对齐*/


s格式符:用来输出一个字符串(string)


  • .ms表示只输出字符串的前m个字符


3.2 (*)scanf

1格式

scanf(格式控制字符串,输入表列);


2 用法

输入字符的情况:

/*用法有三种,最易错的为%c*/
{
    char c1,c2,c3;
    scanf("%c%c%c",&c1,&c2,&c3);
}
//若此时输入a_b_c;
//output
a b
/*原因在于scanf会把空格当成字符进行存储*/


遇到字符与数字一同是输入内容的情况:

  • 数字之间要用空格
  • 数字与字符之间,不能用空格


输入浮点数的情况:

{
    float f;
    scanf("%f",&f);
    double b;
  scanf("%lf",&d);
}
/*float和double都会被转换成double然后送给printf函数 所以其实用%f还是%lf输出其实并不重要;
输入%lf表示地址对应的是8字节的double,%f表示地址对应的是4字节的float……存储方式都不一样,混用了肯定会出问题*/


输入中带*情况的处理:

{
    scanf("%d%*d%d",&a,&c);
    //计算机读入三个数,把第一个与第三个分别存入a和c
    //多了*表示读入但不赋值给变量
}


4 逻辑运算和判断选取控制


4.1 逻辑表达式

C的真值表示

  • 真:1,非0数看作“真”
  • 假:0


短路现象

  • 计算表达式1&&表达式2 若表达式1为假,则能确定逻辑计算结果为假,表达式2不继续进行
  • 计算表达式1||表达式2 若表达式1为真,则能确定逻辑计算结果为真,,表达式2不继续进行


优先级

  • !优先于&&优先于||
  • 一般来说优先级为:从高到低(算数、关系、逻辑、赋值)
  • 特例:!优先于二目运算(原因在于!看作单目运算符)


4.2 条件运算符和条件表达式

表达式1?表达式2:表达式3


/*这个例子带你理解条件运算符从右到左是如何进行的*/
int a=1, b=3, c=2, d;
d = a>b ? a : c>b ? c : b; 
// 根据从右到左的结合顺序,则该表达式等价于d = (a>b ? a : (c>b ? c : b));
// 计算过程:
// 1、先算a>b,结果为0;
// 2、再算(c>b ? c : b),之后算c>b,结果为0,
// 3、所以最后结果为b的值,也即等于3
// 如果是从左到右的结合顺序,那么该表达式等价于d =((a>b ? a : c>b) ? c : b);
//计算过程:
// 1、先算a>b,结果为0;
// 2、再算c>b,结果为0;
// 3、所以d=b,结果为b的值,也即等于3


5 函数


5.1 函数的定义

//无参类型
void main() //类型标识符 函数名
{
}


//有参函数形式1
int max(int a,int b)//(类型名 形参)
{
    int z;
    z=a-b;
    return (z);
}
//有参函数形式2
int max(a,b) //(形参1,形参2)
int a,b;  //形参类型说明
{
    int z;
    z=a-b;
    return (z);
}
//空函数定义形式
int dummy
{
}


5.2 函数调用

5.2.3函数的参数

  • 形参:出现在函数定义的括号后面
  • 实参:出现在调用者的括号后面

实际参数通过函数调用的过程,将真实的值赋值给形式参数(里面的操作可能会对实际参数造成影响,绝大多数也可能没影响)


//交换两个数的一些好方法(不通过函数)
//方法1:使用一个临时变量来进行保存
{
    temp = a;
    a = b;
    b = temp;
}
//方法2:使用加减法来进行交换,这种方法实际上就是先把a+b的结果暂时先保存在变量a中,然后通过这改变后的a和原始的b进行减法就可以得到交换后的b,但是这种方法有一个缺陷,就是a和b都是int类型,a+b的结果可以越界。
{
    a = a + b;
    b = a - b;
    a = a - b;
}
//方法3:使用乘除法来进行交换,这种方法和方法2类似,只是用a*b代替a+b放在a中暂存,后面思路一样,这种方法有着和方法2一样的缺陷,就是越界问题,而且更加容易越界。
{
    a = a * b;
    b = a / b;
    a = a / b; 
}
//(妙)方法4:使用异或的方法来进行交换,这种方法不存在之前越界的缺陷,是一种很完美的方法,这种方法主要利用了异或的特性a^b的值先保存到a,因为a^b^b=a所以可以顺利完成交换。
{
    a = a ^ b;
    b = a ^ b;
    a = a ^ b;
}
//方法5:使用移位的方法,把原来的int类型的a,把a的值拆分成高16位和低16位,相当于多了16位的暂存空间可以周转,但是此方法的缺陷也显而易见,就是如果被赋值的a或者b超过了16位,这种方法就会发生错误。
{
    a <<= 16;
    a |= b;
    b = a >> 16;
    a = a & 0xffff;
}

 

等到指针部分可以有一些在函数体内完成对主函数内的元素进行交换。


5.2.4 函数的返回值

  • return:使函数中断,程序流程返回到主调函数,不返回值
  • return(表达式):中断,返回一个值给主调函

函数调用时,注意实参表求值的顺序并不确定,有的是从左到右,有的是从右至左,C-free按自右向左,因此要避免出现歧义的情况,这在群里争议过的题目中有体现!


关于函数调用时,实参求值顺序的一道题

int f(int a,int b)
{ 
  int c;
    if(a>b) c==1;
    else if(a==b) c=0;
    else c=-1;
    return (c);
}
int main()
{
    int i=2,p;
    p=f(i,++i);
    printf("%d",p);
}
//输出为0
int f(int a,int b)
{ 
  int c;
    if(a>b) c=1;
    else if(a==b) c=0;
    else c=-1;
    return (c);
}
int main()
{
    int i=2,p;
    p=f(i,i++);//改为i++
    printf("%d",p);
}
//输出为1


5.2.5 对被调函数的声明

  • 库函数的声明
#include<stdio.h>
#include"math.h"
//两者的差异需知晓,如果使用下方形式,则先在当前源文件所在目录进行寻找


  • 用户定义的函数声明

应用场景:主要是函数定义出现在了函数调用之后,所以要先对被调函数进行声明

//三种形式
int fun;//无参
int fun(int,char,int);//有参数,只含参数类型
int fun(int a,char c,int b);//有参数,含参数类型和参数名


5.3 (*)函数的递归调用

递归调用属于嵌套调用,但是我这里着重理解下递归调用


定义:间接或直接调用自身函数的递归调用


//递归调用求n!
int fac(int n)
{
  int f; 
    if(n==1||n==0) //递归的终结条件;
        f=1;
    else 
        f=n*fac(n-1);
    return f; 
}
int main() 
{
    printf("%d",fac(4));
    return 0;
}


递归要求:


递归定义必须是有确切意义的,


每经过一步可以变得更简单,规模要变小,


最终要能够终结,不能无限调用,


每次调用都需要判断能否达到结束条件。


目录
相关文章
|
9天前
|
C语言
c语言运算符
C的运算符有以下几种: 算术运算符:+、-、*、/、% 结合方向自左向右 关系运算符:>、<、==、>=、<=、!= 逻辑运算符:!、&&、|| 位运算符<<、>>、~、|、^、& 赋值运算符:=及符号扩展赋值运算符(+=、-=、*=、/=) 条件运算符:? : 逗号运算符:, 指针运算符:*、& 求字节运算符:sizeof 强制类型转换运算符:((类型)) 分量运算符:.、-> 下标运算符:[]
22 4
|
9天前
|
C语言
c语言调用的函数的声明
被调用的函数的声明: 一个函数调用另一个函数需具备的条件: 首先被调用的函数必须是已经存在的函数,即头文件中存在或已经定义过; 如果使用库函数,一般应该在本文件开头用#include命令将调用有关库函数时在所需要用到的信息“包含”到本文件中。.h文件是头文件所用的后缀。 如果使用用户自己定义的函数,而且该函数与使用它的函数在同一个文件中,一般还应该在主调函数中对被调用的函数做声明。 如果被调用的函数定义出现在主调函数之前可以不必声明。 如果已在所有函数定义之前,在函数的外部已做了函数声明,则在各个主调函数中不必多所调用的函数在做声明
25 6
|
22天前
|
存储 算法 程序员
C语言:库函数
C语言的库函数是预定义的函数,用于执行常见的编程任务,如输入输出、字符串处理、数学运算等。使用库函数可以简化编程工作,提高开发效率。C标准库提供了丰富的函数,满足各种需求。
|
28天前
|
机器学习/深度学习 C语言
【c语言】一篇文章搞懂函数递归
本文详细介绍了函数递归的概念、思想及其限制条件,并通过求阶乘、打印整数每一位和求斐波那契数等实例,展示了递归的应用。递归的核心在于将大问题分解为小问题,但需注意递归可能导致效率低下和栈溢出的问题。文章最后总结了递归的优缺点,提醒读者在实际编程中合理使用递归。
54 7
|
28天前
|
存储 编译器 程序员
【c语言】函数
本文介绍了C语言中函数的基本概念,包括库函数和自定义函数的定义、使用及示例。库函数如`printf`和`scanf`,通过包含相应的头文件即可使用。自定义函数需指定返回类型、函数名、形式参数等。文中还探讨了函数的调用、形参与实参的区别、return语句的用法、函数嵌套调用、链式访问以及static关键字对变量和函数的影响,强调了static如何改变变量的生命周期和作用域,以及函数的可见性。
29 4
|
25天前
|
存储 C语言
【c语言】字符串函数和内存函数
本文介绍了C语言中常用的字符串函数和内存函数,包括`strlen`、`strcpy`、`strcat`、`strcmp`、`strstr`、`strncpy`、`strncat`、`strncmp`、`strtok`、`memcpy`、`memmove`和`memset`等函数的使用方法及模拟实现。文章详细讲解了每个函数的功能、参数、返回值,并提供了具体的代码示例,帮助读者更好地理解和掌握这些函数的应用。
21 0
|
25天前
|
C语言
【c语言】qsort函数及泛型冒泡排序的模拟实现
本文介绍了C语言中的`qsort`函数及其背后的回调函数概念。`qsort`函数用于对任意类型的数据进行排序,其核心在于通过函数指针调用用户自定义的比较函数。文章还详细讲解了如何实现一个泛型冒泡排序,包括比较函数、交换函数和排序函数的编写,并展示了完整的代码示例。最后,通过实际运行验证了排序的正确性,展示了泛型编程的优势。
20 0
|
28天前
|
算法 C语言
factorial函数c语言
C语言中实现阶乘函数提供了直接循环和递归两种思路,各有优劣。循环实现更适用于大规模数值,避免了栈溢出风险;而递归实现则在代码简洁度上占优,但需警惕深度递归带来的潜在问题。在实际开发中,根据具体需求与环境选择合适的实现方式至关重要。
27 0
|
1月前
|
C语言 C++
C语言 之 内存函数
C语言 之 内存函数
34 3
|
29天前
|
存储 缓存 C语言
【c语言】简单的算术操作符、输入输出函数
本文介绍了C语言中的算术操作符、赋值操作符、单目操作符以及输入输出函数 `printf` 和 `scanf` 的基本用法。算术操作符包括加、减、乘、除和求余,其中除法和求余运算有特殊规则。赋值操作符用于给变量赋值,并支持复合赋值。单目操作符包括自增自减、正负号和强制类型转换。输入输出函数 `printf` 和 `scanf` 用于格式化输入和输出,支持多种占位符和格式控制。通过示例代码详细解释了这些操作符和函数的使用方法。
35 10