数据挖掘实验一(主要:转到使用WSL)

代码内容没啥,比较简单,主要验证解决了三个问题,第一:一些之前没用过的IO流的使用

写到这里了

第二:sort自定义排序函数的使用。

写到这里了

第三:在Clion中分别尝试使用MInGW和WSL(Windows subsystem of Linux)两种环境下编译调试。

MinGW很简单,官网下载----解压-----直接使用

在这里插入图片描述

WSL需要多费很多事,安装LInux子系统,在LInux子系统里面安装CMake、gcc 、g++ 。我遇到的问题:1、忘记了是不是自己在Linux里装的CMake了,版本号低于我CLion里面的Cmake版本,而CLion的CMake好像不太容易换成低版本,所以我只能又回到LInux里面去卸载CMake再下载指定版本的CMAKe(3.20.2,与CLion中匹配一致)2、中间安装CMake遇到很多事情,先下载、再解压,再执行make 、make install 、详见下面链接。 也许是在解压之后少执行了“sudo apt update”去更新?反正按步骤执行解压之后的操作,清华的源表示找不到某个东西,然后换成了阿里的源,然后也执行了“sudo apt update”,之后正常安装上了3.20.2版本的CMAKe。3、Linux与Windows的文件路径格式问题,详见代码中的注释

我自己曾经写的安装wsl的参考过程链接

阿里的Ubuntu镜像源的提供网站

Linux下的cmake安装参考工程链接
在这里插入图片描述

这里标红了的位置:wsl默认的搜索cmake的位置不是这而是,而是boot文件路径下的cmake文件,可能这个搜索路径是某种默认安装方式下的cmake的位置,但是由于它是3.16.3版本,所以我把它卸载了,然后重新在用户根目录的位置下载了新的3.20.2版本的CMAKe的压缩包,并解压缩,安装,所以是被安装在了用户根目录下(home…),而CLion只扫描这个boot路径,所以需要手动设置这里的Cmake路径(如图红线所示)

执行结果:
MinGW(WIndows)环境下

在这里插入图片描述

WSL(Windows subsystem of Linux)(Ubuntu) 环境下

在这里插入图片描述

源代码(这里代码是在WSL的Linux环境下调试通过的,如果需要在MINGW下使用,需要同时修改其中的注释与代码才能运行,如果是别的什么环境,请自己尝试)
//
// Created by Alan on 2022/4/22.
/*数据预处理要实现的功能要求如下:
 * 1、日期中的缺失值(#)使用流水号的字串来确定
 * 2、商品的购买数量不能为负数
 * 3、总额 = 单价 * 购买数量 ,所以新的数据集中可以省略总价字段
 * 4、三个流水表的日期格式要统一
 * 5、门店号同POS机号一样,可以省略一个
 * 6、同一个购物篮的商品按照序号顺序递增保存
 * */
//
#include<iostream>
#include<string>
#include<fstream>
#include<algorithm>
//#include<direct.h>
#include<unistd.h>
using namespace std;
class Sales
{
public:
    string serial;  //流水号
    int market;     //门店号
    int posno;      //POS
    string date;    //短日期
    int sn;         //购买商品序号
    int id;         //商品id
    float num;      //购买数量
    float price;    //销售单价
    float total;    //销售总价
    void print()
    {
        /*全部字段打印*/
        cout << serial<< " " << market << " "  << posno  << " " <<
        date << " "<<sn<<" "<<id<<" "<<num<<" "<<price<<" "<<total<<endl;
    }
};

bool cmp(Sales a, Sales b)
{
    return a.sn < b.sn; //从小到大排序(升序)
}

string current_working_directory()
{
    /*获取当前项目的绝对路径:当前项目的 WorkingDirectory 路径*/
    /*在MinGW编译环境下
     搭配#include<direct.h>
     char buff[250];
    _getcwd(buff, 250);
    std::string current_working_directory(buff);
    return current_working_directory;*/

    //在wsl环境下使用#include<unistd.h>
    char *path;
    path = get_current_dir_name();
    string Path = path;
    return Path;
}

int main()
{


    /**************************选择进行数据预处理的txt源文件与处理数据的存储目标txt文件**********************/
    string path_first = current_working_directory();
    /*获取当前源文件所处的working_directroy(工作目录)的完整路径*/
    string x = "\\";
    /*如果使用MinGW环境,在MinGW环境下可以使用direct.h的_getcwd()方法获取当前工作目录
     * (要提前把工作目录设置成源文件所在文件夹的绝对路径)
     * 然后再加上'\txtname'构成这个txt文件的完整路径,但是 要注意'\\'才会表示为 '\'
     * 所以需要执行:
     * path_first = path_first + x; */
    //而如果在Linux环境下,根本没有direct.h这个头文件,可以使用unistd.h的get_current_dir_name()方法来获取当前工作目录
    //但是注意:在Linux环境下整个工作目录都被解析成以 '/'分隔的路径,所以要执行: +'/textname',
    // 如下所示:
    path_first = path_first + "/";


    string path_from;
    string path_to;
    string from_txt;
    string to_txt;
    cout << "请输入要进行预处理操作的txt文件的文件名(1019.txt、1020.txt、1021.txt):“xxx.txt” \n";
    getline(cin,from_txt);
    if(!from_txt.empty()){
        path_from = path_first +  from_txt;
        cout << "获取数据的文件名为:" << path_from << endl;
    }
    else{
        cout << "输入获取数据的文件名时:存在非法输入";
        exit(1);
    }
    cout << "请输入存放处理后数据的的txt文件的文件名(fl_1019.txt,fl_1020.txt,fl_1021.txt):“xxx.txt” \n";
    getline(cin,to_txt);
    if(!to_txt.empty()){
        path_to = path_first + to_txt;
        cout << "存放数据文件的绝对路径为:" << path_to << endl;
    }
    else{
        cout << "输入存放数据文件名时:存在非法输入";
        exit(1);
    }




    /**************************设置IO流来读入原始数据、写入目标文件**********************/
    ifstream infile(path_from,ios::in);
    /*ios basic_ios<char> : 字符流的基类
     * infile为ifstream类的实例化对象,通过此构造函数,
     * 作为1021.txt文件的输入流,负责读1021.txt到内存*/
    if(infile.fail())
    {
        /*fail():检查是否发生了可恢复的错误*/
        cout << "error open!" << from_txt << "打开发生错误,无法正常打开" << endl;
        exit(1);
    }
    ofstream outfile(path_to,ios::out);
    if(!outfile)
    {
        cout<<"open error!" << to_txt << "打开发生错误,无法正常打开"  <<endl;
        exit(1);
    }




    /**************************将原始数据读到数组中,进行数据预处理**********************/
    Sales sal[10000];
    int sal_size = 0;
    //读入
    while(!infile.eof())
    {
        /*将原始数据读入数组存储,为后面的数据处理做准备*/
        /*eof(): 检查是否到达了文件末尾*/
        if(sal_size == 10000){
            cout << "默认处理数据10000条,而此数据文件有大于10000条数据,只处理到前10000条,后面数据不读入不处理\n";
            exit(1);
        }
        infile >> sal[sal_size].serial >> sal[sal_size].market >>
        sal[sal_size].posno>> sal[sal_size].date>> sal[sal_size].sn>>
        sal[sal_size].id>> sal[sal_size].num>> sal[sal_size].price>> sal[sal_size].total;
        //sal[sal_size].print();
        /*选择调用print函数来查看是否将原始数据正确读入数组中*/
        sal_size++;
    }



    //预处理操作、写到指定txt文件
    /*同一流水号的商品进行排序*/
    sal_size = sal_size - 1;
    /*前面循环的最后一步执行了sal_size++*/
    int i = 0;
    while(i < sal_size){
        int j = i;
        int m = 0;
        if( j + 1 <= sal_size){
            while(sal[j].serial == sal[j+1].serial){
                m++;
                j++;
            }
            sort(sal+i,sal+i+m,cmp);
            /*同组排序:前提是同一个流水号的商品要连续紧邻在一起,当i到i+m位置处为同一流水号的商品记录时
             * sort函数对i到i+m行的数据记录根据他们的sn字段进行升序排序*/
            i = j + 1;
        }
    }


    outfile << "流水号\t\t\t" << "\t门店号\t" << "日期\t" << "\t购买商品序号\t" << " 商品id\t" << "购买数量\t" << "商品单价\t" << endl;
    for(int i = 0; i < sal_size; i++)
    {
        if (sal[i].num<0){
            /*购买数量不能为负数,将负数的购买数量直接取反*/
            sal[i].num=-sal[i].num;
        }
        sal[i].date.assign(sal[i].serial ,0,8);
        /*调用assign函数实现用流水号的子串来全部重写日期字段,清除原始数据的缺失值:
         * 获取serial字符串的子串,从第0位开始,一共取8位字符组成子串赋给date*/


        /*将处理过后的一行数组数据写到指定的txt文件*/
        outfile << sal[i].serial <<"\t"<<sal[i].market<<"\t"<<sal[i].date<<"\t\t"
        << sal[i].sn<<"\t\t"<<sal[i].id<<"\t\t"<<sal[i].num<<"\t\t" <<sal[i].price << endl;
    }
    cout << "该数据文件共有" << sal_size << "行数据记录\n";

    infile.close();//关闭文件
    outfile.close();//关闭文件
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值