Demo entry 6677125

reexp

   

Submitted by anonymous on Dec 02, 2017 at 14:43
Language: C. Code size: 3.8 kB.

#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#define _CRT_SECURE_NO_WARNINGS

//学生结点
typedef long TypeOfNum;
typedef double TypeOfMark;
typedef struct Student
{
	char _NameOfStud[10];
	TypeOfNum _NumOfStud;
	TypeOfMark _MarkOfStud;
	struct Student* _NextStud;
}Student;



//输出函数,遍历单链表
int Show_List(Student * HeadPtr)
{
	printf("输出学号\t姓名\t\t成绩\n");
	Student * temp;
	temp = HeadPtr->_NextStud;
	int cnt = 0;
	if (temp == NULL) {
		printf("空链表");
		return 0;
	}
	while (temp != NULL)
	{
		printf("学号为:%d\t", temp->_NumOfStud);
		printf("姓名为:%s\t", temp->_NameOfStud);
		printf("成绩为:%.2lf\n", temp->_MarkOfStud);
		cnt++;
		temp = temp->_NextStud;
	}
	return cnt;
}


//排序函数,将最后一个结点,插入至前面的有序队列中
Student* Sort(Student *head,Student *now)
{
	//如果链表中仅有一个或没有结点,直接返回
	Student* first = head->_NextStud;
	if (head == NULL || head->_NextStud == NULL || first->_NextStud ==NULL)
		return head;

	//如果链表中有两个结点,比较两结点的成绩大小,并做调整
	TypeOfMark nowMark=now->_MarkOfStud;
	if (first->_NextStud == now) {
		if (first->_MarkOfStud > nowMark)
			return head;
		else {
			head->_NextStud = now;
			now->_NextStud = first;
			first->_NextStud = NULL;
			return head;
		}
	}

	Student *t, *q, *p,*k;
	p = first;
	k = first;
	//k是倒数第二个结点指针,如果k的成绩比最后一个结点成绩大于等于,则直接返回
	while ( k != NULL && k->_NextStud != now )
		k = k->_NextStud;
	if (k->_MarkOfStud >= nowMark)
		return head;

	//p是最后一个比now大的结点,q是第一个比now小的结点,now应该插入在p,q之间
	while (p->_NextStud !=NULL){
		q = p->_NextStud;
		if (q->_MarkOfStud <= nowMark && p->_MarkOfStud >= nowMark)
			break;
		p = p->_NextStud;
	}

	//如果q是除now外最小的结点,也就是now仅仅前移了一位,则q后置空
	t = (q->_NextStud == now)? NULL: q->_NextStud;
	p->_NextStud = now;
	now->_NextStud = q;
	q->_NextStud = (t == NULL )? NULL:t;

	//因此最后一个结点由now变成k,
	//此时应该将k下一位置空
	k->_NextStud = NULL;

	return head;
}


//由文件读入创建学生链表
Student* CreateListFile(const char FileName[]) {
	//打开失败则返回
	FILE *StudFile = fopen(FileName, "rt");
	if ((StudFile == NULL)) {
		printf("CANNOT OPEN THE FILE \n");
		return 0;
	}

	//初始化头结点,最后一个结点,当前读入结点
	Student *HeadPtr, *TailPtr, *NowPtr;
	HeadPtr = TailPtr= (Student*)malloc(sizeof(Student));
	memset(HeadPtr,0, sizeof(Student));
	TailPtr->_NextStud = NULL;


	//循环读入每一行,写入缓冲区buf
	while (!feof(StudFile)) {
		char buf[100];
		memset(buf, 0, sizeof(buf));
		fgets(buf,1000, StudFile);
		if (strlen(buf) == 0)
			return HeadPtr;
		
		
		TypeOfNum TempNum;
		char* TempName = (char*)malloc(10);
		TypeOfMark TempMark;
		//读入的字符串做解析,一行中含空格或制表符位均可,将读入的数据写入三个临时变量
		char* token = strtok(buf," \t");
		if(token != NULL) {
			TempNum = atol(token);
			token = strtok(NULL, " \t");
			TempName = token;
			token = strtok(NULL, " \t");
			TempMark = atof(token);
		}

		//初始化当前结点,将读入的一行数据赋给当前结点
		NowPtr = (Student*)malloc(sizeof(Student));
		NowPtr->_NumOfStud = TempNum;
		strncpy(NowPtr->_NameOfStud, TempName, sizeof(NowPtr->_NameOfStud));
		NowPtr->_MarkOfStud = TempMark;
		NowPtr->_NextStud = NULL;

		//如果当前为空链表,则直接插入
		if ((HeadPtr->_NextStud) == NULL) {
			HeadPtr ->_NextStud = NowPtr;
		}
		//否则找到最后一个结点,在其后插入(始终是尾插)
		while (TailPtr->_NextStud!=NULL)
			TailPtr = TailPtr->_NextStud;
		TailPtr->_NextStud = NowPtr;
		TailPtr = NowPtr;
		
		//将最后一个结点,插入至前面的有序链表中
		HeadPtr=Sort(HeadPtr,NowPtr);

		int size=Show_List(HeadPtr);
		printf("size = %d\n",size);
		//清空缓冲区
		memset(buf, 0, sizeof(buf));
	}
	fclose(StudFile);
	return HeadPtr;
}





int main(int argc, char* argv[])
{
	//读入含n个同学成绩的dat文件
	Student * Stud;
	Stud = CreateListFile("grade.dat");
	
	//读入空文件
	Student * blank;
	blank = CreateListFile("gradeNULL.dat");
	Show_List(blank);

	//读入含1个同学的dat文件
	Student * single;
	single = CreateListFile("gradeONE.dat");
	
	return 0;
}

This snippet took 0.01 seconds to highlight.

Back to the Entry List or Home.

Delete this entry (admin only).