标签归档:C++

C++14关联容器set自定义排序函数报错

十年前写的一个C++项目编译报错:“bool compatetor_asc::operator ()(const std::wstring &,const std::wstring &)”: 不能将“this”指针从“const compatetor_asc”转换为“compatetor_asc &”

对应的代码如下 :

class compatetor_asc
{
public:
    bool operator()(const std::wstring& lhs, const std::wstring& rhs) 
    {
        return lhs < rhs ;
    }
};

这段代码重载了函数调用操作符(),可以让该类的对象能够像函数一样使用。调用的代码std::set<std::wstring, compatetor_asc> m_OriginalAsc;

当时这个C++项目是用VS2008开发的,C++标准是C++03,现在用VS2022来编译,用的C++标准是C++14。

简单解了一下,原来从C++11开始,标准库排序谓词函数就要求必须是const成员函数了,那么只要把operator()函数改为const成员函数即可。

bool operator()(const std::wstring& lhs, const std::wstring& rhs) const
{
    return lhs < rhs ;
}

修改后再次编译,问题解决。

后记:

已经有近十年没有写过C++项目了,最初学习C++用的是VC++6.0,标准是C++98,到后来有了C++03,现如今已经到了C++23了,二十年如一梦。

C++获取windows系统分区大小及使用情况

C++使用Windows SDK获取系统分区大小以及使用情况,代码如下:

// ConsoleApplication1.cpp : 定义控制台应用程序的入口点。
//
#include "stdafx.h"

#include <stdint.h>
#include <windows.h>
#include <iostream>
#include <string>

using namespace std;

void TestDrive()
{
    cout << "TestDrive" << endl;
    char* lpDrives = (char *)malloc(MAX_PATH * sizeof(char ));
    memset(lpDrives, 0, MAX_PATH * sizeof (char));

    DWORD dwLen = ::GetLogicalDriveStringsA(MAX_PATH, lpDrives);
    cout << "dwLen: " << dwLen << endl;

    DWORD driver_number = dwLen / 4;
    cout << "driver_number: " << driver_number << endl;

    string driver;
    LPTSTR start;
    for (DWORD nIndex = 0; nIndex < driver_number; nIndex++)
    {
        start = lpDrives + nIndex * 4;
        cout << "........................................." << endl;
        driver.append(start);
        cout << "lpDrives + nIndex * 4: " << lpDrives + nIndex * 4 << endl;
        cout << "DRIVE_REMOVABLE: " << DRIVE_REMOVABLE << endl;
        cout << "::GetDriveType(lpDrives + nIndex * 4): " << :: GetDriveType(lpDrives + nIndex * 4) << endl;
        if (::GetDriveType (start) == DRIVE_REMOVABLE)
        {
            driver.append(start);
            if (GetVolumeInformation (start, 0, 0, 0, 0, 0, 0, 0)) //判断驱动是否准备就绪
            {
                cout << "驱动准备就绪 " << endl;
            }
        }
        uint64_t lpFreeBytesAvailable = 0;
        uint64_t lpTotalNumberOfBytes = 0;
        uint64_t lpTotalNumberOfFreeBytes = 0;
        GetDiskFreeSpaceExA(lpDrives + nIndex * 4,
                            (PULARGE_INTEGER)&lpFreeBytesAvailable,
                            (PULARGE_INTEGER)&lpTotalNumberOfBytes,
                            (PULARGE_INTEGER)&lpTotalNumberOfFreeBytes);
        cout << "lpFreeBytesAvailable: " << lpFreeBytesAvailable << endl;
        cout << "lpTotalNumberOfBytes: " << lpTotalNumberOfBytes << endl;
        cout << "lpTotalNumberOfFreeBytes: " << lpTotalNumberOfFreeBytes << endl;
    }
    std::cout << "driver: " << driver << endl;
}

int main(int argc, char *argv[])
{
    TestDrive();
    return 0;
}

std::string 常用函数

string replace(const string & str , const string & src , const string & dest )
{
        string ret;
       
        string:: size_type pos_begin = 0;
        string:: size_type pos       = str.find( src);
        while (pos != string::npos)
       {
              cout << "replacexxx:" << pos_begin <<" " << pos <<"\n";
              ret.append( str.data() + pos_begin, pos - pos_begin);
              ret += dest;
              pos_begin = pos + 1;
              pos       = str.find( src, pos_begin);
       }
        if (pos_begin < str.length())
       {
              ret.append( str.begin() + pos_begin, str.end());
       }
        return ret;
}

int split(const string & str , vector <string >& ret_, string sep = ",")
{
        if ( str.empty())
       {
               return 0;
       }
       
        string tmp;
        string:: size_type pos_begin = str.find_first_not_of( sep);
        string:: size_type comma_pos = 0;
       
        while (pos_begin != string::npos)
       {
              comma_pos = str.find( sep, pos_begin);
               if (comma_pos != string::npos)
              {
                     tmp = str.substr(pos_begin, comma_pos - pos_begin);
                     pos_begin = comma_pos + sep.length();
              }
               else
              {
                     tmp = str.substr(pos_begin);
                     pos_begin = comma_pos;
              }
              
               if (!tmp.empty())
              {
                      ret_.push_back(tmp);
                     tmp = "";
              }
       }
        return 0;
}


string trim(const string & str )
{
        string:: size_type pos = str.find_first_not_of( ' ');
        if (pos == string::npos)
       {
               return str;
       }
        string:: size_type pos2 = str.find_last_not_of( ' ');
        if (pos2 != string::npos)
       {
               return str.substr(pos, pos2 - pos + 1);
       }
        return str.substr(pos);
}

c/c++ float round up

float val = 37.0201;

float rounded_down = floorf(val * 100) / 100;   /* Result: 37.02 */
float nearest = roundf( val * 100) / 100;  /* Result: 37.02 */
float rounded_up = ceilf(val * 100) / 100;      /* Result: 37.03 */

TCHAR number[24]; // dummy size, you should take care of the size!
swprintf_s( number, L "%.2f", rounded_up );
AfxMessageBox( number);

http://stackoverflow.com/questions/1343890/rounding-number-to-2-decimal-places-in-c

C++基于Windows的音频采集

#include "stdafx.h"

#include <time.h>
#include <windows.h>
#include<mmsystem.h>
#include<mmreg.h>
#pragma  comment(lib, "winmm.lib")

struct RIFF_HEADER//文件类型
{
    char szRiffID[4]; // 'R','I','F','F'
    DWORD dwRiffSize;//DWORD最大可容纳4GB的文件大小=FILE_LENGTH-8(即减去此数据结构大小)
    char szRiffFormat[4]; // 'W','A','V','E'
};

struct WAVE_FORMAT
{
    WORD wFormatTag;
    WORD wChannels;
    DWORD dwSamplesPerSec;
    DWORD dwAvgBytesPerSec;
    WORD wBlockAlign;
    WORD wBitsPerSample;
};

struct FMT_BLOCK
{
    char szFmtID[4]; // 'f','m','t',' '
    DWORD dwFmtSize;
    WAVE_FORMAT wavFormat;
};

struct DATA_BLOCK
{
    char szDataID[4]; // 'd','a','t','a'
    DWORD dwDataSize;
};

//struct FACT_BLOCK//可先项 一般可不用
//{
//    char szFactID[4]; // 'f','a','c','t'
//    DWORD dwFactSize;
//};

WAVEFORMATEX pwfx; //声音格式


#define MAX_RUN_COUNT 4
#define BUFFER_COUNT 4
#define MAX_BUFF_SOUNDSIZE 10240
FILE *fptmp;
CHAR m_cBufferIn[BUFFER_COUNT][MAX_BUFF_SOUNDSIZE];
WAVEHDR m_pWaveHdrIn[BUFFER_COUNT];
HWAVEIN phwi; //设备句柄

bool is_stop = false;


void WaveInitFormat(LPWAVEFORMATEX m_WaveFormat, WORD nCh, DWORD nSampleRate, WORD BitsPerSample)
{
    m_WaveFormat->wFormatTag = WAVE_FORMAT_PCM;
    m_WaveFormat->nChannels = nCh;
    m_WaveFormat->nSamplesPerSec = nSampleRate;
    m_WaveFormat->nAvgBytesPerSec = nSampleRate * nCh * BitsPerSample / 8;
    m_WaveFormat->nBlockAlign = m_WaveFormat->nChannels * BitsPerSample / 8;
    m_WaveFormat->wBitsPerSample = BitsPerSample;
    m_WaveFormat->cbSize = 0;
}

DWORD CALLBACK MicCallback(HWAVEIN hwavein, UINT uMsg, DWORD dwInstance, DWORD dwParam1, DWORD dwParam2)
{
    switch (uMsg)
    {
    case WIM_OPEN: //打开设备时消息,在此期间我们可以进行一些初始化工作
        printf("\n设备已经打开...\n");
        break;

    case WIM_DATA: //当缓存已满或者停止录音时的消息,处理这个消息可以对缓存进行重新分配,实现不限长度录音
    {
        WAVEHDR*p = ((PWAVEHDR)dwParam1); // 这就是采集到的数据指针
        DWORD len = p->dwBytesRecorded; // 这就是采集到的数据长度
       

        int i = p->dwUser;
        if (is_stop) //停止
        {
            waveInUnprepareHeader(phwi, p, sizeof(WAVEHDR)); //释放
            return 0;
        }
        
        printf("\n缓冲区%d存满...\n", p->dwUser);
        fwrite(&m_cBufferIn[i], 1, p->dwBytesRecorded, fptmp);
        waveInUnprepareHeader(phwi, p, sizeof(WAVEHDR)); //释放
        


        p->lpData = m_cBufferIn[i];
        p->dwBufferLength = MAX_BUFF_SOUNDSIZE;
        p->dwBytesRecorded = 0;
        p->dwUser = i;
        p->dwFlags = 0;
        waveInPrepareHeader(phwi, p, sizeof(WAVEHDR)); //准备内存块录音
        waveInAddBuffer(phwi, p, sizeof(WAVEHDR)); //增加内存块

        break;
    }
    case WIM_CLOSE: //关闭录音设备时的消息
        printf("\n设备已经关闭...\n");
        break;
    default:
        break;
    }
    return 0;
}

//录音函数
void Start()
{
    //获取声卡数
    int count = waveInGetNumDevs();//1
    printf("\n音频输入数量:%d\n", count);

    //获取声音输入设备
    WAVEINCAPS waveIncaps;
    MMRESULT mmResult = waveInGetDevCaps(0, &waveIncaps, sizeof(WAVEINCAPS));//2
    printf("\n音频输入设备:%s\n", waveIncaps.szPname);

    //如果正确获取到输入设备
    if (MMSYSERR_NOERROR == mmResult)
    {
        /// HWAVEIN phwi; //设备句柄
        //  WAVEFORMATEX pwfx;
        WaveInitFormat(&pwfx, 1, 8000, 8);
        printf("\n请求打开音频输入设备");
        printf("\n采样参数:单声道 8kHz 8bit\n");
        //打开录音设备
        mmResult = waveInOpen(&phwi, WAVE_MAPPER, &pwfx, (DWORD)(MicCallback), NULL, CALLBACK_FUNCTION);//3

        //如果正确打开了设备
        if (MMSYSERR_NOERROR == mmResult)
        {
            for (int i = 0; i < BUFFER_COUNT; i++)
            {
                m_pWaveHdrIn[i].lpData = m_cBufferIn[i];
                m_pWaveHdrIn[i].dwBufferLength = MAX_BUFF_SOUNDSIZE;
                m_pWaveHdrIn[i].dwBytesRecorded = 0;
                m_pWaveHdrIn[i].dwUser = i;
                m_pWaveHdrIn[i].dwFlags = 0;
                mmResult = waveInPrepareHeader(phwi, &m_pWaveHdrIn[i], sizeof(WAVEHDR));//4
                printf("\n准备缓冲区%d\n", i + 1);
            }

            //数据头准备完成
            if (MMSYSERR_NOERROR == mmResult)
            {
                for (int i = 0; i < BUFFER_COUNT; i++)
                {
                    mmResult = waveInAddBuffer(phwi, &m_pWaveHdrIn[i], sizeof(WAVEHDR));//5
                    printf("\n将缓冲区%d加入音频输入设备\n", i + 1);
                }

                //数据块准备完成
                if (MMSYSERR_NOERROR == mmResult)
                {
                    //开始录音
                    mmResult = waveInStart(phwi);//6
                    printf("\n请求开始录音\n");
                }
            }
        }
    }
}

void Stop()
{
    is_stop = true;
    Sleep(3000); //等待录音完成

    printf("Start Stop\n");
    waveInStop(phwi);

    printf("Start Reset\n");
    waveInReset(phwi);

    printf("Start Close\n");
    waveInClose(phwi);

    fclose(fptmp);
}

void Save()
{
    long len = 0;
    char *buf = NULL;
    FILE *fp;
    if (fopen_s(&fp, "temp.dat", "rb") == 0)
    {
        fseek(fp, 0, SEEK_END);;
        len = ftell(fp);
        fseek(fp, 0, SEEK_SET);
        buf = new char[len + 1];
        memset(buf, 0, sizeof(char)*(len + 1));
        fread(buf, len, 1, fp);
        fclose(fp);
    }
    if (buf == NULL)
    {
        printf("save error\n");
        return;
    }

    if (fopen_s(&fp, "output.wav", "wb") == 0)
    {
        RIFF_HEADER riff;
        WAVE_FORMAT wform;
        FMT_BLOCK fmt;
        //FACT_BLOCK fact;
        DATA_BLOCK data;
        memset(&riff, 0, sizeof(RIFF_HEADER));
        memset(&wform, 0, sizeof(WAVE_FORMAT));
        memset(&fmt, 0, sizeof(FMT_BLOCK));
        //memset(&fact, 0, sizeof(FACT_BLOCK));
        memset(&data, 0, sizeof(DATA_BLOCK));

        fmt.wavFormat.wFormatTag = WAVE_FORMAT_PCM;//1
        fmt.wavFormat.dwAvgBytesPerSec = pwfx.nAvgBytesPerSec;
        fmt.wavFormat.dwSamplesPerSec = pwfx.nSamplesPerSec;
        fmt.wavFormat.wBitsPerSample = pwfx.wBitsPerSample;
        fmt.wavFormat.wBlockAlign = pwfx.nBlockAlign;
        fmt.wavFormat.wChannels = pwfx.nChannels;

        memcpy(fmt.szFmtID, "fmt ", 4);
        fmt.dwFmtSize = 16;//一般情况下为16,如有附加信息为18
        memcpy(data.szDataID, "data", 4);
        data.dwDataSize = len;


        riff.dwRiffSize = (len + sizeof(FMT_BLOCK) + sizeof(DATA_BLOCK));
        memcpy(riff.szRiffFormat, "WAVE", 4);
        memcpy(riff.szRiffID, "RIFF", 4);

        fwrite(&riff, sizeof(RIFF_HEADER), 1, fp);//写RIFF_HEADER
        fwrite(&fmt, sizeof(FMT_BLOCK), 1, fp);//写FMT_BLOCK
        fwrite(&data, sizeof(DATA_BLOCK), 1, fp);//写数据头 DATA_BLOCK

        fwrite(buf, len, 1, fp);

        fclose(fp);
    }
}


DWORD WINAPI TimeThread(LPVOID wPame)
{
    Sleep(10000);
    return 0;
}


int main(void)
{
    errno_t errno;
    errno = fopen_s(&fptmp, "temp.dat", "wb");
    if (errno != 0)
    {
        printf("临时文件创建失败..\n");
        return 0;
    }

    Start();

    HANDLE hThread = CreateThread(NULL, NULL, TimeThread, NULL, NULL, NULL);
    WaitForSingleObject(hThread, INFINITE); //等待计时线程执行完成

    Stop();
    Save();

    system("pause");
    return 0;
}

错误: _malloc 已经在 Libcmtd.lib 中定义, 引发的思考

C++编译器选项:/MT,/MTd,/Md,/MDd
必须让工程所使用的库都使用相同的配置,否则就会有相应的警告或错误提示,甚至出现无法解析的函数,
有时,我们使用的库不是自己可以控制的,那么就只能把工程属性设置成你使用库的选项相同,这样可以编译通过了.

构造函数是producted属性的创建方法

如下声明的构造函数:

protected:
    CWeb();           // 动态创建所使用的受保护的构造函数
    virtual ~CWeb();

创建方法如下:

CRuntimeClass * pRuntimeClass = RUNTIME_CLASS(CWeb);
CObject* pObject = pRuntimeClass->CreateObject();
ASSERT(pObject->IsKindOf(RUNTIME_CLASS(CWeb)));
m_pWeb = ((CWeb*)pObject);  // m_pWeb为自己定义的CWeb类指针

之后使用m_pWeb就可以了。

gdb的感性认识

编译时要加调试函数(-g): g++ -g hello.cpp -o hello

l: 列出代码
break 2: 在第2行加断点
break func:设置断点,在func()函数入口处
info break:查看断点信息
r: 运行程序(run的简写)
n: 单条语句执行(next)
c: 继续向下执行(continue)
p i: 答应变量i的值(print)
bt: 查看函数堆栈
finish: 退出函数