C语言 - 基础、理论(原码/反码/补码)、函数(字符串、定义)

概念

原码、反码、补码

原码 
一个数的原码(原始的二进制码)有如下特点:

  • 最高位作为符号位,0表示正,1表示负
  • 其他数值部分就是数值本身绝对值的二进制数
  • 负数的原码是在其绝对值的基础上,最高位变为1

下面数值以1字节的大小描述

十进制原码
+15 0000 1111
-15 1000 1111
+0 0000 0000
-0 1000 000

原码表示简单易懂,与带符号数本身转换方便,只要符号还原即可,但当两个正数相减或不同符号数相加时,必须比较两个数哪个绝对值大,才能决定谁减谁,才能决定结果是正还是负,所以 原码不便于加减运算 。

反码

  • 对于正数,反码与原码相同
  • 对于负数,符号位不变,其他部分取反(1变0,0变1)
十进制反码
+15 0000 111
-15 1111 0000
+0 0000 0000
-0 1111 1111

反码运算也不方便, 通常用来作为求补码的中间过度 。

补码

在计算机系统中,数值一律用补码来存储。

补码特点:

  • 对于正数,原码、反码、补码相同
  • 对于负数,其补码为它的反码加1
  • 补码符号位不动,其他位求反,最后整个数加1,得到原码
十进制反码
+15 0000 111
-15 1111 0001
+0 0000 0000
-0 0000 0000

例子 
在这里插入图片描述

在这里插入图片描述 
补码的意义

  • 取反 
    不管以原码方式存储,还是以反码方式存储,0也有两种表示形式。(用于区分符号位) 
    但是如果以补码方式存储, 补码统一了0的编码
  • 反码加一 (也可以理解位原码减一) 
    左移动

补码的意义

关键字

在这里插入图片描述

数据类型

在这里插入图片描述

几种基本数据类型的字符(Byte)大小(32位): 
在这里插入图片描述

short、int、long、long long

常量表示

整型常量所需类型
10 int
10l, 10L long
10u, 10U unsigned int
10ul, 10UL unsigned long
10ull, 10ULL unsigned long long

打印格式(进制维度)

打印格式含义
%的 有符号 十进制
%u 十进制 无符号
%o(字母o) 八进制
%x 十六进制 小写小写字母
%X 十六进制 大写字母

打印格式(类型维度)

打印格式含义
%hd short
%d int
%l long
%ll long long
%hu unsigned short
%u unsigned int
%lu unsigned long
%llu unsigned long long
                      #  include   <stdio.h>    int   main   (   void   )   {   int  a  ;   scanf   (   "%d"   ,   &  a  )   ;   // 取地址   printf   (   "%d\n"   ,  a  )   ;   return   0   ;   }   

char

字符型变量用于存储一个单一字符,在C语言中用char表示,其中每个字符变量都会占用1个字节,在给字符型变量赋值时,需要用一堆英文半角格式的单引号( '' )把字符括起来。

字符变量实际上并不是把该字符本身放到变量的内存单元中去,而是将该字符对应的ASCII编码放到变量的存储单元中, char的本质就是一个1字节大小的整型

                      #  include   <stdio.h>    int   main   (   void   )   {   // char a = 'A';   char  a  ;  a  =   getchar   (   )   ;   // printf("%c\n", a);   putchar   (  a  )   ;   putchar   (   '\n'   )   ;   return   0   ;   }   

float、double

浮点型变量是用来存储小数值的。在C语言中,浮点型变量分为两种:单精度浮点数(float)、高中生出国留学双精度浮点数(double)。 
double型变量所表示的浮点数比float型变量更精确 (double型变量表示范围比float型变量大) 
( 浮点型变量语法上可以运算,但因为精度问题,不适合用于运算 )

                      #  include   <stdio.h>    int   main   (   void   )   {   float  r  =   2   ;   float  s  =  r  *  r  *   3.14   ;   printf   (   "%.2f\n"   ,  s  )   ;   // 保留两位小数   // 科学计数法   float  a  =   3.2e3f   ;   // 3.2*1000 = 32000, e可写为E   float  b  =   1000e-3f   ;   // 0.1   return   0   ;   }   

数组

整型数组

                      #  include   <stdio.h>    int   main   (   void   )   {   int  arr  [   10   ]   =   {   1   ,   4   ,   2   ,   3   ,   5   ,   6   ,   9   ,   8   ,   7   ,   0   }   ;   int  len  =   sizeof   (  arr  )   /   sizeof   (   0   )   ;   printf   (   "%d\n"   ,  len  )   ;   // 冒泡排序   for   (   int  i  =   0   ;  i  <  len  ;  i  ++   )   {   for   (   int  j  =  i  ;  j  <  len  ;  j  ++   )   {   int  a  =  arr  [  i  ]   ;   int  b  =  arr  [  j  ]   ;   if   (  a  >  b  )   {   int  t  =  a  ;  arr  [  i  ]   =  b  ;  arr  [  j  ]   =  t  ;   }   }   }   // 展示   for   (   int  i  =   0   ;  i  <  len  ;  i  ++   )   {   printf   (   "%d "   ,  arr  [  i  ]   )   ;   }   printf   (   "\n"   )   ;   return   0   ;   }   

二维数组

                      #  include   <stdio.h>    int   main   (   void   )   {   int  t  [   3   ]   [   5   ]   =   {   {   1   }   ,   {   2   ,   3   }   ,   {   0   }   }   ;   int  len  =   sizeof   (  t  )   /   sizeof   (  t  [   0   ]   )   ;   for   (   int  i  =   0   ;  i  <  len  ;  i  ++   )   {   int  len2  =   sizeof   (  t  [   0   ]   )   /   sizeof   (  t  [   0   ]   [   0   ]   )   ;   for   (   int  j  =   0   ;  j  <  len2  ;  j  ++   )   {   printf   (   "%d "   ,  t  [  i  ]   [  j  ]   )   ;   }   printf   (   "\n"   )   ;   }   printf   (   "\n"   )   ;   return   0   ;   }   

字符数组

                      #  include   <stdio.h>    int   main   (   void   )   {   char  buff  [   ]   =   {   'h'   ,   'e'   ,   'l'   ,   'l'   ,   '\0'   ,   '0'   }   ;   printf   (   "%s\n"   ,  buff  )   ;   return   0   ;   }   

在这里插入图片描述

%s 遇到 \0 就停止

类型限定符

限定符含义
extern 
外部的,不在内部的
声明一个变量,extern声明的变量没有建立存储空间。 
extern int a;
const 定义一个常量,常量的值不能修改。 
const int a = 10;
volatile 防止编译器优化代码 
(多线程时候,变量的可见性)
register 定义寄存器变量,提高效率。register是建议型的指令,而不是命令型的指令。如果CPU有空闲寄存器,那么register就生效,如果没有空闲寄存器,那么register无效。

常量

常量的定义

  1. const 数据类型 常量名
  2. 【宏定义】 #define 常量名 值 
    在这里插入图片描述

注意

  1. 通过 #define 定义的常量是根据值来匹配数据类型的
  2. const 修饰的常量是不安全的,可以通过指针来修改

一些C语言特殊的运算符

goto

                      #  include   <stdio.h>    int   main   (   void   )   {   goto  Here  ;   printf   (   "hello world\n"   )   ;  Here  ;   printf   (   "here"   )   ;   return   0   ;   }   

& (变量地址)

                      #  include   <stdio.h>    int   main   (   void   )   {   int  arr  [   10   ]   ;   printf   (   "数组的位置: %p\n"   ,  arr  )   ;   printf   (   "数组0号位的位置: %p\n"   ,   &  arr  [   0   ]   )   ;   printf   (   "数组的位置+1: %p\n"   ,  arr  +   1   )   ;   printf   (   "数组0号位的位置+1: %p\n"   ,   &  arr  [   0   ]   +   1   )   ;   return   0   ;   }   

在这里插入图片描述

函数

打印

进制的打印

                      int  a  =   10   ;   // 十进制中的10   int  b  =   010   ;   // 八进制中的10   int  c  =   0x10   ;   // 十六进制中的10   int  d  =   0X10   ;   // 十六进制中的10   /*
%d 将数据按照十进制输出
%o 将数据按照八进制输出
%x 将数据按照十六进制小写输出
%X 将数据按照十六进制大写输出
*/   

字符串函数

gets() 和 puts()

int puts(const char *s) 
标准设备输出字符串,在输出完成后自动输出一个 '\n'

                      #  include   <string.h>    int   main   (   void   )   {   char  ch  [   100   ]   ;   // 获取一个字符   gets   (  ch  )   ;   // 输出一个字符串,并换行   puts   (  ch  )   ;   return   0   ;   }   

char *gets(char *s) 
从标准输入输入字符,并保存到制定的内存空间,知道出现换行符或督导文件结尾为止。

gets(str) 与 scanf("%s", str) 的区别:

  • gets(str) 允许输入额字符串包含有空格
  • scanf("%s", str) 不允许含有空格。需要写成 scanf("%s[^\n]",str)

注意:由于scanf和gets无法知道字符串s大小,必须遇到换行符或督导文件结尾才结束接收输入,因此容易导致字符数组越界(缓冲区溢出)的情况。 
在这里插入图片描述

fgets() 和 fputs()

char *fgets(char *s, int size, FILE *stream); 
从stream指定的文件内读入字符,保存到所指定的内存空间,直到出现换行字符、读到文件结尾或者已读了size-1个字符为止,最后会自动加上字符 '\0' 作为字符串结束。

                     参数:
	s:字符串
	size:指定最大读取字符串的长度(size-1)
	stream:文件指针,如果读键盘输入的字符串,固定写为stdin
返回值:
	成功:成功读取的字符串
	督导文件尾或出错:NULL  
                      #  include   <string.h>    #  include   <stdio.h>    // stdin   int   main   (   void   )   {   char  arr  [   10   ]   ;   // 参数:字符指针 大小 文件流(std in 标准输入流)   fgets   (  arr  ,   5   ,   stdin   )   ;   puts   (  arr  )   ;   return   0   ;   }   
  • 如果 输入的大小 小于原始指针对应区域的大小,会在字符串输入完成时自动加上 \n\0
  • 如果 输入的大小 大于等于原始指针对应的区域大小,会自动加上 \0 , 而不会加上\n 
    在这里插入图片描述

int fputs(const char *str, FILE *stream); 
将str所指定的字符串写入到stream指定的文件中,字符串结束符 \n 不写入文件。

                     参数
	str:字符串
	stream:文件指针,如果把字符串输出到屏幕,固定写为stdout
返回值
	成功:0
	失败:-1  
                      #  include   <string.h>    #  include   <stdio.h>    // stdin   int   main   (   void   )   {   char  arr  [   10   ]   ;   // 参数:字符指针 大小 文件流(std in 标准输入流)   fgets   (  arr  ,   5   ,   stdin   )   ;   // puts(arr);   fputs   (  arr  ,   stdout   )   ;   return   0   ;   }   

fputs() 是 puts() 的文件操作版本,但 fputs() 不会自动输出一个 \n 
在这里插入图片描述

打印/输出 printf()、scanf()

                      #  include   <string.h>    int   main   (   void   )   {   char  arr  [   100   ]   ;   scanf   (   "%*d%s"   ,  arr  )   ;   // 屏蔽字符串(开头)   printf   (   "%s\n"   ,  arr  )   ;   return   0   ;   

在这里插入图片描述

长度 strlen()

size_t strlen(const char *s); 
计算指定字符串s的长度,不包含字符串结束符 \0

                     参数
	s:字符串首地址
返回值
	字符串s的长度,size_t为unsigned int类型  
                      #  include   <stdio.h>    #  include   <string.h>    int   main   (   void   )   {   char  arr  [   ]   =   "abcdefg"   ;   int  n  =   strlen   (  arr  )   ;   printf   (   "n=%d"   ,  n  )   ;   return   0   ;   }   

strcpy()

char *strcpy(char *dest, const char *src); 
把src所指向的字符串复制到dest所指向的空间中, '\0' 也会拷贝过去

                     参数
	dest:目的字符串首地址
	src:源字符首地址
返回值
	成功:返回dest字符串的首地址
	失败:NULL  

注意: 如果参数dest所指的内存空间不够大,可能会造成缓冲溢出的错误情况。

                      #  include   <stdio.h>    #  include   <string.h>    int   main   (   void   )   {   char  dest  [   20   ]   =   "123"   ;   char  src  [   ]   =   "hello\0 world"   ;   if   (   strcpy   (  dest  ,  src  )   !=   NULL   )   {   printf   (   "拷贝成功!\n"   )   ;   }   printf   (   "%s\n"   ,  dest  )   ;   return   0   ;   }   

在这里插入图片描述

strcat()

char *strcat(char *dest, const char *src); 
将src字符串连接到dest的尾部, \0 也会追加过去

                     参数
	dest:目的字符串首地址
	src:源字符串首地址
返回值
	成功:返回dest字符串的首地址
	失败:NULL  
                      #  include   <stdio.h>    #  include   <string.h>    int   main   (   void   )   {   char  arr1  [   ]   =   "hello"   ;   char  arr2  [   ]   =   "world"   ;   strcat   (  arr1  ,   " "   )   ;   strcat   (  arr1  ,  arr2  )   ;   printf   (   "%s\n"   ,  arr1  )   ;   printf   (   "%s\n"   ,  arr2  )   ;   return   0   ;   }   

strcmp()

比较两个字符串的大小, 比较的是字符ASCII码大小

                     参数
	s1:字符串1首地址
	s2:字符串2首地址
返回值
	相等:0
	大于:>0 在不同操作系统strcmp结果会不同,返回ASCII差值
	小于:<0  
                      #  include   <stdio.h>    #  include   <string.h>    int   main   (   void   )   {   char   *  str1  =   "hello world"   ;   char   *  str2  =   "hello mike"   ;   if   (   strcmp   (  str1  ,  str2  )   ==   0   )   {   printf   (   "str==str2\n"   )   ;   }   else   if   (   strcmp   (  str1  ,  str2  )   <   0   )   {   printf   (   "str<str2\n"   )   ;   }   else   if   (   strcmp   (  str1  ,  str2  )   >   0   )   {   printf   (   "str>str2\n"   )   ;   }   return   0   ;   }   

在这里插入图片描述

模板输入/输出 sprintf()、sscanf()

int sprintf(char *_CRT_SECURE_NO_WARNINGS, const char *format, ...); 
根据参数format字符串来转换并格式化数据,然后将结果输出到str指定的空间中,直到出现 '\0' 为止。

                     参数
	str:字符串首地址
	format:字符串格式,用法和printf()一样
返回值
	成功:实际格式化的字符个数
	失败:-1  
                      #  include   <stdio.h>    #  include   <string.h>    int   main   (   void   )   {   char  dst  [   100   ]   =   {   0   }   ;   int  a  =   10   ;   char  src  [   ]   =   "hello world"   ;   printf   (   "a=%d, src=%s\n"   ,  a  ,  src  )   ;   int  len  =   sprintf   (  dst  ,   "a=%d, src=%s"   ,  a  ,  src  )   ;   printf   (   "dst=\"%s\"\n"   ,  dst  )   ;   printf   (   "len=%d\n"   ,  len  )   ;   return   0   ;   }   

在这里插入图片描述

查找 strchr()

char *strchr(const char *s, int c); 
在字符串s中查找字母c出现的位置

                     参数
	s:字符串首地址
	c:匹配字母(字符)
返回值
	成功:返回第一次出现的c地址
	失败:NULL  
                      #  include   <stdio.h>    #  include   <string.h>    int   main   (   void   )   {   char  src  [   ]   =   "dddaaa123"   ;   char   *  p  =   strchr   (  src  ,   'a'   )   ;   printf   (   "p=%s\n"   ,  p  )   ;   return   0   ;   }   

在这里插入图片描述

替换 strtok()

char *strtok(char *str, const char *delim); 
将字符串分割成一个个片段。当strtok()在参数str的字符串中发现参数delim中包含的分割字符时,则会将该字符改为0字符,当连续出现多个时只替换第一个为0。

                     参数
	str:指向欲分割的字符串
	delim:为分割字符串中包含的所有字符
返回值
	成功:分割后字符串首地址
	失败:NULL  

在第一次调用时,strtok()必须给予参数str字符串 
往后的调用则将参数str设置成NULL,每次调用成功则返回被分割出来的片段的指针

                      #  include   <stdio.h>    #  include   <string.h>    int   main   (   void   )   {   char  a  [   100   ]   =   "aaa*bbb*ccc*ddd"   ;   char   *  s  =   strtok   (  a  ,   "*"   )   ;   // 将"*"分割的子串取出   while   (  s  !=   NULL   )   {   printf   (   "%s\n"   ,  s  )   ;  s  =   strtok   (   NULL   ,   "*"   )   ;   }   return   0   ;   }   

在这里插入图片描述

扫描 atoi()

int atoi(const char *nptr); 
atoi()会扫描nptr字符串,跳过前面的空格字符,直到遇到数字或正负号才开始做转换,而遇到非数字或字符串结束符( '\0' )才结束转换,并将结果返回返回值。

                     参数
	nptr:待转换的字符串
返回值:成功转换后整数  

类似的函数有:

  • atof():把一个小数形式的字符串转化为一个浮点数
  • atol():将一个字符串转化为long类型

要引入 stdlib.h 依赖,否则可能出现值异常

                      #  include   <stdio.h>    #  include   <string.h>    #  include   <stdlib.h>    int   main   (   void   )   {   char   *  str1  =   "-10a"   ;   int  num1  =   atoi   (  str1  )   ;   printf   (   "num1=%d\n"   ,  num1  )   ;   char  str2  [   ]   =   "3.141123"   ;   float  num2  =   atof   (  str2  )   ;   printf   (   "num2=%f\n"   ,  num2  )   ;   return   0   ;   }   

在这里插入图片描述

函数的创建和定义

c程序是由函数组成的(函数是C程序的基本模块,是用于完成特定任务的程序代码单元)。

从函数定义的角度看,函数可分为系统函数和用户定义函数

                      #  include   <stdio.h>    #  include   <string.h>    #  include   <stdlib.h>    void   show   (   int  arr  [   ]   ,   int  len  )   {   for   (   int  i  =   0   ;  i  <  len  ;  i  ++   )   {   printf   (   "%d "   ,  arr  [  i  ]   )   ;   }   printf   (   "\n"   )   ;   }   void   bubble   (   int  arr  [   ]   ,   int  len  )   {   for   (   int  i  =   0   ;  i  <  len  ;  i  ++   )   {   for   (   int  j  =  i  ;  j  <  len  ;  j  ++   )   {   int  a  =  arr  [  i  ]   ;   int  b  =  arr  [  j  ]   ;   if   (  a  >  b  )   {  arr  [  i  ]   =  b  ;  arr  [  j  ]   =  a  ;   }   }   }   }   int   main   (   void   )   {   int  arr  [   ]   =   {   1   ,   3   ,   2   ,   4   ,   7   ,   6   ,   5   ,   8   ,   9   ,   0   }   ;   int  len  =   sizeof   (  arr  )   /   sizeof   (  arr  [   0   ]   )   ;   printf   (   "%d\n"   ,  len  )   ;   show   (  arr  ,  len  )   ;   bubble   (  arr  ,  len  )   ;   show   (  arr  ,  len  )   ;   return   0   ;   }   

在这里插入图片描述

函数的声明和调用

                      #include <stdio.h>  // 1、声明 声明函数的格式
extern int add  (  int a, int b  )   ;  int main  (  void  )   {  // 3、调用 
  int a  =  add  (  10, 20  )   ;  printf  (   "%d\n"  , a  )   ;   return  0  ;   }  // 2、定义 函数的定义就是对函数功能的实现
int add  (  int a, int b  )   {   return  a + b  ;   }   

 

头文件

头文件的作用

  1. 函数、变量的声明
  2. 系统库的调用
                      // 头文件只包含一次   #  pragma  once   #  include   <stdio.h>    #  include   <string.h>    #  include   <stdlib.h>    extern   int   max   (   int  a  ,   int  b  )   ;   

为了避免同一个文件被include多次,C/C++中有两种方式,一种是 #ifndef 方式,一种是 #pragma once 方式 
方法一:

                        #  ifndef  __SOMEFILE_H__   #  define  __SOMEFILE_H__   // 声明语句   #  endif    

方法二:

                        #  pragma  once   // 声明语句   

main函数的参数

                      #  include   <stdio.h>    int   main   (   int  argc  ,   char   *  argv  [   ]   )   {   // argc 接收传递参数的个数   // argv 接收传递参数的内容   printf   (   "%d\n"   ,  argc  )   ;   for   (   int  i  =   0   ;  i  <  argc  ;  i  ++   )   {   printf   (   "%s\n"   ,  argv  [  i  ]   )   ;   }   return   0   ;   }   

在这里插入图片描述

posted @ 2020-09-29 14:13  小琪琪来啦  阅读(0)  评论(0)    收藏  举报
欢迎大家来到我的博客:武汉雅思 | 武汉托福 | 新航道 | 雅思培训 | dnfsf | 天龙sf | 热血江湖sf | 天龙sf | dnfsf