记录第二周的C++作业


作业要求

Visual Studio 编写一个控制台程序<程序名Members.exe为例>,功能如下:
第一阶段:依次输入姓名,性别,工号,电话,然后即时的显示出来。
第二阶段:把输入信息以下面格式保存在文本中,并且可以增加人员信息并保存:这个阶段程序完成后请存入6名以上同仁信息。
Index 1
Name: xxx
Sex: Male
ID: W00000
Number: 121
第三阶段:查询人员信息:
输入"Members.exe -find Index1""Members.exe -find xxx" "Members.exe -find 121" "Members.exe -find W00000" 均直接显示这个人员的所有信息。
输入"Members.exe -find Male" 即显示出Sex为Male 的所有人信息。
第四阶段:把所有人员信息按照ID的大小排序。并把排序后的结果保存在原文本里。

头文件和全局变量

#define _CRT_SECURE_NO_WARNINGS
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<cstring>
#include <iostream>
#include<fstream>
#include<io.h>
int file_exists(const char* filename);
int get_from_txt();
int write_to_txt(int i);
int sort_member();
using namespace std;
struct member {
    int index;
    char Name[10];
    char Sex[8];
    char ID[10];
    char Number[13];
};
member X[7];

主函数

int main(int nArgc,char *argv[])
{
    //定义一个index字符串
    char flag[12] = "index";
    //用于拼接和保存字符化后的整型变量
    char str[12], string[6];
    //用于给成员分配index、接收命令行参数、非命令行下的选择操作
    int i = 1; char sel[12]; int s;
    //判断是否存在成员信息,不存在则进行写入
    if (!file_exists("member.txt"))
    {
        write_to_txt(i);
    }
    //存在的话则从缓存中读取数据
    else
    {
        get_from_txt();
    }
    //如果不在命令行运行或未配置参数,则提供可选择的操作
    if (nArgc == 1)
    {
        printf("是否需要排序?如果是请输入1:");
        scanf("%d", &s);
        if (s == 1)
        {
            sort_member();
            printf("已完成排序,是否需要保存信息?如果是请输入1:");
            scanf("%d", &s);
            if (s == 1)
            {
                FILE* fp = fopen("member.txt", "a");
                for (int j = 0; j < 7; j++)
                {
                    fprintf(fp, "index %d\nName:%s\nSex:%s\nID:%s\nNumber:%s\n\n", X[j].index, X[j].Name, X[j].Sex, X[j].ID, X[j].Number);
                }
                printf("信息已经保存,请进行其他操作。\n");
                fclose(fp);
            }
            printf("是否需要显示所有成员信息?如果是请输入1:");
            scanf("%d", &s);
            if (s == 1)
            {
                for (int j = 0; j < 7; j++)
                {
                    printf("index %d\nName:%s\nSex:%s\nID:%s\nNumber:%s\n\n", X[j].index, X[j].Name, X[j].Sex, X[j].ID, X[j].Number);
                }
            }
        }
        else
        {
            printf("未对信息进行排序,请进行其他操作。\n");
            printf("是否需要显示所有成员信息?如果是请输入1:");
            scanf("%d", &s);
            if (s == 1)
            {
                for (int j = 0; j < 7; j++)
                {
                    printf("index %d\nName:%s\nSex:%s\nID:%s\nNumber:%s\n\n", X[j].index, X[j].Name, X[j].Sex, X[j].ID, X[j].Number);
                }
            }
        }
    }
    //包含程序名在内参数为3个时进行下一步匹配
    if (nArgc == 3)
    {
        //除程序名之外第一个参数为“-find”时进入查询
        if (!_stricmp(argv[1], "-find"))
        {
            //为sel复制第二个参数的地址
            strcpy(sel, argv[2]);
            for (int j = 0; j < 7; j++)
            {
                //每次循环都为str分配字符串flag的地址
                strcpy(str, flag);
                //将成员的index信息转为字符型变量,并存入string
                _itoa(X[j].index, string, 10);
                //将str与string拼接为index1的形式
                strcat_s(str, string);
                //或语句匹配成员的每一项信息
                if (!_stricmp(str, sel) | !_stricmp(X[j].Sex, sel) | !_stricmp(X[j].ID, sel) | !_stricmp(X[j].Name, sel) | !_stricmp(X[j].Number, sel))
                {
                    printf("index %d\nName:%s\nSex:%s\nID:%s\nNumber:%s\n\n", X[j].index, X[j].Name, X[j].Sex, X[j].ID, X[j].Number);
                }
            }
            //相关信息已全部列出
            cout << "All The Relevant Information Has Been Listed.";
        }
        //如果第一个参数不是“-find”,则提示参数错误
        else
        {
            cout << "Parameters Error.";
        }
    }
    //包含程序名在内如果参数只有两个,且参数与“-find”相符
    else if (nArgc == 2 && !_stricmp(argv[1], "-find"))
    {
        //提示参数不足
        cout << "Insufficient Parameters.";
    }
    //包含程序名在内如果参数只有两个,且参数与“-find”不符
    else if (nArgc == 2 && _stricmp(argv[1], "-find") != 0)
    {
        //提示参数错误
        cout << "Parameters Error.";
    }
    //包含程序名在内参数大于3时
    else if (nArgc > 3)
    {
        //提示参数过多
        cout << "Too Many Parameters.";
    };
}

几个函数

//用于判断文件是否存在,不存在则返回0
int file_exists(const char* filename)
{
    return (_access(filename, 0) == 0);
}
//当成员信息不存在时,则为结构体写入信息,并创建一个保存信息的文本
int write_to_txt(int i)
{
    printf("请依次输入姓名、性别、工号、电话号码,以空格键分隔:\n");
    //首先输入第一个成员信息
    X[0].index = 1;
    scanf("%s %s %s %s", X[0].Name, X[0].Sex, X[0].ID, X[0].Number);
    printf("index %d\nName:%s\nSex:%s\nID:%s\nNumber:%s\n\n", X[0].index, X[0].Name, X[0].Sex, X[0].ID, X[0].Number);
    //初始化X[6]的index值,用于结束后面的while循环
    X[6].index = 0;
    //创建文本
    FILE* fp1 = fopen("member.txt", "wt");
    //创建一个副本,方便读取信息
    FILE* fp2 = fopen("member_temp.txt", "wt");
    //写第一个成员信息
    fprintf(fp1, "index %d\nName:%s\nSex:%s\nID:%s\nNumber:%s\n\n", X[0].index, X[0].Name, X[0].Sex, X[0].ID, X[0].Number);
    //副本中只写入信息而不附加说明
    fprintf(fp2, "%d\n%s\n%s\n%s\n%s\n", X[0].index, X[0].Name, X[0].Sex, X[0].ID, X[0].Number);
    //一直到第7个成员信息被写入,结束循环
    while (X[6].index == 0)
    {
        X[i].index = i + 1;
        printf("请依次输入姓名、性别、工号、电话号码,以空格键分隔:\n");
        scanf("%s %s %s %s", X[i].Name, X[i].Sex, X[i].ID, X[i].Number);
        printf("index %d\nName:%s\nSex:%s\nID:%s\nNumber:%s\n\n", X[i].index, X[i].Name, X[i].Sex, X[i].ID, X[i].Number);
        fprintf(fp1, "index %d\nName:%s\nSex:%s\nID:%s\nNumber:%s\n\n", X[i].index, X[i].Name, X[i].Sex, X[i].ID, X[i].Number);
        fprintf(fp2, "%d\n%s\n%s\n%s\n%s\n", X[i].index, X[i].Name, X[i].Sex, X[i].ID, X[i].Number);
        //写下一个成员
        i++;
    }
    //关闭打开的文本
    fclose(fp1);
    fclose(fp2);
    return 0;
}
//如果信息存在,则从副本中读取信息并传递给结构体变量
int get_from_txt()
{
    //初始化变量j
    int j = 0;
    //初始化一个字符串变量用于保存副本中的每行信息
    char str[13];
    //以读方式打开副本
    FILE* fp = fopen("member_temp.txt", "r");
    while (j <= 6)
    {
        //for循环用于给每个成员分配五行信息
        for (int i = 1; i <= 5; i++)
        {
            //第一次执行读取第一行数据,第二次则读取第二行
            fgets(str, 13, fp);
            //如果读取到换行符,说明已经读取整行信息
            if (str[strlen(str) - 1] == '\n')
            {
                //将换行符改为终止符
                str[strlen(str) - 1] = '\0';
                //switch case语句分配信息到正确的位置
                switch (i)
                {
                case(1):
                {
                    X[j].index = atoi(str);
                    break;
                };
                case(2):
                {
                    strcpy(X[j].Name, str);
                    break;
                };
                case(3):
                {
                    strcpy(X[j].Sex, str);
                    break;
                };
                case(4):
                {
                    strcpy(X[j].ID, str);
                    break;
                };
                case(5):
                {
                    strcpy(X[j].Number, str);
                    break;
                };
                };
            }
        }
        //为下一个成员分配信息
        j++;
    }
    //while循环结束则关闭副本
    fclose(fp);
    return 0;
}
//冒泡排序,用于按成员ID升序排序
int sort_member()
{
    //一个用于缓存的结构体变量
    member temp;
    for (int j = 0; j < 7; j++)
    {

        for (int k = 1; k < 7 - j; k++)
        {
            temp = X[k];
            //C++标准库strcmp,用于比较字符串,前大于后返回1,相等返回0,后大于前返回-1
            if (strcmp(X[k - 1].ID, X[k].ID) == 1)
            {
                X[k] = X[k - 1];
                X[k - 1] = temp;
            }
        }
    }
    return 0;
}