首页 > 技术文章 > c++基础实战

0-lingdu 2021-03-01 10:47 原文

1,文件夹相关操作

判断文件夹是否存在,不存在就创建

    string pthOut="../demo/resultimg";
    int direxists = access(pthOut.c_str(),0);    //参数0表示判断是否存在,存在返回0
    cout << direxists << endl;    //判断文件夹是否存在,存在就返回0
    if(direxists!= 0)     //不存在就创建
    {
        int mkdirre=mkdir(pthOut.c_str(),S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH);
        cout<<"dir isnt exists"<<mkdirre<<endl;
    }

1,ubuntu中用access需要用 #include <unistd.h>头文件,

函数原型:int _access(const char *pathname, int mode);需要的参数是char指针,检查模式参数:

00——只检查文件是否存在

02——写权限

04——读权限

06——读写权限

2,ubuntu中用mkdir需要引用头文件#include <sys/stat.h> ,

函数原型:int mkdir(const char *path, mode_t mode); 第二个参数表示新目录的权限,

  • User: S_IRUSR (read), S_IWUSR (write), S_IXUSR (execute)
  • Group: S_IRGRP (read), S_IWGRP (write), S_IXGRP (execute)
  • Others: S_IROTH (read), S_IWOTH (write), S_IXOTH (execute)
  • 汇总指令:Read + Write + Execute: S_IRWXU (User), S_IRWXG (Group), S_IRWXO (Others)

3,注意哦,mkdir这个函数的权限设置有问题!什么问题呢,当你想用makedir创建一个0777权限的文件夹的时候,如果你用sudo +执行命令 来执行,你只能得到一个0775的权限的文件夹,如果你用root用户执行(su root的那种),你就只能得到一个0755权限的文件夹,这是为什么?因为ubuntu系统里有个umask,当前用户的umask是0002,而root用户的umask是0022,这个umask有啥用我不清楚,但是0777& ~0022就只能拿到0755,据说这个东西叫屏蔽位,那么怎么解决这个屏蔽位的问题呢?首先你可以设置ubuntu系统内部的umask是0000,这会引起什么后果,估计蛮可怕,不建议使用,第二个方法是想办法绕过c++makedir的这个问题,我先创建文件,再使用chmod修改刚刚创建的文件夹权限,果然完美解决,,真是个小机灵鬼!

#include <sys/stat.h>
#include <sys/types.h>
#include <unistd.h>
#include <string>
#include <iostream>

using namespace std;
int main(){
string pthOut="./daqing";
int direxists = access(pthOut.c_str(),0);    //参数0表示判断是否存在,存在返回0
cout << direxists << endl;    //判断文件夹是否存在,存在就返回0
if(direxists!= 0)     //不存在就创建
{
    int mkdirre=mkdir(pthOut.c_str(),0755);
    int chmrlt=chmod(pthOut.c_str(),S_IRWXU|S_IRWXG|S_IRWXO);
    cout<<"make dir rlt"<<mkdirre<<endl;
    cout<<"chmod rlt"<<chmrlt<<endl;
}

return 0;
}

 

2,文件夹相关的操作

opendir和readdir,用到了结构

https://www.linuxidc.com/Linux/2018-03/151330.htm

https://blog.csdn.net/nuptwanglei/article/details/43051643

https://blog.csdn.net/lin_fs/article/details/7335573

3,sprintf 

原型:int sprintf(char *str, const char *format, ...)
第一个参数为char字符数组,足够大就行,比如这样:char a[300];
第二个参数为字符的内容或者说是萝卜的坑,往后的参数是萝卜
实例:
//把整数123 打印成一个字符串保存在s 中。
sprintf(s, "%d", 123); //产生"123"
//浮点数的打印格式,默认保存小数点后六位
sprintf(s, "%f", 3.1415926); //产生"3.141593"


sprintf(s,"%s%d%c","i love csdn  ",123,'N');
sprintf(tmstr,"%4d-%02d-%02d %02d:%02d:%02d",1900+ltm->tm_year,ltm->tm_mon,ltm->tm_mday,ltm->tm_hour,ltm->tm_min,ltm->tm_sec);

//格式化字符串,%02d的意思是,整数转化为%d输出,每个占2个字符,如果不足两个字符,就在左侧补上0

%f 传递浮点数,%s传递字符数组,%c传递一个字符

4.memset用于重置一段内存里的内容,据我所知,只能重置为0或者-1

char fcur[150]="";
strcat(fcur,"hehe");
strcat(fcur,"/");
strcat(fcur,"nihao");
memset(fcur,0,sizeof(fcur));

5,键值对map

https://www.cnblogs.com/fnlingnzb-learner/p/5833051.html

6,智能指针:

http://c.biancheng.net/view/1478.html

7,后加加

没想到有一天我会卡在++上,,厉害厉害。

#include <iostream>
using namespace std;
 
int main ()
{
   int  var[3] = {10, 100, 200};    //定义一个c++数组,长度是3,注意这个数组本身就是一个指针
   int *ptr= var;    //指针赋值
   cout << "ptr" << *ptr << endl;    //此处再次证实c++数组就是指向数组第一个值的指针
   int b=1;
   int c=b++;    //此处理解为,先把b的值赋值给c,然后b自己给自己加上一
   cout << "c" << c<<"b"<<b<< endl;    //所以此处c是1,b是2
   for (int i = 0; i < 3; i++)
   {
      cout << "Value of var" << *(ptr++)<<endl;    //和b++同理,ptr也是先取值,再进行自增运算
   }
   return 0;
}

返回值:

ptr10
c1b2
Value of var10
Value of var100
Value of var200

8,opencv Mat遍历

网上有很多遍历方法,今天只学会了一种,而且非常有参考和纪念意义。

#include <iostream>
#include <opencv2/opencv.hpp>
#include "stdio.h"

int main(){
    frame = cv::imread("./xwh11-0718-183032-1.jpg");
    uchar* data=frame.ptr<uchar>();    //指向图片的第一个像素的指针,因为图片在内存中都是连续的,所以只需要挨着读就可以啦,小括号里写0也是可以的
    for(int r = 0;r<frame.rows*frame.cols;r++){
        printf("px is %u ",*(data++)); 
}

 9,层级创建文件夹,

#include <iostream>
using namespace std;
#ifdef _WIN32
//windows系统
#include <io.h>
#include <direct.h>
int mkdirs(char *dirpath) {
    char thisfilename[255]="";
    char gang1 = '/';
    char gang2 = '\\';
    char  thisone;
    int len = strlen(dirpath);
    for (int i = 0; i<len; i++) {
        thisone = dirpath[i];
        thisfilename[i]=thisone;
        if (thisone==gang1 || thisone == gang2) {
            if (_access(thisfilename, 0) == -1) {
                int mkdirre = _mkdir(thisfilename);
                if (mkdirre == -1) {
                    printf("log dir error,quit!\n");
                    return -1;
                }
            }
            else {
                printf("%s already exists\n", thisfilename);
            }
        }
    }
    return 0;
}
#else
//ubuntu系统
#include <cstring>    //strlen要用的头文件
#include <unistd.h>
#include <sys/stat.h>
int mkdirs(char *dirpath) {
    char thisfilename[255] = "";
    char gang1 = '/';
    char gang2 = '\\';
    char  thisone;
    int len = strlen(dirpath);
    for (int i = 0; i<len; i++) {
        thisone = dirpath[i];
        thisfilename[i] = thisone;
        if (thisone == gang1 || thisone == gang2) {
            if (access(thisfilename, 0) == -1) {
                int mkdirre = mkdir(thisfilename,S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH);
                if (mkdirre == -1) {
                    printf("log dir error,quit!\n");
                    return -1;
                }
                else {
                    printf("successfully mkdir %s \n", thisfilename);
                }
            }
            else {
                printf("%s already exists\n", thisfilename);
            }
        }
    }
    return 0;
}
#endif

int main() {
    char hehe[]= "/home/lvnv/temp/t3/";
    int result = mkdirs(hehe);
    printf("mkdirs i got %d \n", result);
    return 0;
}

 10,使用ifstream读取文件内容

#include <fstream>
#include <string>

using namespace std;

int main(int argc, char *argv[])
{
    char cfgpath[] = "D:\\xxx\\yyy\\project\\Config_Camera";
    ifstream ifs;
    ifs.open(cfgpath);
    cout << "ifs" << endl;
    string str;
    if (ifs.is_open()) {
        cout << "opened" << endl;
        while (getline(ifs, str)) {
            cout << "content:" << str.c_str() << endl;
        }
    }
    else {
        cout << "open faile" << endl;
    }
    return 0;
}

 11,地址拷贝

注意,char数组拷贝到int中,会反过来!int向int中拷贝就不会

memcpy(&sound,rlt,2);
#参数:目标地址,把什么东西拷贝到目标地址上去,拷贝几个字节
#头文件#include <string.h>
unsigned int hehe=0;
unsigned char rlt[4]={0x00,0x00,0x02,0x16}; 
//我有一个填充了4个十六进制数的char数组,底层数据应该是这样的:
//00000000    00000000    00000010    00010110    

memcpy(&hehe,rlt,4);
//我把rlt拷贝到hehe上去

printf("%d \n",hehe);
//打印出来一个莫名奇妙的数!!!这是为什么呢?
//因为拷贝过来的真实数据是这样的:
//00010110    00000010     00000000    00000000 囧!!
//所以,我如果想拿到十进制的534(二进制是00000010    00010110 )我得手动把char数组写成反的,所以建议大家慎用
//unsigned char rlt[4]={0x16,0x02,0x00,0x00}; 

12,位运算

还是11的需求,我能拿到两个字节,每个字节都是一个十六进制数,比如0x02,0x16,我要得到十六进制的216所对应的十进制数,534,更快的办法应当是位运算。

这样做

int sound = 0int sound1=0;
sound=0x02;
sound1=0x16;
int rlt=(sound<<8)+sound1;

//解释一下,sound<<8表示把sound的二进制数向左移动八位,空的填写0,
//  0x02原本是这样的:00000000 00000000 00000000 00000010
//  移动以后是这样的:  00000000 00000000 00000010 00000000
//移动以后再加上0x16: 00000000 00000000 00000010 00010110也就是534

为什么int可以直接等于一个十六进制数呢?因为他俩底层的二进制是一样的,所以,十进制的2就等于十六进制的0x02

推荐阅读