南邮-软件设计实验(C++版)

说在前面:所有代码实现均在C++环境下实现(与c基本一致,只是文件后缀名不一样)。建立文件(*.cpp),粘贴代码即可,运行~
若将代码直接复制进.c文件编译会出错哦!
如需C语言版移步软件设计-C语言版

本次设计实验主要是对C语言字符串、数组、结构体、文件读写等知识的实际运用。文章中的代码测试基本可以运行,界面还需美化。

A档

一、分数统计

课题内容:

  设计一个分数统计程序。包括学生信息的输入输出以及排序。通过该课题全面熟悉数组、字符串、文件的使用,掌握程序设计的基本方法及友好界面的设计。

课题要求:

(1)输入某班级学生的姓名、分数;
(2)对(1)的分数进行降幂排列并输出;
(3)具有输入输出界面。

运行示例

示例代码:

A1.cpp

#include<stdio.h>
#include<string.h>
#include<iostream>

using namespace std;

void swap(char *p,char *q)
{
    char a[20];
    strcpy(a,p);
    strcpy(p,q);
    strcpy(q,a);
}

int main(){
    int score[5],i,j,score_temp;
    char name[5][10];
    cout<<"********学生成绩排序系统**********"<<endl;
    cout<<"请输入学生姓名成绩:"<<endl;
    for(i=0;i<5;i++){
        cin>>name[i];
		cin>>score[i];
    }
    for(i=0;i<5;i++){
        for(j=i+1;j<5;j++){
            if(score[i]<score[j]){
                score_temp = score[i];
                score[i] = score[j];
                score[j] = score_temp;
                swap(name[i],name[j]);
            }
        }
    }
    printf("学生成绩排名如下:\n");
    for(i=0;i<5;i++){
        printf("%s %d\n",name[i],score[i]);
    }
    return 0;
}


/*
one 90
two 80
three 92
four 99
five 86
*/
//此处测试用例5个,可自行扩展

二、打字程序

课题内容:

  设计一个打字程序。包括随机产生字符串,以及字符串比较和统计。通过此课题,熟练掌握数组、格式输出、字符串处理等。

课题要求:

(1)随机产生一字符串,每次产生的字符串内容、长度都不同;
(2)根据(1)的结果,输入字符串,判断输入是否正确,输出正确率;
(3)具有输入输出界面。

运行示例

示例代码:

A2.cpp

#include<stdio.h>
#include<iostream>
#include<time.h>
#include<stdlib.h>
#include<string.h>


using namespace std;

char *randstr(char *str)
{
	srand(time(NULL));
	int i,len;
	len = rand()%10+2;
	for (i = 0; i < len; ++i)
	{
		switch ((rand() % 3))
		{
		case 1:
			str[i] = 'A' + rand() % 26;
			break;
		case 2:
			str[i] = 'a' + rand() % 26;
			break;
		default:
			str[i] = '0' + rand() % 10;
			break;
		}
	}
	str[i] = '\0';
	return str;
}

int main(){
    char name[20],inputstr[20];
    int i=0,error = 0,gailv,j=5;
    while(j!=0){
        cout << randstr(name)<< endl;
        cin>>inputstr;
        while(name[i]!='\0'){
            if(name[i]!= inputstr[i]){
                error++;
            }
            i++;
        }
        if(error == 0){
            cout<<"输入正确,正确率:100%\n"<<endl;
        }else{
            gailv = (1-error/(float)strlen(name))*100;
            printf("输入错误,正确率:");
            cout<<gailv;
            printf("%%\n");
        }
        j--;
        error=0;
        i=0;
    }

    return 0;
}

三、文本编辑器

课题内容:

  设计一个简单的文本编辑器,该系统要求对一个文本文件中的内容进行各种常规操作,如:插入、删除、查找、替换等功能。通过此课题,熟练掌握文本文件的操作及用字符数组或字符指针实现字符串操作的功能。

课题要求:

(1)编辑文本;
(2)保存、打开指定位置的文本文件;
(3)具有输入输出界面。

运行示例

示例代码

A3.cpp

#include<iostream>
#include<string>
#include<cstdlib>
#include<ctype.h>
#include<cstdio>
#include<fstream>
using namespace std;
int NumberCount=0;//数字个数
int CharCount=0;//字母个数
int PunctuationCount=0;//标点符号个数
int BlankCount=0;//空白符个数

class Node
{
public:
    string character;
    int cursor;
    int offset;
    Node* next;
    Node(){
        cursor=0;//每行的光标初始位置
        offset=0;//每行的初始偏移位置
        next=NULL;
    }
};

class TextEditor
{
private:
    Node* head;
    string name;
    int line;//可更改的行数
    int length;//行数
public:
    TextEditor();
    ~TextEditor();
    string GetName();
    void SetName(string name);
    int GetCursor();
    int MoveCursor(unsigned int offset);
    int SetCursor(int line,int offset);
    void AddText(const string s);
    void InsertText(int seat,string s);
    int FindText(string s);
    void DeleteText(string s);
    int GetLine();
    void Count();
    friend ostream& operator<<(ostream& out,TextEditor &text);
    Node* Gethead(){
        return head;
    }
    //int GetLength()
    //{
   //     return length;
   // }
  //  int FindText(string s);
  //  void DeleteText(int seat,string s);
};

TextEditor::TextEditor()
{
    head=NULL;
    name="test";//文件初始名
    //tail=NULL;
    line=1;
    length=0;
}

TextEditor::~TextEditor()
{
    Node* p=head;
    Node* q;
    while(p!=NULL){
        q=p->next;
        delete p;
        p=q;
    }

}

int TextEditor::GetLine()
{
    return line;
}

string TextEditor::GetName()
{
    return name;
}

void TextEditor::SetName(string name)
{
    this->name=name;
}

int TextEditor::GetCursor()
{
    Node *p=head;
    while(p->next!=NULL)
        p=p->next;
    return p->cursor;
}

int TextEditor::MoveCursor(unsigned int offset)
{
    Node *p=head;
    int i=1;
    if(length+1<line){
        cout<<"输入错误!"<<endl;
        exit(0);
    }
    else{
        while(p->next!=NULL&&i<line){
            p=p->next;
            i++;
        }
    }
    if(offset>p->character.length()){
        cout<<"移动位置太大!"<<endl;
        exit(0);
    }
    else
       p->cursor+=offset;
    //cout<<"p  ->cursor="<<p->cursor<<endl;
    return p->cursor;
}

int TextEditor::SetCursor(int line,int offset)
{
    this->line=line;
   //cout<<"line="<<this->line<<endl;
    return MoveCursor(offset);
}

void TextEditor::AddText(const string s)
{
    line=length+1;
    Node* p=new Node;
    Node* q=head;
    p->character=s;
    p->next=NULL;
    if(head==NULL)
        head=p;
    else{
        while(q->next!=NULL)
            q=q->next;
        q->next=p;
    }

        length++;
       // line++;
}

void TextEditor::InsertText(int seat,string s)
{
    Node *p=head;
    unsigned int i=1;
    if(length+1<line){
        cout<<"输入错误!"<<endl;
        exit(0);
    }
    else{
        while(p->next!=NULL&&i<line){
            p=p->next;
            i++;
        }
    }
    //MoveCursor(seat);
    //cout<<"p->cursor="<<p->cursor<<endl;
    string substr;
    for(i=seat;i<s.length()+seat&&i<=p->character.length();i++)
    substr+=p->character[i];

    p->character.insert(p->cursor,s);


    cout<<"substr="<<substr<<endl;
    DeleteText(substr);//覆盖子串
    p->cursor=0;//光标清零
}

ostream& operator<<(ostream& out,TextEditor &text)
{
    Node* p=text.Gethead();
    while(p!=NULL){
        out<<p->character<<endl;
        p=p->next;
    }
   // cout<<"length="<<text.GetLength()<<endl;
    return out;
}

int TextEditor::FindText(string P)
{
    Node* q=head;
    //int templine=1;
    line=1;
    int p=0;
    int t=0;
    int plen=P.length()-1;
    //cout<<"P="<<P<<endl;
    //cout<<"plen="<<plen<<endl;
    int tlen=q->character.length();
    while(q!=NULL){
            p=0;
            t=0;
        tlen=q->character.length();
        if(tlen<plen){
            line++;
             q=q->next;
        }

        while(p<plen&&t<tlen){
            if(q->character[t]==P[p]){
                t++;
                p++;
            }
            else{
                t=t-p+1;
                p=0;
            }
        }
      //  cout<<"P="<<P<<endl;
      //  cout<<"p="<<p<<endl;
      //  cout<<"plen="<<plen<<endl;
        if(p>=plen){

            return t-plen+1;
        }


        else{
            line++;
            q=q->next;
        }

    }
    return -1;
}

void TextEditor::DeleteText(string s)
{
    Node *p=head;
    int i=1;
    int k=FindText(s);
    if(k==-1)
        cout<<"未出现该字符串!"<<endl;
    else{
        while(p!=NULL&&i<line){
            p=p->next;
           // cout<<p->character<<endl;
            i++;
        }

        p->character.erase(k-1,s.length());
        cout<<"删除成功!"<<endl;
    }
}

void TextEditor::Count()
{
    Node *p=head;
    NumberCount=0;
    CharCount=0;
    PunctuationCount=0;
    BlankCount=0;
    while(p!=NULL){
            for(unsigned int i=0;i<p->character.length();i++){
                if(p->character[i]>='0'&&p->character[i]<='9')
                    NumberCount++;
                else if((p->character[i]>'a'&&p->character[i]<'z')||(p->character[i]>'A'&&p->character[i]<'Z'))
                    CharCount++;
                else if(ispunct(p->character[i]))
                    PunctuationCount++;
                else if(p->character[i]==' ')
                    BlankCount++;
            }
            p=p->next;
    }
}

int main()
{
    int i,j,n=2;
    string s,t,name;
    TextEditor text;
    cout<<"---------------------------------------"<<endl;
    cout<<"1.添加字符"<<endl;
    cout<<"2.设置文档名字"<<endl;
    cout<<"3.获取文档名字"<<endl;
    cout<<"4.显示光标位置"<<endl;
    cout<<"5.设置光标位置,在光标位置处插入文本"<<endl;
    cout<<"6.在文档中查找文本"<<endl;
    cout<<"7.在文档中删除文本"<<endl;
    cout<<"8.统计字母、数字、标点符号、空白符号及总字符个数"<<endl;
    cout<<"9.输入文本"<<endl;
    cout<<"0.退出"<<endl;
    while(n){
       // cout<<endl;
        cout<<endl;
        cout<<"---------------------------------------"<<endl;
        cout<<"请输入:";
        cin>>n;
        getchar();
        switch(n){
            case 1: cout<<"请输入字符:"; getline(cin,s,'\n'); text.AddText(s); break;
            case 2: cout<<"请输入文档名字:"; cin>>name; text.SetName(name); break;
            case 3: cout<<text.GetName()<<endl; break;
            case 4: cout<<"光标在第"<<text.GetLine()<<"行,第"<<text.GetCursor()<<"个字符前!"<<endl; break;
            case 5:{
                cout<<"输入行数:";
                cin>>i;
                cout<<"光标在第"<<text.GetCursor()<<"个字符前!"<<endl;
                cout<<"输入移动位数:";
                cin>>j;
                cout<<"输入插入字符:";
                getchar();
                getline(cin,s);
                text.InsertText(text.SetCursor(i,j),s); break;
            }
            case 6: {
                cout<<"输入查找的字符串:";
                getline(cin,s);
                int k=text.FindText(s);
                if(k==-1)
                    cout<<"查找失败!"<<endl;
                else
                    cout<<"所查找文本首次出现在:"<<text.GetLine()<<"行,第"<<k<<"个字符处!"<<endl;
                    break;
            }
            case 7: cout<<"输入要删除的字符串:"; getline(cin,s); text.DeleteText(s); break;
            case 8: {
                text.Count();
                cout<<"文档中共有:"<<endl;
                cout<<NumberCount<<"个数字"<<endl;
                cout<<CharCount<<"个字母"<<endl;
                cout<<PunctuationCount<<"个标点符号"<<endl;
                cout<<BlankCount<<"个空白字符"<<endl;
                cout<<"共有"<<NumberCount+CharCount+PunctuationCount+BlankCount<<"个字符!"<<endl;
                break;
            }
            case 9: cout<<text; break;
            case 0:{
                string ss=text.GetName();
                ss+=".txt";
                cout<<ss<<endl;
                ofstream outFile(ss.c_str());
                Node* p=text.Gethead();
                while(p!=NULL){
                    outFile<<p->character<<endl;
                    p=p->next;
                }
                exit(0);
                break;
            }
            default: cout<<"输入错误,请重新输入!"<<endl; break;
        }
    }
}


声明:此处参考博客用C++实现简易文本编辑器

四、加密

课题内容:

  设计一个加密程序。包括明文与密钥的转换。通过此课题,熟练掌握数组、格式输出、字符串处理、类型转换等。

课题要求:

(1)输入任意一段明文M,以及密钥K;
(2)根据以下公式将其转换为密文C。
Ci = mi + K ,其中i = 0,1,……n-1 , K 为密钥;
(3)具有输入输出界面。

运行示例

示例代码:

A4.cpp

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

using namespace std;
int main(){
    string M;
    int K;
    cout<<"请输入明文M和密钥K:"<<endl;
    cin>>M;
    cin>>K;
    char C[100];
    strcpy(C,M.c_str());
    for(unsigned int i=0;i<M.length();i++){
        C[i] =  C[i]+K;
    }
    cout<<"加密后的密文是:"<<endl;
    cout<<C<<endl;
    return 0;
}

五、进制转换器

课题内容:

  设计一个进制转换器程序。包括二进制、八进制、十进制、十六进制数互相转换。通过此课题,熟练掌握字符串、格式输出、进制换算的各种操作。

课题要求:

(1)可输入二进制、八进制、十进制、十六进制数;
(2)将已输入的数转换成其余进制的数;
(3)具有输入输出界面。

运行示例

示例代码:

A5.cpp

#include<stdio.h>
#include<iostream>
#include<string>
#include <bitset>

using namespace std;

int Atoint(string s,int radix)    //s是给定的radix进制字符串
{
    int ans=0;
    for(unsigned int i=0;i<s.size();i++)
    {
        char t=s[i];
        if(t>='0'&&t<='9') ans=ans*radix+t-'0';
        else ans=ans*radix+t-'a'+10;
    }
        return ans;
}

int main(){
    cout<<"*******进制转换器*******"<<endl;
    cout<<"请输入一个数,并指定它是几进制数:"<<endl;
    string s;
    int r;
    cin>>s;
    cin>>r;
    int num = Atoint(s,r);
    cout<<"二进制:";
    cout<<bitset<sizeof(num)*2>(num)<<endl;
    printf("八进制:%3o\n",num);    //按八进制格式输出,保留5位高位补零
    printf("十进制:%3d\n",num);    //按十进制格式输出,保留3位高位补零
    printf("十六进制:%3x\n",num);    //按十六进制格式输出,保留5位高位补零
    return 0;
}

B档

六、学生成绩核算系统的设计与实现

课题内容:

  设计一个学生成绩核算系统。能实现从文件中读取学生成绩资料,并提供成绩查询统计服务。通过此课题,熟练掌握文件、数组、结构体的各种操作以及友好界面的设计。

课题要求:

(1)按班级按课程从文件中读入相应的平时成绩、期中考试成绩和期末考试成绩。
(2)三个成绩对总评成绩的百分比被定义为常数,各占总成绩的30%、30%和40%。
(3)计算每位学生的总评成绩。
(4)计算该班级本课程的总平均成绩。
(5)计算处于优、良、中、及格、不及格的学生人数以及占总人数的百分比。其中100-90为优,89-80为良,79-70为中,69-60为及格,60分以下为不及格。
(6)按要求输出成绩在优、良、中、及格、不及格各区间的学生学号、成绩。

程序设计参考思路:

  1、建立文本文件 note.dat,第一行为学生的总人数,其后为每个学生的成绩,每个学生的信息占一行,格式为:
学号(9位) 平时成绩 期中考试成绩 期末考试成绩
例如: 15
B16040801 88 75.5 66
B16040802 91 79.5 76
B16040803 85 75 77
B16040804 79 82 80.5
B16040805 94 83.5 81.5
B16040806 80 69 68
B16040807 82 77 71
B16040808 77 57 58
B16040809 91 88 86
B16040810 96 89 90
B16040814 70 45.5 50
B16040812 74 65 66
B16040813 81 71 76
B16040814 83 75 77
B16040815 85 78 79
  2、从文件中读入相应的平时成绩、期中考试成绩和期末考试成绩时,数据的读入方式可用C语言中的文件读入方式进行,也可用C++中的流实现。
  3、 每次计算出的结果可在屏幕输出,并把每个学生的总评成绩输入到新文件out.dat文件中,
格式为: 学生学号(9位) 总评成绩 成绩等级
例如: B16040801 88 B
为查询方便,可把总评成绩所处等级(优、良、中、及格、不及格)同时保存在文件out.dat中,分别用字母A、B、C、D、E表示。
  4、数据结构(可用C++实现)
两个类:学生(student)和学生成绩(marks)
  (1)学生类
  数据成员: 学号、姓名、专业等
  数据类型
    属性(私有、保护、公有)
  方法:
    构造函数和析构函数
  设置学号 void SetId( long );
  读取学号 long GetId( ); 等等
  (2)学生成绩类 —— 从学生类派生
  数据成员:平时成绩、期中考试成绩、期末考试成绩、总评成绩、成绩等级
  数据类型
    属性(私有、保护、公有)
  方法:
    读入成绩 void In( ifstream& ); 或 void In( FILE* );
    输出成绩 void Out( ofstream& ); 或 void Out( FILE* );
    显示成绩 void print( );
    求总评成绩 void ComputeZP( );
    求等级 void ComputeDJ( );
    读取总评成绩 float GetZP( );
    读取等级 char GetDJ( ); 等等
  5、设计
基本思想:自顶向下、逐步细化
  主要功能:
  (1)总控模块
    功能:编制菜单,不断从菜单选择计算或查询功能执行,直到退出。
  程序流程图:~
  (2)计算
  (3)查询~
  6、实现
编程时要求每一个类建两个文件,即类的定义和实现文件。
注意包含相关的文件。
流程图

功能主界面

功能选择

读取文件数据

读取文件数据并展示

计算等级并显示

计算等级并显示

按等级查询

等级查询

按总评成绩排序

按总评成绩排序

等级展示

等级展示

将排序好的数据保存到文件

将排序数据保存文本

代码示例:

B1.cpp

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

using namespace std;

 struct stu{
     char code[10];
     float s1,s2,s3;
     float score;
     char grade;
 }temp;

 void set_choice(char *choice){
     printf(">>>>>>>>>     1、从文件读取数据        <<<<<<<\n");
     printf(">>>>>>>>>     2、计算并显示成绩         <<<<<<<\n");
     printf(">>>>>>>>>     3、按等级查询              <<<<<<<\n");
     printf(">>>>>>>>>     4、按总评成绩排序         <<<<<<<\n");
     printf(">>>>>>>>>     5、按学号查询             <<<<<<<\n");
     printf(">>>>>>>>>     6、查询所有等级           <<<<<<<\n");
     printf(">>>>>>>>>     7、保存到文件            <<<<<<<\n");
     printf(">>>>>>>>>     0、退出系统               <<<<<<<\n");
     printf("请选择您所需要操作的功能(输入数字):");
     *choice = getchar();
 }

 void dispinfo(){
    system("cls");
    //printf("\n\n");
    printf("*****************学生成绩核算系统*****************\n");
 }

 int readfile(struct stu *list){
    int n;
    int i = 0;
    FILE *fp;
    fp = fopen("note.dat","r");
    fscanf(fp,"%d",&n);
    for(i=0;i<n;i++){
        fscanf(fp,"%s%f%f%f\n",list[i].code,&list[i].s1,&list[i].s2,&list[i].s3);
    }
    printf("\t学号\t\t平时成绩 期中成绩 期末成绩\n");
    for(i=0;i<n;i++){
        printf("\t%s\t%5.1lf\t%5.1lf\t%5.1lf\n",list[i].code,list[i].s1,list[i].s2,list[i].s3);
    }
    printf("***********读取文件成功!按任意键继续!**************\n");
    //scanf("%d",i);
    getch();
    fclose(fp);
    return n;
 }

 void view(struct stu *list,int amount){
    int i=0;
    float average=0;
    printf("\t学号\t\t总评\t等级\n");
    for(i=0;i<amount;i++){
        average+=list[i].score;
        printf("\t%10s\t%6.1f\t%c\n",list[i].code,list[i].score,list[i].grade);
    }
    average/=amount;
    printf("   本班总人数%d  本班平均成绩%.1f\n",amount,average);
    printf("\n******按任意键继续!********\n");
    getch();
 }

 void discharge(struct stu *list,int amount){
    float temp;
    char temp1;
    char temp2[10];
    int i,j;
    for(i=0;i<amount;i++){      //对分数排序
        for(j=0;j<amount;j++){
            if(list[j].score>list[i].score){            //比较分数
                temp = list[j].score;
                list[j].score = list[i].score;
                list[i].score = temp;

                strcpy(temp2,list[j].code);
                strcpy(list[j].code,list[i].code);
                strcpy(list[i].code,temp2);

                temp = list[j].s1;
                list[j].s1 = list[i].s1;
                list[i].s1 = temp;

                temp = list[j].s2;
                list[j].s2 = list[i].s2;
                list[i].s2 = temp;

                temp = list[j].s3;
                list[j].s3 = list[i].s3;
                list[i].s3 = temp;

                temp1 = list[j].grade;
                list[j].grade = list[i].grade;
                list[i].grade = temp1;
            }
        }
    }
    view(list,amount);
 }

 void calculate(struct stu *list,int amount){
    int i=0;
    for(i=0;i<amount;i++){
        list[i].score=list[i].s1*0.3+list[i].s2*0.3+list[i].s3*0.4;

        if(list[i].score>=90)
            list[i].grade = 'A';
        else if(list[i].score>=80)
            list[i].grade = 'B';
        else if(list[i].score>=70)
            list[i].grade = 'C';
        else if(list[i].score>=60)
            list[i].grade = 'D';
        else
            list[i].grade = 'E';
    }
    dispinfo();
    view(list,amount);
 }

 void findgrade(struct stu *list,int amount){
    int i=0,j=0;
    char g;
    dispinfo();
    printf("\n请选择您需要查询的等级(输入大写A/B/C/D/E):\n");
    g = getch();
    printf("\t\t学号\t\t总评\t等级\n");
    for(i=0;i<amount;i++){
        if(list[i].grade==g){
            j++;
            printf("\t\t%10s\t%6.1f\t%c\n",list[i].code,list[i].score,list[i].grade);
        }
    }
    printf("\n\n    等级为%c总共有%d人,总人数%d,占总人数的%.2lf\n",g,j,amount,(double)j/amount);
    printf("\n******按任意键继续!********\n");
    getch();
 }

 void gradelist(struct stu *list,int amount){
    int i=0;
    printf("\t\t等级\t人数\t百分比\n");
    int j=0;
    for(i=0;i<amount;i++){
        if(list[i].grade=='A')
            j++;
    }
    printf("\t\tA\t%d\t%6.3lf\n",j,(double)j/amount);

    for(i=0;i<amount;i++){
        if(list[i].grade=='B')
            j++;
    }
    printf("\t\tB\t%d\t%6.3lf\n",j,(double)j/amount);

    for(i=0;i<amount;i++){
        if(list[i].grade=='C')
            j++;
    }
    printf("\t\tC\t%d\t%6.3lf\n",j,(double)j/amount);

    for(i=0;i<amount;i++){
        if(list[i].grade=='D')
            j++;
    }
    printf("\t\tD\t%d\t%6.3lf\n",j,(double)j/amount);

    for(i=0;i<amount;i++){
        if(list[i].grade=='E')
            j++;
    }
    printf("\t\tE\t%d\t%6.3lf\n",j,(double)j/amount);

    printf("\n******按任意键继续!********\n");
    getch();
 }

void find(struct stu *list,int amount){
    int i=0;
    int flag=1;
    char temp[10];
    dispinfo();
    int flag2;
    do{
        flag2 = 1;
        printf("    请输入学号:");
        scanf("%s",temp);
        for(i=0;i<amount;i++){
            flag = strcmp(temp,list[i].code);
            if(flag==0){
                flag2 = 0;
                break;
            }
        }
        if(flag2==1){
            printf("    您所输入的学号不存在,请重新输入!\n");
        }
    }while(flag2);

    printf("\t\t学号\t总评\t等级\n");
    printf("\t\t%10s\t%6.1f\t%6c\n",list[i].code,list[i].score,list[i].grade);
    printf("\n******按任意键继续!********\n");
    getch();
}

void save(struct stu *list,int amount){
    int i=0;
    FILE *fp;
    fp = fopen("out.dat","w");
    fprintf(fp,"\t\t学号\t总评\t等级\n");
    for(i=0;i<amount;i++){
        printf("\t\t%10s\t%6.1f\t%6c\n",list[i].code,list[i].score,list[i].grade);
    }
    printf("\n\n****输出成功!请查看,按任意键继续*******\n");
    fclose(fp);
    getch();
}

int main(){
    //system("colorF9");
    struct stu list[100];
    char choice;
    int amount;
    while(1){
        dispinfo();
        set_choice(&choice);
        switch(choice){
        case '1':
            amount = readfile(list);
            break;
        case '2':
            calculate(list,amount);
            break;
        case '3':
            findgrade(list,amount);
            break;
        case '4':
            discharge(list,amount);
            break;
        case '5':
            find(list,amount);
            break;
        case '6':
            gradelist(list,amount);
            break;
        case '7':
            save(list,amount);
            break;
        case '0':
            system("cls");
            printf("*******欢迎再次光临**********\n");
            getch();
            break;
        }
    }
    return 0;
}

七、模拟电信计费系统的设计与实现

课题内容:

  设计一个模拟电信计费系统。能实现从文件中读取通话以及费率资料,并提供计费、话费查询和话单查询等服务。通过此课题,熟练掌握文件读写、数组、结构体、格式输入输出的各种操作,以及友好界面的设计和一些算法思想的应用。

课题要求:

  (1) 计费功能。根据存放在源数据文件中的通话记录和长途费率文件对每一条通话记录计算其通话费用,并将结果保存在费用文件中。其中:
  通话费的计算方法如下:
  通话费=长途电话费+本地电话费
  长途电话费=费率(元/分钟)×通话时长(分钟)
     (通话时长不满1分钟的按1分钟计算)
  本地电话费为:3分钟以内0.3元,以后每1分钟递增0.2元。
  (2) 话费查询。输入一个电话号码,从费用文件中统计该电话号码的所有本地话费、长途话费,并从用户文件中查找其用户名,最后在屏幕上显示:
    用户名 电话号码 本地话费 长途话费 话费总计
  (3) 话单查询。输入一个电话号码,查询并在屏幕显示该用户的所有通话记录,格式为:
    用户名 主叫电话号码 被叫电话号码 通话时长

程序设计参考思路:

1、本系统的输入输出文件
本系统的输入文件有三个:
(1) 源数据文件(hd.dat)
  存放:主叫区号 主叫电话号码 被叫区号 被叫电话号码 通话时长(秒)
  每次通话作为一条记录,占源数据文件的一行。
  每条记录中各数据之间以空格间隔,例如:025 83491234 010 62320983 90
  每个电话号码可以有多次通话记录。
  如果主、被叫区号相同,则通话记录为本地通话记录;否则为长途通话记录。
(2) 长话费率文件(fl.dat)
  存放:区号 费率
  例如:010 1.20 表示从本地打往区号为010的地区每分钟收费1.20元。
(3) 用户文件(yh.dat)
  存放: 电话号码 用户姓名
  例如: 83491234 张明
本系统的输出文件有一个:
  费用文件(fy.dat)
存放:主叫电话号码 通话类型 话费金额
其中,通话类型表示本次通话是长途还是本地。
2、系统输入数据
hd.dat—有20条通话记录,分别是:
025 83491234 025 85319971 70
025 84927038 010 62140045 236
025 87216340 025 84521009 310
025 83491234 0571 82199516 100
025 58120321 021 81094532 50
025 83491234 025 85319971 80
025 84927038 025 83491234 145
025 58120321 025 87216340 47
025 87216340 010 62140045 93
025 83491234 010 62140045 792
025 84927038 0571 82199516 931
025 83491234 025 85319971 580
025 84927038 025 83491234 358
025 58120321 021 81094532 197
025 87216340 025 84521009 256
025 87216340 010 62140045 193
025 83492200 025 84521009 320
025 83491234 025 85319971 270
025 84927038 025 83491234 231
025 83492200 025 84927038 72
fl.dat 有4条记录
010 1.20
020 1.20
021 0.80
0571 1.00
yh.dat 有5条记录
83491234 张明
84927038 李小红
87216340 王励
83492200 赵强
58120321 杨冬
3、数据结构(可用C++实现)
三个类:话单(callist)、费用(charge)和用户(user)
两个常量:存放本地费率和递增量
(1)话单类
  数据成员: 主叫区号、主叫电话号码、被叫区号、被叫电话号码、通话时长
  数据类型: 属性(私有、保护、公有)
  方法: 构造函数和析构函数、从源数据文件读入通话数据、显示一次通话数据、取主叫区号、取主叫电话号码 等等
(2)费用类 —— 从话单类派生
  数据成员: 通话类型、通话费用
  数据类型: 属性(私有、保护、公有)
  方法: 构造函数和析构函数、从费用文件读入费用数据、向费用文件输出数据、屏幕显示费用、求通话费用、求通话类型、取(返回)通话类型、取通话费用 等等
(3)用户类
  数据成员: 姓名、电话号码
  数据类型: 属性(私有、保护、公有)
  方法: 设置用户的电话号码、查询用户名、设置用户名、查询用户的电话号码、显示用户名和电话号码 等等
4、设计
基本思想:自顶向下、逐步细化
主要功能:
  (1)总控模块
功能:程序流程图:~
  (2)计算通话费用
定义一个话单对象,循环处理。
程序流程图:~
  (3)费用查询
定义一个用户对象,根据电话号码查询用户信息从“计算通话费用”模块生成的费用文件中,按通话类型分别统计某一电话号码的所有费用项。可定义一个费用对象,循环累加。在屏幕显示查询结果。
  (4)话单查询
定义一个用户对象,根据电话号码查询用户信息从源数据(话单)文件中,查询某一电话号码的所有通话清单。在屏幕显示查询结果。可定义一个话单对象,查询并显示。
5、实现
  (1)进行话费查询前,必须先进行费用计算。
可以先判断费用文件是否存在,若不存在,则调用计算通话费用模块后再查询;否则直接查询。
或者用一个全局变量实现——全局变量初值为0,调用计算通话费用模块后该全局变量置为1。当要查询通话费时,首先检查该全局变量的值。
  (2)为了统计话费方便,在费用文件中设一“通话类型”,可以用两个不同的字符表示本地和长途,如0表示本地,1表示长途。
  (3)编程时要求每一个类建两个文件,即类的定义和实现文件。
  (4)编程时注意包含相关的文件。

初始界面:

初始界面

读取话费子界面

读取话费子界面

读取数据源文件

数据源文件

显示长话费率文件:

显示长话费率文件

显示用户信息文件:

用户信息文件

返回主菜单,查询通话费用:

通话费用

话费查询:

话费查询

  • 当输入错误时出现提示:
    错误提示
话单查询:

话单查询

输出至文件:

输出文件

退出系统

退出

代码示例:

B2.cpp

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

#define amount 20

using namespace std;
struct s1{
    char aera1[5];
    char calling[10];
    char aera2[5];
    char called[10];
    int time;
};

struct s2{
    char aera[5];
    double rate;
};

struct s3{
    char num[10];
    char name[10];
};

struct s4{
    char calling[10];
    char type[10];
    double money;
};

void readfile(struct s1 *list1,struct s2 *list2,struct s3 *list3){
    int i;
    FILE *fp;
    fp = fopen("hd.dat","r");
    for(i=0;i<amount;i++){
        fscanf(fp,"%s   %s  %s  %s  %d",list1[i].aera1,list1[i].calling,list1[i].aera2,list1[i].called,&list1[i].time);
    }
    fclose(fp);

    fp = fopen("fl.dat","r");
    for(i=0;i<4;i++){
        fscanf(fp,"%s%lf",list2[i].aera,&list2[i].rate);
    }
    fclose(fp);

    fp = fopen("yh.dat","r");
    for(i=0;i<5;i++){
        fscanf(fp,"%s%s",list3[i].num,list3[i].name);
    }
    fclose(fp);
}

void savefile(struct s4 *list4){
    int i;
    FILE *fp;
    fp = fopen("fy.dat","w");
    fprintf(fp,"%s\n","主叫电话号码   通话类型    话费余额(元)");
    for(i=0;i<amount;i++){
        fprintf(fp,"%10s    %10s    %6.2lf\n",list4[i].calling,list4[i].type,list4[i].money);
    }
    fclose(fp);
    printf("    \n\n【信息已输出至费用文件fy.dat,请查看!按任意键返回!】\n");
    getch();
}

void calculate(struct s1 *list1,struct s2 *list2,struct s4 *list4){
    int i;
    int flag = 1;
    double sum = 0;
    double bill;
    int j;
    int k;
    double rate;
    for(i=0;i<amount;i++){
        flag = strcmp(list1[i].aera1,list1[i].aera2);   //全部相等 flag 为0;
        if(flag == 0){
            strcpy(list4[i].type,"本地通话");
            strcpy(list4[i].calling,list1[i].calling);
            if(list1[i].time<180)
                bill = 0.3;
            else{
                k = list1[i].time-180;
                if(k%60 == 0)
                    bill = 0.3+(k/60)*0.2;
                else
                    bill = 0.3+(k/60+1)*0.2;
            }
            list4[i].money = bill;
            sum = sum+bill;
        }
        else{       //flag不为0时为长途话费
            strcpy(list4[i].type,"长途话费");
            strcpy(list4[i].calling,list1[i].calling);
            for(j=0;j<4;j++){
                if(strcmp(list1[i].aera2,list2[j].aera)==0){
                    rate = list2[j].rate;
                }
            }
            if(list1[i].time%60==0){
                k = list1[i].time-180;
                bill = rate*(list1[i].time/60);
            }else{
                k = list1[i].time-180;
                bill = rate*(list1[i].time/60+1);
            }
            list4[i].money = bill;
            sum = sum+bill;
        }
    }
    printf("    主叫电话    通话类型    通话费用\n");
    for(i=0;i<amount;i++){
        printf("    %s      %s      %5.2lf\n",list4[i].calling,list4[i].type,list4[i].money);
    }
    printf("    话费总额为:%.2lf\n\n",sum);
    printf("    按任意键继续:");
    getch();
}

void searchmoney(struct s3 *list3,struct s4 *list4){    //查询话费
    char ch[10];
    double sum1 = 0;
    double sum2 = 0;
    double sum = 0;
    int i,j,flag,flag1,flag2=1;
    do{
        flag2 = 1;
        printf("    请输入电话号码:");
        scanf("%s",ch);
        for(i=0;i<5;i++){   //从用户信息中根据电话号码查询用户名
            flag = strcmp(ch,list3[i].num);
            if(flag==0){
                flag2 = 0;
                break;
            }
        }
        if(flag2==1){
            printf("    您输入的电话号码不存在,请重新输入!\n");
        }
    }while(flag2);
    for(j=0;j<amount;j++){
        flag = strcmp(ch,list4[j].calling);
        if(flag==0){
            flag1 = strcmp(list4[j].type,"本地通话");
            if(flag1==0)
                sum1 = sum1+list4[j].money;
            else
                sum2 = sum2+list4[j].money;
        }
    }
    sum = sum1+sum2;
    printf("    用户名     主叫电话号码  本地通话费用  长途通话费用  总费用\n");
    printf("    %s          %s        %4.2lf        %4.2lf          %4.2lf\n",list3[i].name,ch,sum1,sum2,sum);
    printf("\n按任意键返回!");
    getch();
}

void searchbill(struct s1 *list1,struct s3 *list3,struct s4 *list4){    //话费账单查询
    char ch[10];
    char user[10];
    int i,flag2,flag,sum1=0,sum2=0,sum=0;

    do{
        flag2 = 1;
        printf("    请输入电话号码:");
        scanf("%s",ch);
        for(i=0;i<5;i++){
            flag = strcmp(ch,list3[i].num);
            if(flag==0){
                flag2 = 0;
                break;
            }
        }
        if(flag2==1){
            printf("    您输入的号码不存在,请重新输入!\n");
        }
    }while(flag2);
    strcpy(user,list3[i].name);
    printf("    用户名 主叫号码    被叫号码    通话时长\n");
    for(i=0;i<amount;i++){
        if(!(strcmp(ch,list4[i].calling))){
            printf("    %s   %s  %s %5d\n",user,list4[i].calling,list1[i].called,list1[i].time);
            if(!(strcmp(list1[i].aera1,list1[i].aera2)))
                sum1 = sum1+list1[i].time;
            else
                sum2 = sum2+list1[i].time;
        }
    }
    sum = sum1+sum2;
    printf("    您的总通话时长为%d秒,其中本地通话时长为%d秒,长途通话时长为%d秒\n",sum,sum1,sum2);
    printf("    按任意键返回!");
    getch();
}

void menu(){
    printf("**************电信计费系统*****************\n\n");
    printf(">>>>>>>>>>>   1、读取话费文件  <<<<<<<<<<<<\n");
    printf(">>>>>>>>>>>   2、查询通用话费  <<<<<<<<<<<<\n");
    printf(">>>>>>>>>>>   3、话费查询       <<<<<<<<<<<<\n");
    printf(">>>>>>>>>>>   4、话费账单查询   <<<<<<<<<<<<\n");
    printf(">>>>>>>>>>>   5、输出至文件   <<<<<<<<<<<<\n");
    printf(">>>>>>>>>>>  0、退出系统      <<<<<<<<<<<<\n");
    printf("********************************************\n");
}

void menu1(){
    printf("****************读取话费文件*****************\n\n");
    printf(">>>>>>>>>>>   1、显示源数据文件  <<<<<<<<<<<<\n");
    printf(">>>>>>>>>>>   2、显示长话费率文件 <<<<<<<<<<<<\n");
    printf(">>>>>>>>>>>   3、显示用户信息文件<<<<<<<<<<<<\n");
    printf(">>>>>>>>>>>   0、返回主菜单       <<<<<<<<<<<<\n");
    printf("************************************************\n");
}

void output1(struct s1 *list1){
    printf("主叫区号    主叫电话号码  被叫区号    被叫电话号码  通话时长\n");
    int i;
    for(i=0;i<amount;i++){
        printf("    %s      %s    %5s         %s  %6d\n",list1[i].aera1,list1[i].calling,list1[i].aera2,list1[i].called,list1[i].time);
    }
}

void output2(struct s2 *list2){
    int i;
    printf("    区号  费率\n");
    for(i=0;i<4;i++){
        printf("    %4s     %.2lf\n",list2[i].aera,list2[i].rate);
    }
}

void output3(struct s3 *list3){
    int i;
    printf("    电话号码  用户姓名\n");
    for(i=0;i<4;i++){
        printf("    %s   %8s\n",list3[i].num,list3[i].name);
    }
}

int main(){
    int choice,choice2;
    struct s1 list1[20];
    struct s2 list2[5];
    struct s3 list3[5];
    struct s4 list4[20];
    while(1){
        system("cls");
        menu();
        printf("请选择:");
        scanf("%d",&choice);
        switch(choice){
        case 1:
            readfile(list1,list2,list3);
            do{
                menu1();
                printf("请选择要查询的文件:");
                scanf("%d",&choice2);
                if(choice2==1){
                    printf("\n");
                    output1(list1);
                }else if(choice2==2){
                    printf("\n");
                    output2(list2);
                }else if(choice2==3){
                    printf("\n");
                    output3(list3);
                }else if(choice2==0)
                    break;
                else
                    printf("\n您的输入有误,请重新输入!\n");
            }while(choice2);
            break;
        case 2:
            calculate(list1,list2,list4);
            getch();
            break;
        case 3:
            searchmoney(list3,list4);
            break;
        case 4:
            searchbill(list1,list3,list4);
            break;
        case 5:
            savefile(list4);
            break;
        case 0:
            system("cls");
            printf("\n\n*************谢谢使用!****************");
            getch();
            break;
        default:
            printf("您的输入有误,请重新输入!\n");
            getch();
        }
    }
    return 0;
}
  • 注意:所有代码实现均在C++环境下实现。建立文件(*.cpp),黏贴代码即可,运行
  • 若将代码直接复制进.c文件编译会出错哦!
  • 以上所有代码均在VC++ 6.0 环境下测试运行,如需C语言版本移步软件设计-C语言版

声明:B档实现参考欧阳雪娇文稿

  • 33
    点赞
  • 165
    收藏
    觉得还不错? 一键收藏
  • 3
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值