您的位置:首页 > 其它

【实训项目】--《手机通讯录》

2015-07-16 23:47 411 查看
/* 
* Copyright (c) 2014, 烟台大学计算机学院 
* All rights reserved. 
* 文件名称:test.cpp 
* 作    者:刘畅
* 完成日期:2015 年  7  月  16 日 
* 版 本 号:v1.0 
*


《手机通讯录》之Telphone.h

#ifndef TELPHONE_H_INCLUDED
#define TELPHONE_H_INCLUDED
#include <iostream>                         //C++标准头文件
#include <fstream>                          //操作文件的头文件
#include <cstdlib>                          //exit()必要的头文件
#include <windows.h>                        //清屏函数必要的头文件
#include <shlobj.h>                         //MessageBox必要的头文件
#include <cstring>
#include <iomanip>
#include "Telphone.h"
using namespace std;
class Person;
/*
    *类名称:PersonTel
    *说明:通讯录中联系人的数据
*/
class PersonTel
{
public:
    PersonTel () {}                                                                    //构造函数
    void setPersonTel(char name[],int age,char sex[],char address[],char phone[]);     //输入
    friend ostream& operator<<(ostream& out, PersonTel& s);                            //重载运算符
    friend class Person;                                                               //将Person声明为友元类
protected:
    char Name[20];                                                                     //姓名
    int Age;                                                                           //年龄
    char Sex[4];                                                                       //性别
    char Address[40];                                                                  //地址
    char Phone[12];                                                                    //电话号码
};
/*
*类名称:Person
    *说明:建立一个通讯录
*/
class Person
{
public:
    Person();
    ~Person();
    void Establish();                                                                  //建立联系人信息
    void Modification();                                                               //修改联系人信息
    void Display();                                                                    //显示联系人信息
    void Query();                                                                      //查询联系人信息
    void Delete();                                                                     //删除联系人信息
    friend int KMP(char a[],char b[]);                                                 //将KMP声明为友元函数
protected:
    PersonTel Per[500];                                                                //最多保存500位联系人
    int NUM;                                                                           //联系人总数
};

#endif // TELPHONE_H_INCLUDED


《手机通讯录》之Telphone.cpp

#include <iostream>                         //C++标准头文件
#include <fstream>                          //操作文件的头文件
#include <cstdlib>                          //exit()必要的头文件
#include <windows.h>                        //清屏函数必要的头文件
#include <shlobj.h>                         //MessageBox必要的头文件
#include <cstring>
#include <iomanip>
#include "Telphone.h"
using namespace std;

/*
    *函数名称:setPersonTel
    *功能描述:将要保存的联系人信息保存到类中.
    *输入参数:name-姓名,age-年龄,sex-性别,address-地址,phone-电话
    *输出参数:Name-姓名,Age-年龄,Sex-性别,Address-地址,Phone-电话
    *返回值:无
    *其他说明:
*/
void PersonTel::setPersonTel(char name[],int age,char sex[],char address[],char phone[])
{
    strcpy(Name,name);
    Age=age;
    strcpy(Sex,sex);
    strcpy(Address,address);
    strcpy(Phone,phone);
}
/*

    *函数名称:Person
    *功能描述:构造函数
    *输入参数:文件中的数据
    *输出参数:对象Person中的数据成员类PersonTel构建的对象
    *返回值:无
    *其他说明:在构建一个Person对象的同时读取文件
*/
Person::Person()                                //构造函数
{
    int num=0;
    ifstream infile("data.dat",ios::in|ios::binary);                   //打开二进制文件
    if (!infile)                                                       //如果找不到文件输出打开失败并退出
    {
        MessageBox(0,"open error!","提示",0);
        exit(1);
    }
    infile.read((char*)&Per[num],sizeof(PersonTel));                    //二进制文件读取
    while (!infile.eof())                                               //当没有达到文件末尾时
    {
        num++;
        infile.read((char*)&Per[num],sizeof(PersonTel));
    }
    infile.close();                                                     //读入完毕一定要关闭文件;
    NUM=num;                                                            //将当前文件中联系人的数目赋值给NUM

}
/*

    *函数名称:~Person
    *功能描述:析造函数
    *输入参数:对象Person中的数据成员类PersonTel构建的对象
    *输出参数:以二进制数据格式存储到文件中
    *返回值:无
    *其他说明:在析构一个Person对象的同时存储数据到中文件
*/
Person::~Person()                               //析构函数,保存数据
{
    ofstream data("data.dat",ios::binary);
    for (int i=0; i<NUM; ++i)
        data.write((char*)&Per[i],sizeof(Per[i]));    //将数据以二进制格式写入文件
    data.close();                                     //写入完毕一定要关闭文件;
}
/*

    *函数名称:KMP
    *功能描述:字符串匹配算法,判断一串字符串是否为另一串的子串
    *输入参数:两串字符串。
    *输出参数:如果匹配失败返回-1,匹配成功则返回其他值
    *返回值:-1 OR others。
    *其他说明:KMP算法的关键是利用匹配失败后的信息,尽量减少模式串与主串的匹配次数以达到快速匹配的目的。
*/
int KMP(char a[],char b[])                      //匹配字符串KMP算法
{
    int i = 0;
    while(a[i]!='\0')
    {
        int tarlen = i;
        int patlen;
        for(patlen=0; b[patlen]!='\0'; patlen++)
        {
            if(a[tarlen++]!=b[patlen])
            {
                break;
            }
        }
        if(b[patlen]=='\0')
        {
            return i;
        }
        i++;
    }
    return -1;
}
/*

    *函数名称  ostream& operator<<.
    *功能描述:重载函数,重载运算符<<.
    *输入参数:引用型输出流对象out和类PersonTel的对象s.
    *输出参数:联系人对象s的数据成员.
    *返回值:  引用型输出流对象out.
    *其他说明:.
*/
ostream& operator<<(ostream& out, PersonTel& s) //重载运算符<<
{
    out<<s.Name<<"\t"<<s.Age<<"\t"<<s.Sex<<"\t"<<s.Address<<"\t\t"<<s.Phone<<endl;
    return out;
}
/*
    *函数名称:Establish
    *功能描述:新建功能,建立一个新的联系人
    *输入参数:当前联系人总数以及新建联系人信息
    *输出参数:新建联系人信息
    *返回值:  无
    *其他说明:将新建的联系人添加到文件的末尾
*/
void Person::Establish()                       //建立联系人信息
{

    if (NUM==0)
        cout<<endl<<"当前联系人列表为空."<<endl<<endl;
    char name[20];         //姓名
    int age;               //年龄
    char sex[4];           //性别
    char address[40];      //地址
    char phone[12];        //电话号码
    do
    {
        int k=1;
        cout<<"请输入姓名:";
        cin>>name;
        for (int i=0; i<NUM; ++i)
        {
            if (strcmp(Per[i].Name,name)==0)
            {
                MessageBox(0,"你输入的姓名已存在,请重新输入(添加备注).","提示",0);  //通过调用MessageBox函数来实现窗口化错误提示
                k=0;
                break;
            }
        }
        if (k==0)
            continue;
        else
            break;
    }
    while(1);
    cout<<"请输入年龄:";
    cin>>age;
    cout<<"请输入性别:";
    cin>>sex;
    cout<<"请输入地址:";
    cin>>address;
    do
    {
        int k=1;
        cout<<"请输入电话号码:";
        cin>>phone;
        for (int i=0; i<NUM; ++i)
        {
            if (strcmp(Per[i].Phone,phone)==0)
            {
                MessageBox(0,"你输入的电话号码已存在.","提示",0);  //通过调用MessageBox函数来实现窗口化错误提示
                k=0;
                break;
            }
        }
        if (k==0)
            continue;
        else
            break;
    }
    while(1);
    cout<<"姓名"<<"\t"<<"年龄"<<"\t"<<"性别"<<"\t"<<"家庭住址"<<"\t"<<"电话号码"<<endl;
    cout<<name<<"\t"<<age<<"\t"<<sex<<"\t"<<address<<"\t\t"<<phone<<endl;
    Per[NUM].setPersonTel(name,age,sex,address,phone);
    ofstream data("data.dat",ios::binary|ios::app);            //将数据以二进制格式保存到文件末尾
    data.write((char*)&Per[NUM],sizeof(PersonTel));
    NUM++;
    data.close();
}
/*
    *函数名称:Modification
    *功能描述:修改功能,通过搜索联系人姓名,修改联系人信息
    *输入参数:二进制文件中的数据
    *输出参数:联系人列表的所有成员及信息
    *返回值:  无
    *其他说明:使用了随机存储和修改,可直接修改那一行的数据
*/
void Person:: Modification()                   //修改联系人信息
{
    int i,k,m;
    char name[20];         //姓名
    int age;               //年龄
    char sex[4];           //性别
    char address[40];      //地址
    char phone[12];        //电话号码
    do
    {
        k=-1;
        cout<<"请输入你想要修改对象的姓名(输入BACK退出):";
        cin>>name;
        if (strcmp(name,"BACK")==0)
            break;
        for (i=0; i<NUM; i++)
        {
            if (strcmp(Per[i].Name,name)==0)
            {
                k=i;
                break;
            }
        }
        if (k==-1)
        {
            MessageBox(0,"你输入的对象不存在,请重新输入.","提示",0); //通过调用MessageBox函数来实现窗口化错误提示
            continue;
        }
        else
        {
            cout<<"姓名"<<"\t"<<"年龄"<<"\t"<<"性别"<<"\t"<<"家庭住址"<<"\t"<<"电话号码"<<endl;
            cout<<Per[k];
            do
            {
                cout<<"请选择你需要修改的内容:"<<endl;
                cout<<"1.姓名    2.年龄    3.性别"<<endl;
                cout<<"4.地址    5.电话    0.退出    "<<endl;
                cout<<"请输入操作指令:";
                cin>>m;
                if (m==0)
                    break;
                switch (m)
                {
                case 1:
                    cout<<"请输入新的姓名:";
                    cin>>name;
                    strcpy(Per[k].Name,name);
                    cout<<Per[k];
                    continue;
                case 2:
                    cout<<"请输入新的年龄:";
                    cin>>age;
                    Per[k].Age=age;
                    cout<<Per[k];
                    continue;
                case 3:
                    cout<<"请输入新的性别:";
                    cin>>sex;
                    strcpy(Per[k].Sex,sex);
                    cout<<Per[k];
                    continue;
                case 4:
                    cout<<"请输入新的地址:";
                    cin>>address;
                    strcpy(Per[k].Address,address);
                    cout<<Per[k];
                    continue;
                case 5:
                    cout<<"请输入新的电话号码:";
                    cin>>phone;
                    strcpy(Per[k].Phone,phone);
                    cout<<Per[k];
                    continue;
                }
            }
            while (1);
            ofstream  outfile1("data.dat",ios::binary|ios::ate|ios::in|ios::out);
            if(!outfile1)
            {
                cerr<<"open error"<<endl;
                exit(1);
            }
            outfile1.seekp(ios::beg);
            outfile1.seekp(sizeof(PersonTel),ios::beg);
            outfile1.seekp(k*sizeof(Per[k]),ios::beg);
            outfile1.write((char*)&Per[k],sizeof(Per[k]));
            outfile1.close();
        }
    }
    while (1);

}
/*
    *函数名称:Display
    *功能描述:显示功能,
    *输入参数:二进制文件中的数据
    *输出参数:联系人列表的所有成员及信息
    *返回值:  无
    *其他说明:无
*/
void Person::Display()                         //显示联系人列表
{

    if (NUM==0)
    {
        MessageBox(0,"当前联系人列表为空.","提示",0);    //通过调用MessageBox函数来实现窗口化错误提示
        cout<<endl;

    }
    else
    {
        cout<<"姓名"<<"\t"<<"年龄"<<"\t"<<"性别"<<"\t"<<"家庭住址"<<"\t"<<"电话号码"<<endl;
        for (int i=0; i<NUM; i++)
            cout<<Per[i];
        cout<<endl;
    }
}
/*
    *函数名称:Query
    *功能描述:查询功能,通过输入某个信息的部分内容,能够查询显示有相关内容的数据
    *输入参数:二进制文件中的数据
    *输出参数:与关键字有关的一组或多组数据
    *返回值:  无
    *其他说明:运用了KMP算法来实现子串匹配母串的功能
*/
void Person::Query()                           //查询联系人信息
{
    int m,i=0;
    char name[20];         //姓名
    int age;               //年龄
    char sex[4];           //性别
    char address[40];      //地址
    char phone[12];        //电话号码
    do
    {
        bool flag=true;
        cout<<"1.姓名    2.年龄    3.性别"<<endl;
        cout<<"4.地址    5.电话    0.退出    "<<endl;
        cout<<"请输入操作指令:";
        cin>>m;
        if (m==0)
        {
            break;
        }
        else if (m==1)
        {
            cout<<"请输入关键字:";
            cin>>name;
            for (i=0; i<NUM; ++i)
                if (KMP(Per[i].Name,name)!=-1)
                {
                    cout<<Per[i];
                    flag=false;
                }
            if (flag==true)
                MessageBox(0,"没有查询到相关内容.","提示",0);
            cout<<endl;
        }
        else if (m==2)
        {
            cout<<"请输入关键字:";
            cin>>age;
            for (i=0; i<NUM; ++i)
            {
                if (Per[i].Age==age)
                {
                    cout<<Per[i];
                    flag=false;
                }
            }
            if (flag==true)
                MessageBox(0,"没有查询到相关内容.","提示",0);
            cout<<endl;
        }
        else if (m==3)
        {
            cout<<"请输入关键字:";
            cin>>sex;
            for (i=0; i<NUM; ++i)
                if (KMP(Per[i].Sex,sex)!=-1)
                {
                    cout<<Per[i];
                    flag=false;
                }
            if (flag==true)
                MessageBox(0,"没有查询到相关内容.","提示",0);
            cout<<endl;
        }
        else if (m==4)
        {
            cout<<"请输入关键字:";
            cin>>address;
            for (i=0; i<NUM; ++i)
                if (KMP(Per[i].Address,address)!=-1)
                {
                    cout<<Per[i];
                    flag=false;
                }
            if (flag==true)
                MessageBox(0,"没有查询到相关内容.","提示",0);
            cout<<endl;
        }
        else if (m==5)
        {
            cout<<"请输入关键字:";
            cin>>phone;
            for (i=0; i<NUM; ++i)
                if (KMP(Per[i].Phone,phone)!=-1)
                {
                    cout<<Per[i];
                    flag=false;
                }
            if (flag==true)
                MessageBox(0,"没有查询到相关内容.","提示",0);

            cout<<endl;
        }
    }
    while (1);
}
/*
    *函数名称:Delete
    *功能描述:删除联系人
    *输入参数:二进制文件中的数据
    *输出参数:删除部分数据后的数据以二进制格式存储到文件中
    *返回值:  无
    *其他说明:新建一个newdata.dat文件用来做中介作用,将原文件中的数据除了要删除的数
     据外保存到这个新文件中,然后再将新文件中的数据写入原文件,达到删除数据的作用
*/
void Person::Delete()                          //删除联系人
{

    ifstream inData("data.dat", ios::in|ios::binary);
    ofstream outData("newdata.dat",ios::binary|ios::out);
    if (!outData || !inData)
    {
        cerr <<"open error" <<endl;
        exit(1);
    }
    char sign[16];
    cout<<"你要删除联系人的姓名:";
    cin >>sign;
    bool flag = true;
    int i=0;
    inData.read((char*)&Per[i],sizeof(PersonTel));
    while (!inData.eof())
    {
        if (strcmp(Per[i].Name,sign)==0)
        {
            cout<<endl<<"你想删除的联系人:";
            cout<<Per[i]<<endl;
            i++;
            flag=false;
            inData.read((char*)&Per[i],sizeof(PersonTel));
            continue;
        }
        outData.write((char*)&Per[i],sizeof(PersonTel));
        i++;
        inData.read((char*)&Per[i],sizeof(PersonTel));
    }
    if (flag)
    {
        MessageBox(0,"对不起!!!联系人中没有你要找的人!!!","提示",0);
        cout <<endl;
        outData.close();
        inData.close();
    }
    else
    {
        outData.close();
        inData.close();
        int i=0;
        ofstream out("data.dat", ios::out|ios::binary);
        fstream in("newdata.dat", ios::in|ios::binary);

        if (!out || !in)
        {
            MessageBox(0,"open error!","提示",0);
            return;
        }
        in.read((char*)&Per[i],sizeof(PersonTel));
        while (!in.eof())
        {
            out.write((char*)&Per[i],sizeof(PersonTel));
            i++;
            in.read((char*)&Per[i],sizeof(PersonTel));

        }
        out.close();
        in.close();
        MessageBox(0,"这个人的信息已经从你的通迅录中删除!!!","提示",0);

    }
}
/*

    *函数名称:Menu
    *功能描述:功能菜单
    *输入参数:无
    *输出参数:输出选项
    *返回值:  无
    *其他说明:每次使用一个功能后重新出现菜单以供选择
*/
void Menu()                                    //菜单
{
    cout<<"选项:"<<endl;
    cout<<"1.添加新的联系人"<<endl;
    cout<<"2.修改联系人信息"<<endl;
    cout<<"3.显示所有联系人"<<endl;
    cout<<"4.查询联系人信息"<<endl;
    cout<<"5.删除联系人    "<<endl;
    cout<<"0.退出"<<endl;
}


《手机通讯录》之main.cpp

#include <iostream>                         //C++标准头文件
#include <fstream>                          //操作文件的头文件
#include <cstdlib>                          //exit()必要的头文件
#include <windows.h>                        //清屏函数必要的头文件
#include <shlobj.h>                         //MessageBox必要的头文件
#include <cstring>
#include <iomanip>
#include "Telphone.h"
void Menu();
int main()
{
    int n;
    Person per;                            //建立一个Person对象
    do
    {

        Sleep(500);                        //等待500毫秒
        Menu();
        cout<<"请输入操作指令:";
        cin>>n;
        if (n==0)
            break;
        switch (n)
        {
        case 1:
            per.Establish();                //新建联系人
            Sleep(1000);
            system("cls");                  //清屏
            continue;
        case 2:
            per.Modification();             //修改联系人信息
            Sleep(1000);
            system("cls");
            continue;
        case 3:
            per.Display();                  //显示联系人列表
            continue;
        case 4:
            per.Query();                    //查询联系人
            Sleep(1000);
            continue;
        case 5:
            per.Delete();                    //删除联系人
            Sleep(1000);
            system("cls");
            continue;
        }
    }
    while (1);
    return 0;
}


初始界面:



新建联系人功能



新建功能电话号码重复报错



显示全部联系人功能:



修改联系人信息功能



删除联系人功能



删除之后再显示所有联系人



学习心得:

这个项目设计做得自我感觉有些水,,,因为主题太简单了,但是过程还是挺复杂的,断断续续的准备了我差不多快一个月的时间,遇到了很多问题并没有及时解决,这几天有个地实训成功改掉了不少BUG。具体的学习心得就不在这说了,写到报告里去,贺老看在浓浓师生情的份上给个满分如何。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: