c 语言基础 C语言基础知识总结

C语言基础知识总结

  }

  #include

  void main

  {

  int a,b;

  scanf("%2d%2d",&a,&b);//输入时将前两位数读入存到a中,接着两位存到b中,然后结束读取,即输入:1234,或123456结果一样

  printf("a=%d,b=%d ",a,b);

  }

  #include

  void main

  {

  int a,b;

  scanf("%d %d",&a,&b);

  printf("a="%d",b="%d" ",a,b);//输出a="12",b="34"

  }

  #include

  void main

  {

  int a,b;

  scanf("%d%*c%d",&a,&b);//任意字符都可作为分隔符,即输入:12,34或12?34或12+34结果都一样

  printf("a=%d,b=%d ",a,b);

  }

  #include

  void main

  {

  int a,b;

  scanf("%2d%*2d%d",&a,&b);//忽略两位,输入123456

  printf("a=%d,b=%d ",a,b);//输出a=12,b=56

  }

  对于程序

  #include

  void main

  {

  int a,b;

  scanf("%d %d",&a,&b);

  printf("a=%d,b=%d ",a,b);

  }

  如果输入12 34a回车,则结果a=12,b=3,程序在遇到非法字符a时,会导致程序输入终止,此时a会读入12,b会读入3

  如果输入123a回车,则结果a=123,b=-858993460,程序在遇到非法字符a时,会导致程序输入终止,此时a会读入123,而b未能读入指定数据项数

  如果在scanf函数中忘记在变量前加取地址运算符&,会导致非法内存访问

  13.%c格式符使用几种情况:

  1) 用%c格式读入字符时,空格字符和转义字符(包括回车)都会被当做有效字符读入 例:键盘输入一个整数加法算式:操作数1+操作数2,输出:操作数1+操作数2=计算结果

  #include

  void main

  {

  int data1,data2;

  char op; //输入:12空格+空格3 回车//输出:12 -858993460=-858993448

  printf("Enter data1+data2 ");//输入:12空格3 回车//输出:12 3=15

  scanf("%d%c%d",&data1,&op,&data2);//输入:12+3 回车//输出:12+3=15 printf("%d%c%d=%d ",data1,op,data2,data1+data2);

  }

  2) 先输入一个数据后再输入字符型变量时,输入一个数据后,输入的回车符将被当做有效字符读给字符型变量

  例:编程从键盘先后输入int型、char型和float型数据,要求每输入一个数据就显示这个数据的类型和数据值

  void main

  {

  int a;

  char b;

  float c;

  printf("Please input an integer:");

  scanf("%d",&a);

  printf("integer:%d ",a);

  //在输入一个整型数据后,输入的回车符被当做有效字符读给了字符型变量b了

  printf("Please input a character:");

  scanf("%c",&b);

  printf("chracter:%c ",b);

  printf("Please input a float number:");

  scanf("%f",&c);

  printf("float:%f ",c);

  }

  14.%c格式符存在问题的解决方法

  1) 用函数get)将数据输入时存入缓冲区中的回车符读入,以避免被后面的字符型变量作为有效字符读入

  #include

  void main

  {

  int a;

  char b;

  float c;

  printf("Please input an integer:");

  scanf("%d",&a);

  printf("integer:%d ",a);

  get);//将存于缓冲区中的回车符读入,避免在后面作为有效字符读入

  //函数get)的返回值是一个回车符,已经避免了错误,不需要再将其赋给字符型变量使用

  printf("Please input a character:");

  scanf("%c",&b);

  printf("chracter:%c ",b);

  printf("Please input a float number:");

  scanf("%f",&c);

  printf("float:%f ",c);

  }

  2) 在%c前面加一个空格,将前面数据输入时存于缓冲区的回车符读入,避免被后面的字符型变量作为有效字符读入

  void main

  {

  int a;

  char b;

  float c;

  printf("Please input an integer:");

  scanf("%d",&a);

  printf("integer:%d ",a);

  printf("Please input a character:");

  scanf(" %c",&b);//在%c前面加空格,将存于缓冲区中的回车符读入

  printf("chracter:%c ",b);

  printf("Please input a float number:");

  scanf("%f",&c);

  printf("float:%f ",c);

  }

  //解释:在%c前加空格为什么能将存于缓冲区中的回车符读入

  因为如果函数scanf的格式控制字符串中存在除格式转换说明符以外的其他字符,必须将这些

  字符原样输入,所以在%c前加空格,就必须在输入字符型数据前先原样输入空格,而空格,回车符,制表符在

  函数scanf输入数值型数据时都代表输入结束,由实践可知,空格符、回车符、制表符在输入时等效

  所以,缓冲区中的回车将代替需要原样输入的空格,因此,实际上,在%c前增加空格或者Tab键都可以完成,

  并且与增加的数量无关,且可以混合增加

  3)*经典例题:编程实现键盘任意输入字符,统计字母、数字、空格、其他字符数量 首选字符串的方法:

  #include

  #define N 100

  int main

  {

  char a[N];

  int i,m=0,n=0,b=0,c=0;

  printf("请输入字符: ");

  gets(a);

  for(i=0;a[i]!=;i++)

  {

  if((a[i]>=a&&a[i]<=z)||(a[i]>=A&&a[i]<=Z)) m++;

  else if(ch>=0&&ch<=9) b++;

  else if(ch== ) c++;

  else d++;

  }

  }while(ch!= );

  printf("字母个数:%d ",a);

  printf("数字个数:%d ",b);

  printf("空格个数:%d ",c);

  printf("其他字符个数:%d ",d);

  return 0;

  }

  //解释:你可以把Tab控制结束改成其他任意字符,包括字母、数字、/;都可以,

  就是不能直接使用回车控制结束,因为你在实际键盘输入时,需要打回车才能把前面的 字符读入,当你输完回车后,就已经换行了,再回车就达不到你要的效果了,不可能把 他读入,但是他会留在缓冲区下一次使用,所以说,理论上任意字符都可以控制结束, 但是不能直接使用回车再回车的方法,而get)函数一次只能读一个字符,当你回车 读入字符后,回车符就会留在缓冲区下一次使用,你可以试试,你把get)这行语句 注释,然后一次输入两个字符再回车的话,那么这时他也只能读入第一个字符,第二个 字符和回车就会计入第二次、第三次的结果。

  总结:这种方式与用字符串的区别在于,字符串可以统计任何字符,但是这种方式不能统计 你用来控制结束的字符,比如说,你用/控制结束,那么就不能统计/的数量了,而且你要把 他去掉,因为在整个程序中/只会出现一次,然后就结束了

  **当程序中出现两次或以上的键盘输入时,就有可能出现缓冲区的问题,只有一次输入,回车直接结束没有这种问题

  15.考点题型:字符串常量的长度问题:

  1)字符串常量"abc d376"的长度是(A)

  A) 7 B) 12 C) 8 D) 14

  // a b c d 376

  2)语句printf("%d",strlen("abs o121"));的输出结果是(C)

  A) 11 B) 10 C) 9 D) 8

  // a b s o 1 2 1

  16.考点题型:赋值运算、关系运算的混合运算问题:

  1)设m,n,a,b,c,d的值均为0,执行(m=a==b)||(n=c==d),m,n的值是(C)

  A) 0,0 B) 0,1 C) 1,0 D) 1,1

  // "=="是算术运算符,"="是赋值运算符,优先级:算术运算符>赋值运算符,先判断a==b?是否正确

  正确则为真,把1赋给m,"||"是或运算,前面已经为真,所以||后面的就不会再运算了,结果就为真

  所以m=1,n=0不变

  2)int a,b,m,n;初值依次为4,3,2,1,经计算m=(a<=b)&&(n=m

  A) 1,1 B) 1,0 C) 0,1 D) 0,0

  // a<=b为假,&&是并,前面已经为假,后面就不会再运算了,结果就为假,把0赋给m,即m=0,n=1不变

  四、 选择控制结构

  1.沃思提出“数据结构+算法=程序”只在面向过程的语言(如C语言)成立

  2.算法的正确性衡量方法:

  1)有穷性 2)确定性 3)有效性 4)允许没有输入或者有多个输入 5)必须有一个或者多个输出

  3.算法的描述方法:

  1)自然语言描述 2)流程图描述 3)NS结构化流程图描述 4)伪码描述

  4.关系表达式:用作判断条件,结果只有真和假,(n%2!=0)等价于(n%2),0表示假,非0表示真

  5.分支结构:当条件P成立时,执行A操作,否则执行B操作;如果B操作为空,即为单分支结构;

  如果B操作不为空,即为双分支结构;如果B操作中又包含另一选择结构,则构成多分支选择结构;

  6.单分支例题:计算输出两整数最大值

  单分支(一般形式):if(表达式P) 语句A

  #include

  void main

  {

  int a,b,max;

  printf("Enter a,b:");

  scanf("%d%d",&a,&b);

  if(a>b) //单分支:if(表达式P) 语句A

  max=a;

  if(a<=b) //单分支:if(表达式P) 语句A

  max=b;

  printf("max=%d ",max);

  }

  7.双分支例题:计算输出两整数最大值

  双分支(一般形式):if(表达式P) 语句1

  else 语句2

  #include

  void main

  {

  int a,b,max;

  printf("Enter a,b:");

  scanf("%d%d",&a,&b);

  if(a>b)

  max=a;

  else

  max=b;

  printf("max=%d ",max);

  }

  8.条件运算符是C语言中唯一的三元运算符,需要三个操作数

  9.条件运算符例题:计算输出两整数最大值

  条件运算符(一般形式):表达式1?表达式2:表达式3

  含义:若表达式1为非0,则结果为表达式2的值,否则是表达式3的值

  #include

  void main

  {

  int a,b,max;

  printf("Enter a,b:");

  scanf("%d%d",&a,&b);

  max=a>b?a:b;

  printf("max=%d ",max);

  }

  10.多分支控制条件语句(一般形式):

  if(表达式1) 语句1

  else if(表达式2) 语句2

  ...

  else if(表达式m) 语句m

  else 语句m+1

  11.条件语句在语法上只允许每个条件分支中带一条语句,而要在分支里处理多条语句 就要使用花括号,构成复合语句

  12.随机数的使用方法:

  1) 符号常量RAND_MAX在头文件#include中定义,标准C规定RAND_MAX不大于双字节整数的最大值32767

  2)随机函数rand产生的是一个在0~RAND_MAX之间的整数,即[0,32767]之间的整数

  3) 利用求余运算rand%b可将函数rand生成的随机数变化到[0,b-1]

  4) 利用rand%b+a可将随机数的取值范围平移到[a,a+b-1]

  例:产生1~100的随机数: rand%100+1

  13.例题:猜数游戏:计算机想一个数,人猜对了提示Right!,否则提示Wrong!,并告诉大小 #include

  #include

  void main

  {

  int magic,guess;

  magic=rand; //随机数

  printf("Please guess a number:");

  scanf("%d",&guess);

  if(guess>magic) //多分支

  {

  printf("Wrong!Too big! "); //复合语句

  }

  else if(guess

  {

  printf("Wrong!Too small! ");

  }

  else{

  printf("Right! ");

  printf("The number is:%d ",magic);

  }

  }

  tch语句:用于多路选择,一般情况大于三种,用开关语句代替条件语句

  1) switch语句(一般形式):

  switch(表达式)

  {

  case 常量1:

  可执行语句序列1 //注意:语句序列不使用花括号

  case 常量2:

  可执行语句序列2

  ........

  case 常量n:

  可执行语句序列n

  default:

  可执行语句序列n+1

  }

  2) switch语句相当于一系列的if-else语句

  3)switch后圆括号内的表达式只能是char型或int型

  4)关键字case后接常量,类型与表达式类型一致,常量的值必须互不相同

  5)常量与case中间至少有一个空格,常量后面是冒号

  6)case本身并没有条件判断的功能,若case后面的语句省略不写,则表示它与后续case执行相同的语句

  7)switch语句的执行过程:

  第一步,计算switch后表达式的值

  第二步,将表达式的值依次与case后的常量比较

  第三步,如果相等,执行case后的代码段,执行完毕,可使用break语句跳出switch语句

  如果没有break语句,不会再比较,程序将依次执行下面的case后的语句,直到遇到break或者switch的}为止

  15.例题:编程实现简单计算器功能

  #include

  void main

  {

  int data1,data2;

  char op;

  printf("Enter your expression:");

  scanf("%d%c%d",&data1,&op,&data2);

  switch(op)

  {

  case +:

  printf("%d+%d=%d ",data1,data2,data1+data2);

  break;

  case -:

  printf("%d-%d=%d ",data1,data2,data1-data2);

  break;

  case *:

  case x:

  case X:

  printf("%d*%d=%d ",data1,data2,data1*data2);

  break;

  case /:

  if(0==data2)//也可写成data2==0,写0==data2的好处:

  { //因为赋值表达式左值必须是变量,如果把==误写成=,会提示错误

  printf("Division by zero! ");

  }

  else{

  printf("%d/%d=%d ",data1,data2,data1/data2);

  }

  break;

  default:

  printf("Invalid operator! ");

  //break;这句一般不需要,因为没有break就会依次执行下面的步骤直到break或者switch的}

  } //这里已经是switch的}了

  }

  16.例题:编程实现简单计算器功能,能进行浮点数运算,操作数与运算符之间可加入任意多个空格

  #include

  #include

  void main

  {

  float data1,data2;

  char op;

  printf("Enter your expression:");

  scanf("%f %c%f",&data1,&op,&data2);

  switch(op)

  {

  case +:

  printf("%f+%f=%f ",data1,data2,data1+data2);

  break;

  case -:

  printf("%f-%f=%f ",data1,data2,data1-data2);

  break;

  case *:

  case x:

  case X:

  printf("%f*%f=%f ",data1,data2,data1*data2);

  break;

  case /:

  if(fabs(data2)<=1e-7)

  {

  printf("Division by zero! ");

  }

  else{

  printf("%f/%f=%f ",data1,data2,data1/data2);

  }

  break;

  default:

  printf("Invalid operator! ");

  }

  }

  //内存中的浮点数所表示的精度是有限的,所以比较实型变量data2与0是否相等时, 不能像整型变量与0比较那样直接用相等关系运算符与0比较,而应使用如下方式判断 实型变量data2的值是否位于0附近的一个很小的区间内,即:if(fabs(data2)<=1e-7)

  17.逻辑运算符和逻辑表达式

  逻辑非:!,单目运算符,右结合, 优先级最高

  逻辑与:&&,双目运算符,左结合,优先级较高

  逻辑或:||,双目运算符,左结合,优先级较低

  例:判断某一年year是否是闰年的条件:

  1) 能被4整除,但不能被100整除;

  1)能被400整除

  逻辑表达式:((year%4==0)&&(year%100!=0))||(year%400==0)

  或:(year%4==0)&&(year%100!=0)||(year%400==0)

  18.特别注意:在计算含有逻辑运算符(&&和||)的表达式时,通常尽量使用最少的操作数来 确定表达式的值,这就意味着表达式中的某些操作数可能不会被计算。

  例:if(a>1&&b++>2&&c--!=0)中,仅在条件表达式a>1为真时,才会计算后面的值

  19.程序测试:

  1)程序测试只能证明程序有错,不能证明程序无错

  2)例:编程输入三角形三边长a,b,c,判断他们能否构成三角形,能构成什么三角形 #include

  #include

  #define EPS 1e-1

  void main

  {

  float a,b,c;

  int flag=1;

  printf("Enter a,b,c:");

  scanf("%f,%f,%f",&a,&b,&c);

  if(a+b>c&&b+c>a&&a+c>b)

  {

  if(fabs(a-b)<=EPS&&fabs(b-c)<=EPS&&fabs(c-a)<=EPS)

  {

  printf("等边");

  flag=0;

  }

  else if(fabs(a-b)<=EPS||fabs(b-c)<=EPS||fabs(c-a)<=EPS)

  {

  printf("等腰");

  flag=0;

  }

  if(fabs(a*a+b*b-c*c)<=EPS||fabs(b*b+c*c-a*a)<=EPS||fabs(a*a+c*c-b*b)<=EPS) {

  printf("直角");

  flag=0;

  }

  if(flag)

  {

  printf("一般");

  }

  printf("三角形 ");

  }

  else{

  printf("不是三角形 ");

  }

  }

  3)例:编程将输入的百分制成绩转换为五分制成绩输出

  #include

  void main

  {

  int score,mark;

  printf("Enter score:");

  scanf("%d",&score);

  if(score<0||score>100)

  {

  mark=-1;//这个if语句很重要,如果去掉,边界测试101~109,-1~-9会出错 }

  else{

  mark=score/10;

  }

  switch(mark)

  {

  case 10:

  case 9:

  printf("%d-优! ",score);

  break;

  case 8:

  printf("%d-良! ",score);

  break;

  case 7:

  printf("%d-中! ",score);

  break;

  case 6:

  printf("%d-及格! ",score);

  case 5:

  case 4:

  case 3:

  case 2:

  case 1:

  case 0:

  printf("%d-不及格! ",score);

  break;

  default:

  printf("Input error! ");

  }

  }

  20.对输入非法字符的检查与处理

  1)例:输入两个整型数,计算并输出两个整数的最大值

  #include

  void main

  {

  int a,b,max;

  printf("Enter a,b:");

  scanf("%d,%d",&a,&b);

  max=a>b?a:b;

  printf("max=%d ",max);

  }

  //隐含问题:在Visual C++下

  1.如果输入3.2,1则输出3

  2.如果输入1,3.2则输出3

  3.如果输入q则输出-858993460

  //解决办法:

  #include

  void main

  {

  int a,b,max,ret;

  do{

  printf("Enter a,b:");

  ret=scanf("%d,%d",&a,&b);

  if(ret!=2)//返回在遇到非法字符前已成功读入的数据项数

  {

  //但是scanf函数不做类型检查,所以输入1,3.2会输出3

  printf("Input error! ");

  while(get)!= );

  }

  else{

  max=a>b?a:b;

  printf("max=%d ",max);

  }

  }while(ret!=2);

  }

  21.位运算符的使用

  1)位运算是对字节或字内的二进制数位进行测试、抽取、设置或移位等操作

  2) 位运算的操作对象只能是char和int类型

  3) C语言中共有6种位运算符,只有按位取反是单目运算符,其他都是双目运算符

  4)关系运算和逻辑运算的结果要么是0,要么是1,而位运算结果可为任意值,但每一位都只能是0或1

  5)6种位运算符:

  按位取反 ~ 用于加密处理,一次求反加密,二次求反解密

  左移位 <<

  右移位 >>

  按位与 & 用于对字节中某位清零

  按位异或 ^

  按位或 | 用于对字节中某位置1

  6)按位取反 ~1=0,~0=1

  例:~5=-6

  ~ 00000101

  ———————

  11111010 是-6的补码

  7)按位与 0&0=0,0&1=0,1&1=1

  例:将15的最低位不变,其余位清零 15&1=1

  00001111

  & 00000001

  ——————

  00000001

  8)按位或 0|0=0,0|1=1,1|1=1

  例:将15的最高位不变,其余位均置1 15|127=127

  00001111

  | 01111111

  ——————

  01111111 是127的补码

  9)按位异或 0^0=0,0^1=1,1^1=0

  例:3^5=6

  00000011

  ^ 00000101

  ——————

  00000110 是6的补码

  10)左移位

  x<

  例:将15左移1、2、3位的二进制补码如下

  初始字节内容 00001111 对应十进制15

  左移1位字节内容 00011110 对应十进制30

  左移2位字节内容 00111100 对应十进制60

  左移3位字节内容 01111000 对应十进制120

  11)右移位

  x>>n 表示把x的每一位向右移n位,当x为有符号数时,左边空位补符号位值—算术移位

  当x为无符号位时,左边空位补0—逻辑移位

  例1:将15右移1、2、3位的二进制补码如下

  初始字节内容 00001111 对应十进制15

  右移1位字节内容 00000111 对应十进制7

  右左移2位字节内容 00000011 对应十进制3

  右移3位字节内容 00000001 对应十进制1

  例2:将-15右移1、2、3位的二进制补码如下

  初始字节内容 11110001 对应十进制-15

  右移1位字节内容 11111000 对应十进制-8

  右左移2位字节内容 11111100 对应十进制-4

  右移3位字节内容 11111110 对应十进制-2

  12) 无论左移位还是右移位,从一端移走的位不移入另一端,移走的位的信息就丢失了

  13)左移位和右移位可以分表代替整数的乘法和除法,左移n位相当于乘以2^n,右移n为相当于除以2^n

  14) 例:写出运行结果

  #include x 0000 0000 0000 1100

  void main ~x 1111 1111 1111 0011

  { ~x反码1000 0000 0000 1100

  int x=12,y=8; ~x反码加一1000 0000 0000 1101 -13 printf("%5d%5d%5d ",!x,x||y,x&&y);

  printf("%5u%5d%5d ",~x,x|y,x&y);

  printf("%5d%5d%5d ",~x,x|y,x&y);

  }

  输出: 0 1 1

  4294967283 12 8

  -13 12 8

  五、循环控制结构

  1.循环:包括计数控制的循环和条件控制的循环

  2.结构化程序设计的三种基本结构:顺序结构、选择结构、循环结构

  3.循环结构的类型:

  1)当型循环结构:for语句(适合循环次数已知,计数控制的循环)

  2)直到型循环结构:while语句、do-while语句(适合循环次数未知,条件控制的循环)

  le语句

  1)一般形式为:

  while(循环控制表达式)

  { |

  语句系列 |循环体

  } |

  2)循环控制表达式在执行循环体之前测试

  3)执行过程:

  计算循环控制表达式的值

  如果循环控制表达式的值为真,那么执行循环体中的语句,并返回步骤1

  如果循环控制表达式的值为假,就退出循环,执行循环体后面的语句

  -while语句

  1)一般形式为:

  do

  { |

  语句系列 |循环体

  }while(循环控制表达式);

  2)循环控制表达式在执行循环体之后测试

  3)执行过程:

  执行循环体中的语句

  计算循环控制表达式的值

  如果循环控制表达式的值为真,那么返回步骤1

  如果循环控制表达式的值为假,就退出循环,执行循环体后面的语句

  语句

  1)一般形式为:

  for(初始化表达式;循环控制表达式;增值表达式)

  { |

  语句系列 |循环体

  } |

  2) 在每次循环体被执行之前,都要对循环控制条件测试一次,每次循环体执行完以后都要执行一次增值表达式

  3)初始化表达式作用:循环变量初始化,即赋初值

  4)循环控制表达式:是控制继续执行的条件,当表达式的值为非0时重复执行循环

  5)增值表达式作用:每执行一次循环,循环控制变量增值

  6)for语句三个表达式之间用分号分隔,有且只能有两个分号

  7)循环控制表达式若省略,表示循环条件为永真

  8)初始化表达式和增值表达式都可省略,但是必须有其他语句反应其作用

  7.例:从键盘输入n,然后计算输出1+2+3+??n的值

  1)while语句编程实现

  #include

  void main

  {

  int i=1,n,sum=0;//sum一定要初始化,不然会是随机值

  printf("Enter n:");

  scanf("%d",&n);

  while(i<=n)

  {

  sum+=i;

  i++;

  }

  printf("1+2+3+??+%d=%d ",n,sum);

  }

  2)do-while语句编程实现

  #include

  void main

  {

  int i=0,n,sum=0;

  printf("Enter n:");

  scanf("%d",&n);

  do

  {

  sum+=i;

  i++;

  }while(i<=n);

  printf("1+2+3+??+%d=%d ",n,sum);

  }

  3)for语句编程实现

  #include

  void main

  {

  int i=1,n,sum=0;

  printf("Enter n:");

  scanf("%d",&n);

  for(i=1;i<=n;i++)

  {

  sum+=i;

  }

  printf("1+2+3+??+%d=%d ",n,sum);

  }

  8.逗号运算符

  1)所有运算符中优先级最低,左结合

  2)作用:可实现对各个表达式的顺序求值

  3)结果:将最后一个表达式的值作为整个逗号表达式的值

  4)例:从键盘输入n,然后计算输出1+2+3+??n的值

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容, 请发送邮件至 1156092664@qq.com 举报,一经查实,本站将立刻删除。

在线客服
分享本页
返回顶部