python开发环境搭建

工欲善其事必先利其器,想要做python开发首先要搭建好自己的开发环境,搭建环境需要以下安装文件,没有的同学用我给你们的链接下载!

1.python解释器(写博客的时候官网最新版本为3.6.2),我一般用的是3.5开发,
下载地址windows64位操作系统,其他操作系统可以在下面留言我单独发给你们。

安装好python之后默认是会把python3.5安装在
C:\Users[用户名]\AppData\Local\Programs\Python\Python35,不同系统的电脑用户名路径可能不太一样,但是用户名之后的路径一般不会变,进入到这个目录下找到python.exe程序,点击执行就可以进入python解析器啦,在python解析器里面就可以尝试写一些简单的python语法了!

安装成功后进入Python解释器的界面跟下面的图片一样,说明你就安装成功了解释器安装成功

2.pycharm(我常用的python编辑器,当然python编辑器不止这一个)下载地址pycharm下载

下载成功后就点击安装,然后打开

pycharm专业版是要收费的,如果是刚开始学python,可以先点击试用版,试用版可以免费使用一个月,如果要深入研究的话可以试一下网上的破解方法pycharm破解,试过,有效!

然后就可以打开pycharm,开心的撸代码了!当然这样的环境搭建是最基础的,想要做一些高端的开发还需要下载一系列的包,在后续的博客中给大家接着介绍!

C++与C的三目运算符的区别

C语言中的三目运算符返回的是右值,C++语言中三目运算符返回的是左值
C语言
int main()
{
//C语言
int a=10;
int b=20;
printf("%d/n",a>b?a:b);
a>b?a:b=30;//会报错
int c=a>b?a:b;//ok

//C++
a>b?a:b=30;//不会报错

}

Linux学习:简单模拟tar命令实现对目录的打包和解包

打包解包流程:

1.首先在main函数中判断参数个数
如果参数为2代表解包,调用解包函数untar(argv[1]);
如果参数为3代表打包,调用打包函数tar(argv[1], argv[2]);

2.在tar(const char *dstpath, const char *srcpath) 中,仅做一些打包准备工作
1)打开目标文件
2)调用tardir(FILE *dstfile, const char * srcpath) 函数打包目录
3)关闭目标文件

3.在tardir(FILE *dstfile, const char *srcpath)函数中实现打包目录功能
1)打开目录
2)循环读取目录项
3)判断目录项是普通文件还是子目录,此处注意拼接完整路径
a)如果是普通文件,调用tarfile(FILE *dstfile, const char *filepath)函数打包文件
b)如果是子目录,递归调用自己,遍历子目录

4.在tarfile(FILE *dstfile, const char *filepath)函数中实现打包文件
1)打开源文件
2)读取内容写入到目标文件中

5.如果只写入文件内容,那么无法进行解包,所以需要把文件名和文件大小也写入目标文件
1)在tarfile函数中加入代码写入文件名和文件大小
2)如果直接写入文件名,会有绝对路径的情况,所以需要转换为相对路径写入
a)此时,在tardir和tarfile函数中再加入一个参数root,传入初始打包路径,并且在tar函数中先把相对根目录的名字写入到打包文件中,就是name = rindex那段

//打包先告一段落

解包:
1.调用untar函数
在untar中打开要解包的文件,读取第一条记录,创建相对根目录
把读取一行封装成一个getLine函数,使用静态数组
2.循环调用untarfile函数
读取出文件名,此时静态数组中的相对根目录会被覆盖,为了避免这种情况,在untar函数中获取相对根目录时使用strdup函数,该函数会自动进行深拷贝,单独创建一个堆空间来存放相对根目录,注意在最后要释放

把相对根目录传入untarfile函数中,与获取到的文件名进行拼接路径,然后使用完整路径创建文件,并获取内容写入
此时出现新问题,如果有子目录的话,没办法直接创建,并且空目录也需要打包到目标文件中,所以在这一阶段修改打包函数tardir,把要打包的目录名也写入到目标文件中

为了解包时区分读取到的记录是文件还是目录,我们在写入目录名和文件名时加了标记d和-

修改untarfile函数,第一次获取到的不再是文件名,而是文件类型,判断是目录还是文件

如果是类型为d,先创建目录,再次循环调用untarfile

如果是类型为-,创建对应文件并写入数据

为了让循环untarfile函数有结束条件,在打包结束时,tar函数中写入结束标记{--END--}

如果在untarfile函数中获取的类型为结束标记,则返回-1,跳出循环,如果正常创建目录或文件则返回0

#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <dirent.h>
#include <string.h>
#include <strings.h>
// /home/saul/Test/mydir/dir1/a.txt
void tarfile(const char *root, FILE *dstfile, const char *filepath)
{
//把源文件名写入到目标文件
fprintf(dstfile, "-\n%s\n", filepath + strlen(root));
//获取源文件大小
struct stat buf_stat;
stat(filepath, &buf_stat);
//把源文件大小写到目标文件
fprintf(dstfile, "%d\n", (int)buf_stat.st_size);
FILE *fp = fopen(filepath, "r");
if (fp == NULL)
{
printf("open filepath error\n");
return;
}
char buf[4096] = {0};
while(1)
{
int ret = fread(buf, 1, sizeof(buf), fp);
if (ret <= 0)
{
break;
}
fwrite(buf, 1, ret, dstfile);
}
fclose(fp);
}
// /home/saul/Test/mydir/dir1
void tardir(const char *root, FILE *dstfile, const char *srcpath)
{
//把要打包的目录名写入到目标文件
if (strcmp(root, srcpath) != 0)
fprintf(dstfile, "d\n%s\n", srcpath + strlen(root));
//打开文件夹
DIR *dir = opendir(srcpath);
while(1)
{
struct dirent *de = readdir(dir);
if (de == NULL)
break;

    //拼接完整路径
    char filepath[1024] = {0};
    sprintf(filepath, "%s/%s", srcpath, de->d_name);

    if (de->d_type == DT_REG)
    {
        //打包文件函数
        tarfile(root, dstfile, filepath);
    }
    else if (de->d_type == DT_DIR)
    {
        if (strcmp(de->d_name, ".") == 0 || strcmp(de->d_name, "..") == 0)
        {
            continue;
        }
        tardir(root, dstfile, filepath);
    }
}

}

// ./tar.out /home/saul/Test/mytar /home/saul/Test/mydir
// ./mydir
// mydir
void tar(const char *dstpath, const char *srcpath)
{
//打包前的准备工作
FILE *fp = fopen(dstpath, "w");
//在打包前先把源文件的根目录写入目标文件
char *name = rindex(srcpath, '/');
if (name == NULL) name = (char *)srcpath;
else name = name + 1;
fprintf(fp, "%s\n", name);
//打包目录函数
tardir(srcpath, fp, srcpath);
//打包文件加结束标记
fprintf(fp, "%s\n", "{--END--}");
fclose(fp);
}
//获取一行数据的函数
char * getLine(FILE *fp)
{
static char buf[1024] = {0};
fgets(buf, sizeof(buf), fp);
buf[strlen(buf) - 1] = '\0'; //mydir
return buf;
}

int untarfile(const char *root, FILE *fp)
{
char *type = getLine(fp);
if (strcmp(type, "{--END--}") == 0)
return -1;
if (strcmp(type, "d") == 0)
{
char *dirname = getLine(fp); //读取出目录名
char filepath[1024] = {0};
sprintf(filepath, "%s%s", root, dirname); // mydir/dir1
mkdir(filepath, 0777);
return 0;
}
else if (strcmp(type, "-") == 0)
{
char *filename = getLine(fp); // /b.txt
char filepath[1024] = {0};
sprintf(filepath, "%s%s", root, filename); // mydir/b.txt
FILE *dstfile = fopen(filepath, "w");
if (dstfile == NULL)
{
printf("open untar dstfile error\n");
return -2;
}
int filelen = atoi(getLine(fp));
char buf[1024] = {0};
while(filelen > 0)
{
memset(buf, 0, sizeof(buf));
int ret = fread(buf, 1, filelen < sizeof(buf) ? filelen : sizeof(buf), fp);
if (ret <= 0)
break;
fwrite(buf, 1, ret, dstfile);
filelen -= ret;
}
fclose(dstfile);
}
return 0;
}
//解包函数
void untar(const char *path)
{
FILE *fp = fopen(path, "r");
char *root = strdup(getLine(fp));
mkdir(root, 0777); //创建相对根目录
while(1)
{
//解包文件函数
int ret = untarfile(root, fp);
if (ret == -1)
break;
}
free(root);
fclose(fp);
}

// ./tar.out ./mytar ./mydir 打包
// ./tar.out ./mytar 解包
int main(int argc, char *argv[])
{
if (argc == 2)
{
untar(argv[1]); //自定义解包函数
}
else if (argc == 3)
{
tar(argv[1], argv[2]); //自定义打包函数
}
else
{
printf("args error\n");
}
return 0;
}

Linux学习:unlink函数的测试

#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>

int main()
{
//文件的默认引用计数器为1
//打开文件时,文件的引用计数器会加1
int fd = open("./b.c", O_RDONLY);
if (fd < 0)
{
perror("open");
return -1;
}
//使用unlink函数并不会真正的删除文件,而是让文件的引用计数器先减1,但是此时在终端中已经查看不到文件了
unlink("./b.c");
char buf[4096] = {0};
//因为文件没有被真正删除,所以还可以对文件进行读写操作
read(fd, buf, sizeof(buf));
printf("%s\n", buf);
//关闭文件描述符时,引用计数器减1,文件在此时真正被删除
close(fd);
return 0;
}

Linux文件属性:拷贝文件内容的同时可以修改文件属性

#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <utime.h>
//cp a.c b.c
int main(int argc, char *argv[])
{
if (argc != 3)
{
printf("args error\n");
return -1;
}

const char *srcfile = argv[1];
const char *dstfile = argv[2];

FILE *srcfp = fopen(srcfile, "r");
if (srcfp == NULL)
{
    printf("open src file error\n");
    return -1;
}
FILE *dstfp = fopen(dstfile, "w");
if (dstfp == NULL)
{
    printf("open dst file error\n");
    return -1;
}

char buf[4096];
while(1)
{
    int ret = fread(buf, 1, sizeof(buf), srcfp);
    if (ret <= 0)
    {
        break;
    }
    fwrite(buf, 1, ret, dstfp);
}

fclose(srcfp);
fclose(dstfp);

struct stat src_stat;
stat(srcfile, &src_stat);
//让目标文件的时间和源文件保持一致
struct utimbuf tim;
tim.actime = src_stat.st_atime;
tim.modtime = src_stat.st_mtime;
utime(dstfile, &tim);

//修改文件的访问权限
chmod(dstfile, src_stat.st_mode & ~S_IRUSR);
//修改文件的所有者,注意些函数只能用管理员用户调用
chown(dstfile, 0, src_stat.st_gid);
return 0;

}