C语言第二次实验报告

一.实验题目,设计思路,实现方法。

题目1:11-8 螺旋方阵

所谓“螺旋方阵”,是指对任意给定的N,将1到N×N的数字从左上角第1个格子开始,按顺时针螺旋方向顺序填入N×N的方阵里。本题要求构造这样的螺旋方阵。

输入格式:
输入在一行中给出一个正整数N(<10)。
输出格式:
输出N×N的螺旋方阵。每行N个数字,每个数字占3位。

设计思路:

螺旋方针,螺旋填数。

实现方法:

定义一个标记loop,loop用来记录行数。然后通过n-loop来实现对行数的控制。
运用while循环嵌套,最外圈的while循环一次,则填一圈的数,从而只要循环n/2次即可填满全部的数。
定义count来进行填数。每次个循环后,count加一,实现数累加。

题目2:12-8 删除重复字符

本题要求编写程序,将给定字符串去掉重复的字符后,按照字符ASCII码顺序从小到大排序后输出。

输入格式:
输入是一个以回车结束的非空字符串(少于80个字符)。
输出格式:
输出去重排序后的结果字符串。

设计思路:

使用gets()函数实现长字符串的读取。并用strlen()函数计算字符串的长度。
通过for循环嵌套实现去除重复字符。
通过选择排序进行对剩余字符按ASCII码顺序排序。

解决方案:

删除重复字符:定义两个字符数组,数组n用于存储键盘输入的字符,而数组m用于存储去除后的字符数组。通过for循环嵌套,判断前i个里面是否有与第i个相同的字符,如果没有则存入数组m中,如果有,则进入下一个字符的判断。

字符排序:与选择排序相同,先找出ASCII码最小的字符,放到最前面,接着找出第二小的……从而实现对按ASCII码顺序排序。

题目3:13-6 数组循环右移

本题要求实现一个对数组进行循环右移的简单函数:一个数组a中存有n(>0)个整数,将每个整数循环向右移m(≥0)个位置,即将a中的数据由(a0 a1 ⋯ a n-1)变换为(an-m ⋯ an-1a0 a1 ⋯ 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;
}

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

设计思路:

定义一个新的数组b[],将转化后的新的数组存入数组b[]中,然后通过for循环将数组b中的内容复制到数组a中。

解决方案:

由于要右移m个位子,注意到b数组的第(i+m)%n个位子对应着数组a的第i个位子,从而在for循环中可以有  b[(j+m)%n] = a[i]  ,i从0到n。

题目4:14-6 通讯录的录入与显示

通讯录中的一条记录包含下述基本信息:朋友的姓名、出生日期、性别、固定电话号码、移动电话号码。 本题要求编写程序,录入N条记录,并且根据要求显示任意某条记录。

输入格式:
输入在第一行给出正整数N(≤10);随后N行,每行按照格式姓名 生日 性别 固话 手机给出一条记录。其中姓名是不超过10个字符、不包含空格的非空字符串;生日按yyyy/mm/dd的格式给出年月日;性别用M表示“男”、F表示“女”;固话和手机均为不超过15位的连续数字,前面有可能出现+。

在通讯录记录输入完成后,最后一行给出正整数K,并且随后给出K个整数,表示要查询的记录编号(从0到N−1顺序编号)。数字间以空格分隔。

输出格式:
对每一条要查询的记录编号,在一行中按照姓名 固话 手机 性别 生日的格式输出该记录。若要查询的记录不存在,则输出Not Found。

设计思路:

使用结构体,使每个成员的信息都成为一个整体,主函数中定义结构体数组,从而实现输入多组成员信息。
通过数组实现多组数据的查询输出。

实现方法:

在结构体中,因为固定电话,手机可能出现+,从而固话与手机定义为字符数组且比原来多一位。而每个信息在定义的时候都多定义的一位,是为了吃掉输入过程中的空格。
通过%s实现字符串的输入与输出。
通过for循环实现多组数据的查询。

题目5:15-5 建立学生信息链表

本题要求实现一个将输入的学生成绩组织成单向链表的简单函数。

函数接口定义:
void input();
该函数利用scanf从输入中获取学生的信息,并将其组织成单向链表。链表节点结构定义如下:
struct stud_node {
    int              num;      /*学号*/
    char             name[20]; /*姓名*/
    int              score;    /*成绩*/
    struct stud_node *next;    /*指向下个结点的指针*/
};
单向链表的头尾指针保存在全局变量head和tail中。
输入为若干个学生的信息(学号、姓名、成绩),当输入学号为0时结束。
裁判测试程序样例:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

struct stud_node {
     int    num;
     char   name[20];
     int    score;
     struct stud_node *next;
};
struct stud_node *head, *tail;

void input();

int main()
{
    struct stud_node *p;
	
    head = tail = NULL;
    input();
    for ( p = head; p != NULL; p = p->next )
        printf("%d %s %d\n", p->num, p->name, p->score);

    return 0;
}

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

设计思路:

定义结构体指针,通过结构体指针实现链表的新建已经补充。

实现方法:

定义结构体指针 *q,并向内存申请空间。先读取 p->num,判断值是否为0,若不为零则进入循环:读取对应的name、score,判断头指针是否为空,若为空,则新建链表,头指针指向q,然后让tail指针指向q,tail->next为空。若头指针不为空,则让tail->next指向q,再让tail指针指向q,tail->next为空。

二.源程序

题目1:11-8 螺旋方阵

#include <stdio.h>

int main(){
	int n;
	scanf("%d",&n);
	int a[n][n];
	int i=0,j=0,count=1,loop=0;
	a[0][0] = count++;

	while (loop < n/2) {  
	    while (++j < n - loop) {  
	        a[i][j] = count++;  
	    }  
	    j--;  
	    while (++i < n - loop) {  
	        a[i][j] = count++;  
	    }  
	    i--;  
	    while (--j >= loop) {  
	        a[i][j] = count++;  
	    }  
	    j++;  
	    while (--i > loop) {  
	        a[i][j] = count++;  
	    }  
	    i++;  
	          
	    loop++;  
	}  

	if (n % 2 && n != 1) {  
        a[n/2][n/2] = count;  
    }
	for (i=0; i<n; i++) {  
        for (j=0; j<n; j++) {  
            printf("%3d", a[i][j]);  
        }  
        if(i<n-1)printf("\n");  
    }
}
	

题目2:12-8 删除重复字符

#include<stdio.h>
#include<string.h>
int main()
{
	char n[100],m[100];
	gets(n);
	int i,j,len,flag=0,h=0;
	len=strlen(n);
	for(i=0;i<len;i++){
		flag=0;
		for(j=0;j<i;j++){
			if(n[i]==n[j]){
				flag=1;
			}
		}
		if(flag==0){
			m[h]=n[i];h++;
		}
	}
	m[h]='\0';
	int index=0,t;
	len=strlen(m);
	for(i=0;i<len;i++){
		index=i;
		for(j=i+1;j<len;j++){
			if(m[index]>m[j])index=j;
		}
		t=m[i];
		m[i]=m[index];
		m[index]=t;
	}
	for(i=0;i<len;i++){
		printf("%c",m[i]);
	}
	
	return 0;
}

题目3:4-5 求简单交错序列前N项和

int ArrayShift( int a[], int n, int m ){
	int b[n];
	int i;
	int j=0;
	
	for( i=0;i<n;i++,j++ ){
		b[(j+m)%n] = a[i];
	}
	
	for( i=0;i<n;i++ ){
		a[i] = b[i];
	}
	 
}

题目4:14-6 通讯录的录入与显示

#include <stdio.h>

struct student{
	char name[11];			//姓名
	char birthday[11];		//生日
	char sex[2];			//性别
	char fixedline[15];		//固话
	char telephone[15];		//手机 
};
int main(){
	struct student s[11];
	int i,n;
	int k;
	
	scanf("%d",&n);
	if(n<=0) return 0; 
	for(i=0;i<n;i++){
		scanf("%s %s %s %s %s\n",&s[i].name,&s[i].birthday,&s[i].sex,&s[i].fixedline,&s[i].telephone);
	} 
	
	scanf("%d",&k);
	int a[10] = {0};
	for(i=0;i<k;i++){
		scanf("%d",&a[i]);
	}
	for(i=0;i<k;i++){
		if(a[i]<n&&a[i]>=0){
			printf("%s %s %s %s %s",s[a[i]].name,s[a[i]].fixedline,s[a[i]].telephone,s[a[i]].sex,s[a[i]].birthday);
		}else{
			printf("Not Found");
		}
		printf("\n");
	}
}

题目5:15-5 建立学生信息链表

void input()
{
    struct stud_node *q;
    q=(struct stud_node *)malloc(sizeof(struct stud_node));
    scanf("%d", &q->num);
    while(q->num != 0)
    {
        scanf("%s %d", q->name, &q->score);
        if(head == NULL){
            head = q;
            head->next = NULL;
        }
        if(tail != NULL){
            tail->next = q;
        }
        tail = q;
        tail->next = NULL;
        q=(struct stud_node *)malloc(sizeof(struct stud_node));
        scanf("%d", &q->num);
    }
}

三.遇到的问题及解决方法,心得体会

第11次实验-第15次实验的难度远远大于前面的,特别是指针那块的实验,杂乱,学完后深感计算机的博大精深。
在这几次实验中,遇到了较多的困难,如:在题目4中,定义结构体的时候性别不是数组,而是单个字符,从而无法消掉信息与信息之间的空格,困扰了很久。最终上查阅资料后,改成字符数组就可以了。
posted @ 2018-01-22 20:10  兰翔  阅读(542)  评论(0编辑  收藏  举报