您的位置:首页 > 编程语言 > C语言/C++

入门级Windows平台VS2010开发C/C++语言

2019-04-22 15:49 176 查看
版权声明:本文为博主原创文章,遵循 CC 4.0 by-sa 版权协议,转载请附上原文出处链接和本声明。 本文链接:https://blog.csdn.net/weixin_40874302/article/details/89452056

工作这段时间磕磕绊绊有所成长,所以想写一篇入门总结防止自己忘记也希望帮助他人。本文只从实用性角度进行阐述,只是作为入门级的参考不写入深层次的概念和理论,如有错误请大佬们指正。

//字符串类数组CString str[] = {TEXT(“姓名”), TEXT(“性别”), TEXT(“年龄”)};
//字符串格式化(初始化)
CString name;
name.Format(TEXT(“张三”));
Name.ReleaseBuffer();//清除C字符串
TEXT()//可以自动转换编码格式 好处不用改工程的字符集属性

//char * 与CString 之间的转换

//char * -> CString
char * p3 = “ccc”;
CString str = CString(p3);

//CString -> char *
CStringA tmp;
tmp = str;
char * pp = tmp.GetBuffer();

//利用定时器实现一个100毫秒的循环
HANDLE hTimer = ::CreateWaitableTimer( NULL, false, NULL ); //创建定时器
LARGE_INTEGER dueTime;
dueTime.QuadPart = 0;//设置定时器启动的相对时间(多久后启动定时器)
::SetWaitableTimer(hTimer, &dueTime, 100, NULL, NULL, false); //定时时间为100毫秒

while(true)
{
if (WaitForSingleObject(hTimer, INFINITE) != WAIT_OBJECT_0)
{
OutputDebugString(_T(“超过100毫秒了 定时器出错了/r/n”));
CloseHandle(hTimer);//销毁定时器
return 3;
}
else
{
SetWaitableTimer(hTimer, &dueTime, 0, NULL, NULL, 0);//参3为0 取消定时
OutputDebugString(_T(“时间到了/r/n”));
}
}

信号
HANDLE m_hSendEvent;
m_hSendEvent = CreateEvent(NULL,0,0,NULL);//创建事件
SetEvent(m_hSendEvent);//触发发送事件
int iRet = WaitForSingleObject(m_hSendEvent,100);//阻塞等待事件到达 参数2等待时间毫秒
if (iRet != WAIT_OBJECT_0) //成功返回WAIT_OBJECT_0
{
continue;
}

函数功能描述:创建或打开一个命名的或无名的事件对象
函数原型:HANDLE CreateEvent(
LPSECURITY_ATTRIBUTES lpEventAttributes, // 安全属性
BOOL bManualReset, // 复位方式
BOOL bInitialState, // 初始状态
LPCTSTR lpName // 对象名称);
参数:
lpEventAttributes: [输入]一个指向SECURITY_ATTRIBUTES结构的指针,确定 返回的句柄是否可被子进程继承。如果lpEventAttributes是NULL,此句柄不能被继 承。Windows NT/2000:lpEventAttributes的结构中的成员为新的事件指定了一个安 全符。如果lpEventAttributes是NULL,事件将获得一个默认的安全符。

bManualReset: [输入]指定将事件对象创建成手动复原还是自动复原。如果是TRUE,那么必须用 ResetEvent函数来手工将事件的状态复原到无信号状态。如果设置为FALSE,当事件被一个等待线程 释放以后,系统将会自动将事件状态复原为无信号状态。

bInitialState: [输入]指定事件对象的初始状态。如果为TRUE,初始状态为有信号状态;否则为无信号状态。

lpName:[输入]指定事件的对象的名称,是一个以0结束的字符串指针。名称的字符格式限定在MAX_PATH之内。名字是对大小写敏感的。 如果lpName指定的名字,与一个存在的命名的事件对象的名称相同,函数将请求EVENT_ALL_ACCESS来访问存在的对象。这时候,由于 bManualReset和bInitialState参数已经在创建事件的进程中设置,这两个参数将被忽略。如果lpEventAttributes是 参数不是NULL,它将确定此句柄是否可以被继承,但是其安全描述符成员将被忽略。

如果lpName为NULL,将创建一个无名的事件对象。
如果lpName的和一个存在的信号、互斥、等待计时器、作业或者是文件映射对象名称相同,函数将会失败,在GetLastError函数中将返回ERROR_INVALID_HANDLE。造成这种现象的原因是这些对象共享同一个命名空间。

终端服务(Terminal Services):名称中可以加入"Global"或是"Local"的前缀,这样可以明确的将对象创建在全局的或事务的命名空间。名称的其它部分 除了反斜杠(),可以使用任意字符。详细内容可参考Kernel Object Name Spaces。

Windows 2000:在Windows 2000系统中,没有终端服务运行,"Global"和"Local"前缀将被忽略。名称的其它部分除了反斜杠(),可以使用任意字符。

Windows NT 4.0以及早期版本, Windows 95/98:名称中除了反斜杠(),可以使用任意字符。返回值:

如果函数调用成功,函数返回事件对象的句柄。如果对于命名的对象,在函数调用前已经被创建,函数将返回存在的事件对象的句柄,而且在GetLastError函数中返回ERROR_ALREADY_EXISTS。

如果函数失败,函数返回值为NULL,如果需要获得详细的错误信息,需要调用GetLastError。

注:以上长篇文字说明部分摘抄自某位大神的文章,以下为原文链接想仔细研究的小伙伴看看吧https://www.cnblogs.com/MrYuan/p/5238749.html

CRITICAL_SECTION m_CS; //线程同步
InitializeCriticalSection(&m_CS); //初始化锁
EnterCriticalSection(&m_CS); //上锁
LeaveCriticalSection(&m_CS); //解锁
DeleteCriticalSection(&m_CS); //删除锁

函数模板:
//声明部分
template void Swap(T&, T&);//声明函数模板和对应的函数
//tem plate声明函数模板关键字
//type name声明虚拟数据类型关键字 老版本中用class代替
//& 表示引用前面的虚拟类型作为参数

//实现部分
template//模板头
void Swap(T &a, T &b)//函数实现部分
{
T temp = a;
a = b;
b = temp;
}

内联函数:在函数前添加 inline 关键字, 内联函数起替换做用。
好处:提高程序运行效率
应用场景:代码小于100行,逻辑运行简单的函数,才可以使用。

提高程序运行效率的几个注意事项:1. 尽量满足上述条件下使用内联函数和宏函数2. 少使用堆栈开辟空间3. 根据实际情况选择最合适的容器

Vector容器 队列

基本函数和功能:
(1) frond()返回第一个元素的值
(2) Bakc()返回最后一个元素的值
(3) Insert()在一个给定的位置插入一个新的元素
(4) Push_back()在末尾添加一个元素
(5) Pop_back()删除末尾的一个元素

使用:
(1) #include //容器
(2) #include//算法
(3) #include//迭代器
(4) using namespace std;

int SIZE = 6;
Int array[SIZE] = {1, 2, 3, 4, 5, 6};
//声明一个int类型集合的容器,并用数组array对其初始化
vector<int> v(array, array + SIZE);
v[1] = 7;//将第二个元素改写成7
v.at(2) = 10;//作用同上,但这种方法更安全会检查是否越界
v.insert(v.bengin() + 1, 22);//在第二个元素位置插入22
v.push_back(19);

//声明迭代器用于遍历
vector<int>::iterator iter;//使用类似于指针
iter = v.begin();//使迭代器指向容器的第一个元素
while(iter != v.end())
{
cout<< *iter <<endl
Iter++;
}

//算法
//查找元素值为22 的位置,并返回其迭代器
iter = find(v.begin(), v.end(), 22);//如果找到就指向对应元素位置,如果没找到指向最后一个元素的下一个位置
if(iter != v.end())
{
cout<<(iter - v.begin())<<endl;//输出元素所在位置
}
else
{
cout&l
3ff7
t;<”没找到”<<endl;
}

cout << “容器所能分配的最大空间” << v.max_size() << endl;
cout <<”当前容器最大容量” << v.capacity() << endl;

//异常处理 防止程序崩溃
try{  //不出异常走try
V.at(1) = 777;
}
catch(out_of_range & e){  //出现异常走catch
cout << “输出异常信息” << e.what();
}
v.erase(v.begin());//清除第一个元素
v.erase(v.begin(), v.end()); //清除所有元素 也可以指定清除范围
v.clear(); //清空容器所有元素 不能指定范围
//判断容器是否被清空 成功v.empty()返回值为真1,失败返回值为假0
cout << “容器是否清空” << (v.empty() ? “已清空” : “未清空”) << endl;

总结:
优点:1.遍历访问速度快2.在队列尾部差数删除快3.大小可变
缺点:容器内存储的数据量过多后,在队列之中插入删除效率低下。

List 容器 双向链表
#include
#include //头文件
#include //迭代器
typedef namespace std;

typedef list IntList //重新定义类型
//IntList lst; //相当于list lst;

list lst;
lst.push_front(100);//从链表起始位置插入一个节点(头插)
lst.push_back(200);//在链表结束为止插入一个节点(尾插)

lst.sort();//升序排列

listlst::iterator itor = lst.begin();//定义迭代器 并将链表起始位置保存

while(itor != lst.end()){ //遍历链表
cout<< *itor++ <<endl;
}

//插入和删除
for(list::iterator iter = lst.begin(); iter != lst.end; iter ++)
{
int &value = *iter;// 引用
if(value == 3)//删除值为3的节点
{
lst.insert(iter, 2);//将2插入到 iter 的前面
lst.erase(iter);//删除
break;
}
}

补充说明:iterator insert(iterator pos,const T &vaule); //在pos前插入vaule,返回新元素的迭代器,不影响现有迭代器。//参数1迭代器指向的节点 或者链表节点 参数2为值
例如:在表的首元素插入数据节点0,新建立的迭代器指向新插入的0节点的位置,原有迭代器还是指向原来的1节点

void erase(iterator pos); //删除pos指向的元素,删除后pos指向未知

优点 插入删除消耗资源少

缺点 不支持随机访问 访问必须要用迭代器进行遍历 不支持[]和+运算符(++可用)

内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: