C语言第二次实验报告

时间:2022-02-16 01:42:37

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

题目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中,定义结构体的时候性别不是数组,而是单个字符,从而无法消掉信息与信息之间的空格,困扰了很久。最终上查阅资料后,改成字符数组就可以了。