C 2015年笔试题

1、写出程序输出结果

void main()
{
    char p[10]="abc";
    char q[]="xyz";
    int i,j;
    i=0;
    while(*(p+i)!='\0') i++;  //此时i=3
    j=0;
    i++;   // i= 4
    while(*(q+j)!='\0')
    {
        *(p+i)=*(q+j);
        j++;
        i++;
    }
    printf("%s", p);
}

解答:经过代码运行,p所指向的字符串内容为{a,b,c,\0,x,y,z,\0},所以最后运行的结果为输出abc。

或者

void main()
{
    char p[10]="abc";
    char q[]="xyz";
    int i,j;
    i=0;
    while(*(p+i)!='\0') i++;  //此时i=3
    j=0;
    i++;   // i= 4
    while(*(q+j)!='\0')
    {
        *(p+i)=*(q+j);
        j++;
    }
    printf("%s", p);
}

解答:经过代码运行,p所指向的字符串内容为{a,b,c,\0,z,\0},所以最后运行的结果为输出abc。 


2、 写出该代码的功能,并给出改进之处

void main()
{
	int n, x, j, i = 1;
	float sum = 1, k = -1;
	printf("Input n and x:\n");
	scanf("%d %d", &n, &x);
	while (i <= n) {
		k = -1;
		for (j = 1; j <= i; j++) {
			k = -1*k*x;
		}
		for (j = 1; j <= i; j++) {
			k =  k/ j;
		}
		sum += k;
		i++;
	}
	printf("%f\n", sum);
}

解答,该代码的功能为求解1+x+x^2/2! +x^3/3! + ... + x^n/n!

该代码可以通过动态规划进行改进,使得时间复杂度下降至O(n),代码如下:

void main()
{
		int n,x,i=1;
		float sum = 1,k = -1;
		printf("Input n and x:\n");
		scanf("%d %d", &n, &x);
		while (i <= n) {
			k = -1 * k*x / i;
			sum += k;
			i++;
		}
		printf("%f", sum);
}

3、代码for(int i=1;i<n;i++) S;是什么结构?该代码如何使用显示结构表示?

解答:该代码是循环判断选择结构。该代码的显示结构如下:

int i = 1;
FOR: if (i<n) goto S0;
        goto S1;
S0: S;
        i = i+1;
        goto FOR;
S1: ...     

4、根据下面的代码,填写表格。内存按2字节编址,整数占2字节,字符占1字节,指针占4字节。每个区域的相对地址都从0开始

int num=2;//2存储在常量区,num存储在全局区,两个都是整形占2字节。
void main()
{
	char str1[10]={"UESTC"};//"UESTC"和10存储在常量区,各占6和2个字节
	char *str2="CHENGDU";//"CHENGDU"存储在常量区,占8各字节,注意’\0’。
	char p;//p存储在main区,占1字节。str1和str2存储在main区,str1占10字节,str2占4字节
}
void func(int m)//m存储在func区,占2字节
{
	int n=10;//n存储在func区,10存储在常量区,各占2字节。
}

根据出现的顺序,就可以知道相对地址为多少了。每占用两个字节,内存向后偏移一位。


填空题

5.1 给定一个数,给出质数分解结果,例如90=2*3*3*5

int main()
{
    int n, i=2;
    printf("\nInput:");
    scanf("%d", &n);
    printf("=");
    i = 2;
    while (n > 1)
    {
        if (n%i == 0)
        {
            printf("%d", i);
            n = n / i;
            if (n > 1) printf("*");
        }
        else i++;  // 如果不能整除时,说明不是其素数
    }
    return 0;
}

 5.2 若100个人围成圈,从第一个人开始,1~3报数,数到3人退出,剩下来的人编号是几

代码:

//求最后剩下的编号
int main(
{
    int n = 100, num[100];
    int m  /*m为已退出人数*/,f = 3, i, *p;

    p = num;
    for (i = 0; i < n; i++)  //将1~n存入num
    {
        *(p + i) = i + 1;
    }
    i = 0;
    m = 0;
    int k = 0;  // k是工作指针
    printf("杀死顺序为:\n");
    while (m < n - 1)
    {
        if (*(p + i) != 0) //碰到元素为0的跳过,说明已经杀死,不再参与计数
        {
            k++;
        }
        if (k == f)  //正好到第f个时,将第f个元素置0
        {
            printf("%d\t",*(p + i)); //输出满足条件的元素
            *(p + i) = 0;
            k = 0; //重新开始计数
            m++;
        }
        i++;
        if (i == n)  //当i = 6时,将i置0,循环操作
            i = 0;
    }
    while (*p == 0)
    {
        p++;
    }
    printf("\n最后一个是:%d",*p);
    return 0;
}

扩展:约瑟夫环问题:【 N个人围成一圈,从第一个开始报数,第M个将被杀掉,最后剩下一个,其余人都将被杀掉。例如N=6,M=5,被杀掉的顺序是:5,4,6,2,3,1】

代码:

//求最后剩下的号
int main()
{
    int n, num[100];
    int m/*注:m为已退出人数*/,f, i, *p;

    printf("n= ");
    scanf("%d", &n); //n是总人数
    printf("f= ");
    scanf("%d", &f); //f是第f个杀掉的人

    p = num;
    for (i = 0; i < n; i++)  //将1~n存入num
    {
        *(p + i) = i + 1;
    }
    i = 0;
    m = 0;
    int k = 0;  // k是工作指针
    printf("杀死顺序为:\n");
    while (m < n - 1)
    {
        if (*(p + i) != 0) //碰到元素为0的跳过,说明已经杀死,不再参与计数
        {
            k++;
        }
        if (k == f)  //正好到第f个时,将第f个元素置0
        {
            printf("%d\t",*(p + i)); //输出满足条件的元素
            *(p + i) = 0;
            k = 0; //重新开始计数
            m++;
        }
        i++;
        if (i == n)  //当i = 6时,将i置0,循环操作
            i = 0;
    }
    while (*p == 0)
    {
        p++;
    }
    printf("\n最后一个是:%d",*p);
    return 0;
}

5.3 带头结点链表逆序  【同2017年24题】

方法1:取下头结点,然后按照头插法即可实现链表逆序

方法2:后继指针指向前驱结点


6 编程题

6.1 将给定字符串例如”aaa111bbb222#”中的数字全部提取出来,放到给定的数组中。字符串以#结尾。

函数形式为void int_find(int arr[], char *pc);溢出以-1作为标志

分析:该题目有一处表述不清,即溢出以-1做为标志。已知C语言无法求出这种情况下的数组长度,所以无法判断数组溢出。综上,该溢出标志可能为数组的最后一个元素,即所有数字查找完毕时以-1结尾

代码:

#include <stdlib.h>

void int_find(char *pc)
{
    int arr[50] = {0};
    char *p = pc;  // p 是工作指针
    int i = 0;
    while (*p != '\0')
    {
        if (*p >'0'&&*p <'9')
        {
            arr[i]=atoi(p);
            /*
            int atoi(const char *str): 把参数str所指向的字符串转换为一个整数(类型为 int 型),该函数返回转换后的长整数,如果没有执行有效的转换,则返回零,标准库:<stdlib.h>
            */
            i++;
            //遇到数字后继续进行直到遇到非数字元素
            while (*p >'0'&&*p <'9')
            {
                p++;
            }
        }
        //如果不是数字,则跳过
        else p++;
    }
    arr[i] = -1; //最后以-1结尾
    //输出arr的值
    int *q = arr;
    for(i = 0;*(q + i) != -1;i++)
    {
        printf("%d\t",arr[i]);
    }
}
int main()
{
    char ch[] ="aaa111bbb222dsadas2ew2ewq213rf32342r53433#";
    char *c = ch;
    int_find(c);
    return 0;
}
  

6.2 随机输入最多100个整数和浮点数,将整数按从大到小排列,浮点数按从小到大排列(浮点数排序可省略),并输出。

如:输入10 12.3 12 5 52.1 3.65 88.6 1.0 输出:12 10 5 1.0 3.65 12.3 52.1 88.6

 分析:这道题目在不借助库函数编程非常困难,也是当年的一道难题。若忽略1.0这样的数字,可以将输入全部视为浮点数,然后判断浮点数可以使用if(int(num)==num)这种方法判断。要实现完美解答,并以最少的时间完成本题,需要借助strstr、atoi、atof三个函数

代码:

#include <stdio.h>
#include <stdlib.h>
//整数降序排序
void sort_int(int num[], int n)
{
    int i, j;
    for (i = 0; i<n - 1; i++)
    {
        for (j = i + 1; j <= n - 1; j++)
        {
            if (num[j]>num[i])
            {
                int temp = num[i];
                num[i] = num[j];
                num[j] = temp;
            }
        }
    }
    //输出整型
    for(i = 0;i < n;i++)
    {
        printf("%d\t",num[i]);
    }
}
//浮点数升序排序
void sort_float(float num[],int n)
{
    int i,j;
    //冒泡排序
    for(i = 0;i < n-1;i++)
    {
        for(j = i+1;j <= n-1;j++)
        {
            if (num[j]<num[i])
            {
                int temp = num[i];
                num[i] = num[j];
                num[j] = temp;
            }
        }
    }
    //输出浮点数
    for(i = 0;i < n;i++)
    {
        printf("%f\t",num[i]);
    }
}
int main()
{
    int intarr[100];
    float fltarr[100];
    int m=0,n,i=0,j=0;
    char buff[100];

    printf("input n:\n"); //n是几个数
    scanf("%d", &n);
    while (m < n)
    {
        scanf("%s", buff);
        //如果是浮点型数
        if (strstr(buff, "."))
            /*
        strstr(str1,str2)函数用于判断字符串str2是否是str1的子串。如果是,则该函数返回 str1字符串从 str2第一次出现的位置开始到 str1结尾的字符串;否则,返回NULL
            */
            fltarr[j++]=atof(buff); //浮点数存入fltarr数组
            /*
            float atof(const char *str)把参数str所指向的字符串转换为一个浮点数(类型为 float型,函数返回转换后的单精度浮点数,如果没有执行有效的转换,则返回零(0.0),标准库:<stdlib.h>
            */
        else
            //若为整型
            intarr[i++] = atoi(buff);//整型存入intarr数组中
        m++;
    }
    printf("排序后:\n");
    sort_int(intarr, i);
    sort_float(fltarr,j);
    return 0;
}

6.3 编写完整的程序,构造整数集合,并实现对该集合操作的若干功能:查找集合内的某元素;集合中加入一个新元素;删除集合中某一元素;求两个集合的并集;求两个集合的交集;并给出main函数调用的例子

分析:该代码等价于构造一个链表,判断某元素是否在链表内,当加入一个元素时,判断该元素是否在链表内,如果不在则插入链表;当删除一个元素时,找到这个元素并删除该节点;输出两个链表的交集,输出两个链表的并集。该题目代码量非常大

代码:

#include <stdio.h>
#include <stdlib.h>

typedef struct node
{
    int data;
    struct node *next;
};

//判断某元素是否在集合内
int isexist(struct node *L, int num)
{
    struct node *p = L->next;
    while (p != NULL)
    {
        if (p->data == num)return 1;
        p = p->next;
    }
    return 0;
}

//增加一个元素
void add(struct node *L, int num)
{
    //头插法,逆序
    if (isexist(L,num) == 0)
    {
        struct node *p = (struct node *)malloc(sizeof(struct node));
        p->data = num;
        p->next = L->next;
        L->next = p;
    }
}

//删除集合中某一元素
void del(struct node *a, int num)
{
    if (isexist(a,num) == 0)
    {
        printf("没有此元素,删除失败!\n");
    }

    struct node *p = a->next, *pre = a;
    while (p != NULL)
    {
        if (p->data == num)
        {
            pre->next = p->next;
            free(p);
            break;
        }
        pre = p;
        p = p->next;
    }
}
//输出链表
void inputnode(struct node *a)
{
    struct node *l = a ->next;
    while(l != NULL)
    {
        printf("%d\t",l ->data);
        l = l ->next;
    }
}

//输出两个集合并集
void intersection(struct node *a, struct node *b)
{
    struct node *p = a->next;
    int flag = 0;
    while (p != NULL)
    {
        printf("%d ", p->data);
        p = p->next;
    }
    struct node *q = b->next;
    while (q != NULL)
    {
        p = a->next;
        flag = 0;
        while (p != NULL)
        {
            if (q->data == p->data)
            {
                flag = 1;
                break;
            }
            p = p->next;
        }
        if (!flag)
            printf("%d ", q->data);
        q = q->next;
    }
}

//输出两个集合交集
void Union(struct node *a, struct node *b)
{
    struct node *p = a->next, *q = b->next;
    while (p != NULL)
    {
        q = b->next;
        while (q != NULL)
        {
            if (p->data == q->data)
            {
                printf("%d ", q->data);
                break;
            }
            q = q->next;
        }
        p = p->next;
    }
}

void main()
{
    struct node *L = (struct node *)malloc(sizeof(struct node)); //L的头结点
    struct node *S = (struct node *)malloc(sizeof(struct node)); //S的头结点
    L->next = NULL;
    S->next = NULL;

    printf("输入L:\n");
    int temp;
    scanf("%d", &temp);
    while (temp != -1)
    {
        add(L, temp);
        scanf("%d", &temp);
    }

    printf("输入S:\n");
    scanf("%d", &temp);
    while (temp != -1)
    {
        add(S, temp);
        scanf("%d", &temp);
    }

    printf("输出L:");
    inputnode(L);
    printf("\n输出S:");
    inputnode(S);

    printf("\n删除L中的元素2:\n");
    del(L,2);
    inputnode(L);

    printf("\n并集:");
    intersection(L, S);
    printf("\n交集:");
    Union(L, S);
}

posted @ 2020-03-24 17:03  PamShao  阅读(894)  评论(0编辑  收藏  举报