关于初学c语言遇到的一些易错题

关于学习c语言时遇到的一些易错题及其错因分析

一. 关于选择题

  1. 若int i=10;执行下列程序后,变量i的正确结果是( )
    switch(i){
    case 9:i+=1;
    case 10:i+=1;
    case 11:i+=1;
    default:i+=1;
    }

    A: 10
    B: 11
    C: 12
    D: 13

    我的答案:B
    标准答案:D

    错因: 第三句之后未加break;所以i会自增两次。


  1. 设int x,a,b;则下面if语句中错误的是( )

    A: if(a=b) x++;
    B: if(a= C: if(a-b) x++;
    D: if(x) x++;

    我的答案:A
    标准答案:B

    错因:if语句中不能加 :运算符


  1. 若有定义:int a=3,b=2,c=1;并有表达式:①a%b,②a>b>c,③b&&c+1.则表达式值相等的是( )

    A: ①和②
    B: ②和③
    C: ①和③
    D: ③和④

    我的答案:A
    标准答案:C

    错因:表达式②的值为0.


  1. 下列表达式中,不满足“当x的值为偶数时值为真,为奇数时值为假”要求的是( )

    A: x%2==0
    B: !x%2!=0
    C: (x/2*2-x)==0
    D: !(x%2)

    我的答案:C
    标准答案:B

    错因:B选项中当x为任意值时都为0(当值为0除外),故此项都为假.


  1. 以下程序输出结果是( )
    main( )
    {
    int x=1,y=0,a=0,b=0;
    switch(x)
    {
    case 1:switch(y)
    {
    case 0 :a++;break;
    case 1 :b++;break;
    }
    case 2:a++;b++;break;
    case 3:a++;b++;
    }
    printf(“a=%d,b=%d”,a,b);
    }

    A: a=1,b=0
    B: a=2,b=1
    C: a=1,b=1
    D: a=2,b=2

    我的答案: A
    标准答案: B

    错因:当程序进入第一个case 1后会再进入case 0,然后break调出后会再次进入case 2,所以a自增两次,b自增一次。所以选B项.


  1. 下述程序的而输出结果是( )
    main( )
    {
    int a,b,c;
    int x=5,y=10;
    a=(y=x++)?y:++x;
    b=y++;c=x;
    printf("%d,%d,%d",a,b,c);
    }

    A: -5,5,6
    B: 5,5,6
    C: 5,6,6
    D: 6,6,6

    我的答案: C
    标准答案: B

    错因:在 b=y++ 中,y的值是先用再自增,故b的值是5而不是6.


  1. 已知 int x=10, y=20, z=30; 以下语句执行后x, y, z的值是( )。
    if(x>y)
    z=x;x=y;y=z;

    A: x=10,y=20,z=30 
    B: x=20,y=30,z=30
    C: x=20,y=30,z=10 
    D: x=20,y=30,z=20

    我的答案: A
    标准答案: B

    错因:此题容易看错导致出错,在z=x之后是一个’;‘符号,故此符号之后的语句仍会执行。


  1. 对下述程序,正确的判断是( )
    main()
    {
    int x,y;
    scanf("%d,%d",&x,&y);
    if(x>y)
    x=y;y=x;
    else
    x++;y++;
    printf("%d,%d",x,y);
    }
    A: 有语法错误,不能通过编译
    B: 若输入3和4,则输出4和5
    C: 若输入4和3,则输出3和4
    D: 若输入4和3,则输出4和5

    我的答案: D
    标准答案: A

    错因:此程序会弹出:error C2181: illegal else without matching if 的错误提示,意思为if 和else匹配不合法,因为在x=y;之后还有一个单独的语句,故选A。


  1. 下述程序的输出结果是( )
    main()
    {
    int a=0,b=0,c=0;
    if(++a>0||++b>0) ++c;
    printf("%d,%d,%d",a,b,c);
    }

    A: 0,0,0
    B: 1,1,1
    C: 1,0,1
    D: 0,1,1,

    我的答案: B
    标准答案: C

    错因:因为 ++a>0成立,所以||的结果必为真,因此后面的++b就不再执行。因为if成立,所以++c肯定执行了。所以a,c变成了1,b还是0


  1. 设int a=0,b=5;执行表达式++a||++b,a+b后,a,b和表达式的值分别是( )

    A: 1,5,7
    B: 1,6,7
    C: 1,5,6
    D: 0,5,7

    我的答案: B
    标准答案: C

    错因:因为++a成立所以++b不再执行,故a为1,b仍是5.


  1. 以下程序的输出结果是( )
    main()
    {
    int x=0,y=0,z=0;
    if(x=y+z)
    printf("***");
    else
    printf("###");
    }

    A: 有语法错误,不能通过编译
    B: 输出:***
    C: 可以编译,但不能通过连接,所以不能运行
    D: 输出:###

    我的答案: B
    标准答案: D

    错因:因为赋值表达式的值与最左变量一样,所以表达式 x=y+z 的值为0,所以执行else部分的语句,所以输出###


  1. 在算法的逻辑结构中,要求进行逻辑判断并根据结果进行不同处理的是哪种结构( )

    A: 顺序结构
    B: 条件分支结构和循环结构
    C: 顺序结构和条件分支结构
    D: 顺序结构和循环结构

    我的答案: C
    标准答案: B

    错因:算法的三种基本结构是顺序结构、条件结构、循环结构。因为题中在算法的逻辑结构中,要求进行逻辑判断,条件结构需要判断条件,而循环结构一定包含条件结构,故选B。


  1. 若有定义:int (*p)[4];则标识符____。

    A: 是一个指向整型变量的指针
    B: 是一个指针数组名
    C: 是一个指针,它指向一个含有四个整型元素的一维数组
    D: 定义不合法

    我的答案: B
    标准答案: C

    错因: 题目中 int (*p)[4]是一个指针,它指向一个含有四个整型元素的一维数组,而int * p[4]才是一个指针数组


  1. 下面不能正确进行字符串赋值操作的是( )。

    A: char s[6]={“ABCDE”};
    B: char s[5]={‘A’,'B’,'C’,'D’,'E’};
    C: char *s;s=”ABCDE”;
    D: char *s; scanf(“%s”,s);

    我的答案: D
    标准答案: B

    错因:B项中缺少了位置给‘\0’


  1. 设有以下定义:
    int a[4][3]={1,2,3,4,5,6,7,8,9,10,11,12}; int (*prt)[3]=a,*p=a[0];
    则下列能够正确表达数组元素a[1][2]的表达式是( )。

    A: *((*prt+1))
    B: ((p+5))
    C: (*prt+1)+2
    D: ((a+1)+2)

    我的答案: C
    标准答案: D

    错因: (*prt+1)+2 中所指的值是a[1][2]*的地址


  1. 若有以下定义,则赋值正确的是( )。
    int a ,b , *p;
    float c, *q;

    A: p=&c
    B: q=p
    C: p=NULL
    D: q=new int

    我的答案: D
    标准答案: C

    错因:D答案明显错误:q = new : 语法错误。new是关键字。


  1. 若有以下定义,且0≤i<4,则不正确的赋值语句是_______.
    int b[4][6], *p, *q[4];

    A: q[i] = b[i];
    B: p = b;
    C: p = b[i]
    D: q[i] = &b[0][0];

    我的答案: C
    标准答案: B

    错误: B选项中p是一个int型指针,而b是一个二维数组名,某些环境运行不会出错,但严谨意义上是不允许的,b,b[0],&b[0][0],结果都是b[0][0]的地址,但是三个方式的类型不完全相同,bint(*)[]型,b[0]int *型,&b[0][0]int*型,而指针p是int *型,所以p=b犯了类型不同的错误。


  1. 下面判断正确的是____________。

    A: char *a=“china”;等价于char *a; a=“china”;
    B: char str[10]={“china”};等价于char str[10];str[]={“china”};
    C: char *s=”china”;等价于char *s; *s=”china”;
    D: char c[4]=”abc”,d[4]=”abc”;等价于char c[4]=d[4]=”abc”;

    我的答案: C
    标准答案: A

    错因:选项A中 char * a;*a="china"应改为char*a;a="china";。选项C中str[]={“china”};应该改为str={“china”};。选项D中表述方法错误,c,d两个数组定义时不能连续赋值。


  1. 若有说明:int*p1,*p2,m=5,n;以下程序段正确的是( )

    A: p1=&m;p2=&p1
    B: p1=&n;scanf("%d",*p1)
    C: scanf("%d",n); *p1=n
    D: p1=&n; *p1=m

    我的答案: A
    标准答案: D

    错因:A选项中p2不是二级指针。B项中scanf("%d",*p1)应改为scanf("%d",p1);。C项中p1未指向任何变量,是野指针,所以*p1=n无意义。


  1. 若有以下定义和语句,则对a数组元素地址的正确引用为______。
    int a[2][3], (*p)[3]; p=a;
    A: *(p+2)
    B: p[2]
    C: *(p[1]+1)
    D: (p+1)+2

    我的答案: D
    标准答案: C

    错因:选项C中p[1]指向了数组a的第二行,p[1]+1则指向了第二行的第二个数据元素,其他几个选项都不正确。


  1. 若有说明:int*p1,*p2,m=5,n;以下程序段正确的是( )

    A: p1=&m;p2=&p1
    B: p1=&n;scanf("%d",*p1)
    C: scanf("%d",n); *p1=n
    D: p1=&n; *p1=m

    我的答案: B
    标准答案: D

    错因:(第二次错)A选项中p2不是二级指针。B项中scanf("%d",*p1)应改为scanf("%d",p1);。C项中p1未指向任何变量,是野指针,所以*p1=n无意义。


  1. 有以下程序:
    void fun(char *c,int d)
    {
    *c=*c+1;
    d=d+1;
    printf(“%c,%c,”,*c,d);
    }

    main()
    { char b=’a’,a=’A’;
    fun(&b,a);
    printf(“%c,%c\n”,b,a);
    }
    程序的运行结果是( )

    A: a,B,B,a
    B: b,B,b,A
    C: a,B,a,B
    D: b,B,B,A

    我的答案: D
    标准答案: B

    错因:void fun(char *c,int d)函数中,改变了第一个参数的值而第二个并没有传进来地址,故在跳出函数之后,第二个参数的值仍未改变,所以选B.


  1. 若有语句int a[10]={0,1,2,3,4,5,6,7,8,9},*p=a;则选项( )不是对a数组元素的正确引用(其中0≤i<10)。

    A: p[i]
    B: *(*(a+i))
    C: a[p-a]
    D: *(&a[i])

    我的答案: A
    标准答案: B

    错因:选项B *(*(a+i))应改为 *(a+i)


  1. 若有说明:int i, j=2,*p=&i;, 则能完成i=j赋值功能的语句是( )

    A: i=*p
    B: *p=*&j
    C: i=&j
    D: i=**p

    我的答案: D
    标准答案: B

    错因:指针p指向i,故可以完成i=j的复制操作。


  1. 对于语句int *pa[5];下列描述中正确的是_______.

    A: pa是一个指向数组的指针,所指向的数组是5个int型元素
    B: pa是一个指向某数组中第5个元素的指针,该元素是int型变量
    C: pa [5]表示某个元素的第5个元素的值
    D: pa是一个具有5个元素的指针数组,每个元素是一个int型指针

    我的答案: A
    标准答案: D

    错因:int *pa[5];是指针数组且是一个具有5个元素的指针数组,每个元素是一个int型指针。


二. 关于编程题

  1. 统计个数

描述:
给定若干行字符串,要求统计大小写字母和数学字符的个数。

标准输入: 包括若干行,第一行为用例的个数n,接下来的n行,每行为一个字符串,可以包括空格、标点、数字字符和大小写字符,每行不超过80个字符。输出

标准输出: 每个用例用一行输出大写字符,小写字符和数字字符的个数,用一个空格隔开。

样例输入:
2
Kdf7d sdfs9,./dfs
12dfABc3D,{}de

样例输出:
1 10 2
3 5 3

思路: 只需在for循环中完成一个字符一个字符的比较即可,并相应的计数。


  1. 奇数位的提取

描述: 键盘输入一个整数,要求将该数奇数位上的数字提取出来构成新的数。奇数位即从右边开始计数,分别是个位,百位,万位等,例如:“125486”, 奇数位上的数字分别是6、4、2,提取出来即构成新的数246。注意:原来高位还是高位。
输入只有一个用例,即一个整数n。

输入:
用一行输出对应的奇数位上数字提取出来构成的数。

样例输入:
1568758

样例输出:
1678

**思路:**先用while循环判定整数n是几位数,再逐个奇位数的提取出来,最后利用累加的思想,将提取出来的数组成一个新的数即可(注意:在累加中,每累加一次,累加的和乘以10


  1. 判断闰年

描述: 键盘输入一个四位数的年份,判断该年是否为闰年。闰年即如果是整百年,要求能被400整除,如果不是整百年,则能被4整除。如2000年是闰年,1900年不是闰年,1996年是闰年。如果是闰年,输出“OK”,否则输出“NO”。

样例输入:
1990

样例输出:
NO

思路: 判断任意年份是否为闰年,需要满足以下条件中任意一个:
① 该年份能被 4 整除同时不能被 100 整除;
② 该年份能被400整除。
③且推荐使用if-else 语句。


  1. 数组循环右移

描述: 本题要求实现一个对数组进行循环右移的简单函数:一个数组a中存有n(>0)个整数,将每个整数循环向右移m(≥0)个位置,即将a中的数据由(a​0a​1⋯an−1)变换为(an−m​​ ⋯a​n−1​​ a​0a1 ⋯an−m−1)(最后m个数循环移至最前面的m个位置)。

函数接口定义:
int ArrayShift( int a[], int n, int m );

其中a[]是用户传入的数组;n是数组的大小;m是右移的位数。函数ArrayShift须将循环右移后的数组仍然存在a[]中。

裁判测试程序样例:

#include <stdio.h>
#define MAXN 10

int ArrayShift( int a[], int n, int m );

int main()
{
    int a[MAXN], n, m;
    int i;

   scanf("%d %d", &n, &m);
    for ( i = 0; i < n; i++ ) scanf("%d", &a[i]);

   ArrayShift(a, n, m);

   for ( i = 0; i < n; i++ ) {
        if (i != 0) printf(" ");
        printf("%d", a[i]);
    }
   printf("\n");

   return 0;
}
/* 你的代码将被嵌在这里 */

输入样例:
6 2
1 2 3 4 5 6

输出样例:
5 6 1 2 3 4

思想: 此题对于数组右移不需要去实现一次性移位多少个只需要实现移位一次即可。至于移位m个,则只需在外面套上一个for循环,并控制循环m次即可。

函数代码如下:

int ArrayShift( int a[], int n, int m )
{
  int i;
  int k;
  for(k=1;k<=m;k++)
  {
    int temp=a[n-1];
    for(i=n-1;i>0;i--)
     {
        a[i]=a[i-1];
     }
     a[0]=temp;
  }
}


  1. 阶乘计算升级版

描述: 本题要求实现一个打印非负整数阶乘的函数。

函数接口定义:
void Print_Factorial ( const int N );

其中N是用户传入的参数,其值不超过1000。如果N是非负整数,则该函数必须在一行中打印出N!的值,否则打印“Invalid input”。

裁判测试程序样例:

#include <stdio.h>

void Print_Factorial ( const int N );

int main()
{
    int N;
	
   scanf("%d", &N);
    Print_Factorial(N);
    return 0;
}

/* 你的代码将被嵌在这里 */

输入样例:
15

输出样例:
1307674368000

本题原文链接↓↓https://blog.csdn.net/LIUJIALING_lala/article/details/80767121

函数代码如下:

#include <stdio.h>
 
void Print_Factorial ( const int N );
 
int main()
{
    int N;
	
    scanf("%d", &N);
    Print_Factorial(N);
    return 0;
}
void Print_Factorial(int N){
	int a[3000];
	int temp,num,digit;           //temp:每一位的结果  num:进位   digit:结果的位数
	int i,j;
	a[0]=1;
	digit=1;                      //从第1位开始 
	if(N>=0) {
		for(i=2;i<=N;i++){
	    	num=0;
			for(j=0;j<digit;j++){
			  temp=a[j]*i+num;    
			  a[j]=temp%10;       //把当前位的数字存入数字 
			  num=temp/10;        //向前面一位进位 
		    } 
		    while(num){           //当i的阶乘算完,任有进位,则数组需扩大 
		    	a[digit]=num%10;
		    	num/=10;
		    	digit++;
			}
		}
		for(i=digit-1;i>=0;i--){
			printf("%d",a[i]);
		}
	}
	else printf("Invalid input");
} 

思想:

首先:
对于N的值不超过1000,表明了N的阶乘的值是已有的数据形式所不能够存储的所以需要用到数组去存储这个值

其次:
对于0到N,变量i是需要与数组的每一位都要相乘的,而且从低位开始相乘。对于数组中的每一位,它所存储的数是:(与i相乘+进位)%10。

此外要注意:
当你在计算的过程中,肯定要时时刻刻都清楚当前的数组真实的长度吧,所以在这里引进了变量digit,当数组的最高位有进位时,就要根据进位去扩大数组了去存储了。当每一次乘以i时,变量num都需要重新赋值为0,因为相当于又从最低位0位开始新的一轮计算。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值