默认情况下 Visual Studio 2008 的主题是白底黑字,这样看久了代码,很累。
还好,Visual Studio 提供了强大的自定制功能,我们可以随意设置字体的大小与颜色。当然,最方便的,还是使用其他人配好的颜色,比如说这个 Dark Visual Studio 主题就很不错。
要导入该设置,只需要在 Visual Studio 里的菜单 Tools ==> Import and Export Settings… 里进行导入。如果你对配置进行了若干自定义,则可以用该导出功能进行保存与备份。
原创文章,如转载请注明:转载自细节之锤 [ http://blog.WaterLin.org/ ]
Copyright © WaterLin.org. All rights reserved.
我在用 C++ 实现一个缓存文件的程序,即把很多远程传输过来的文件作为临时文件存到本地,当然,为了避免文件名的冲突,需要按照一定的规律来重新给这些文件取名称。如果是用 C++,可以有以下几种简单的方法取一个临时的文件名:
1) 用一个整数作为文件名,比如说从 00001 开始一直增加到 99999,再把整数转成字符串作为文件名。
这里要注意的是,如果是多线程程序,考虑到多线程的安全性,需要在取整数的时候,加一个锁,取完整数后,让整数加1,再解锁。
2) 如果是 Windows 平台,则可以考虑用系统的API,比如说 GetTempFileName 这个函数可以很好地完成任务,有兴趣的可以看看 MSDN 里有关这个函数的使用例子。
3) 如果是 Unix/Linux 主机上,则可以使用函数 tmpfile 来完成任务。
在 C++ 里,如果需要把 int 的数值直接转成字符串(例如对于整数123,我能得到字符串”123″),我们可以用很多种方法来实现:
1) 用 C++ 里的流控制,可以轻松地实现整数转成字符串的功能:
#include <sstream> #include <iostream>main() { int abc = 123; std::ostringstream out; out << abc; std::cout << out.str() << std::endl; }
下面是宽字符版本的演示程序,稍微有点不同,则可以用下面的方法:
int current = 111;
std::wostringstream int2string;
int2string << current;wstring temp_file = int2string.str().c_str();
wprintf(L”current filename is: %s\n”, temp_file.c_str());
wprintf(L”current filename is: %s\n”, int2string.str().c_str());
2) Boost 是 C++ 的准标准库,我们当然应该尝试学习使用 Boost 来完成这个转换,例子如下:
#include <boost/lexical_cast.hpp>
main()
{
int abc = 123;
std::string s = boost::lexical_cast<std::string>(abc);
printf("test for string: %s",s.c_str());
}
3) 用 C 标准库里的 sprintf 或是 swprintf 函数,注意,sprintf 需要头文件 <stdio.h>,而 swprintf 需要 <stdio.h> 或者 <wchar.h> 头文件,可以看看MSDN里的例子:
#include <stdio.h>
int main( void )
{
char buffer[200], s[] = "computer", c = 'l';
int i = 35, j;
float fp = 1.7320534f;
/* Format and print various data: */
j = sprintf( buffer, " String: %s\n", s );
j += sprintf( buffer + j, " Character: %c\n", c );
j += sprintf( buffer + j, " Integer: %d\n", i );
j += sprintf( buffer + j, " Real: %f\n", fp );
printf( "Output:\n%s\ncharacter count = %d\n", buffer, j );
}
4) 用 C 标准库的 itoa 函数也可以实现从字符串到数字的转换,itoa的例子代码:
/* itoa example */
#include <stdio.h>
#include <stdlib.h>
int main ()
{
int i;
char buffer [33];
printf ("Enter a number: ");
scanf ("%d",&i);
itoa (i,buffer,10);
printf ("decimal: %s\n",buffer);
itoa (i,buffer,16);
printf ("hexadecimal: %s\n",buffer);
itoa (i,buffer,2);
printf ("binary: %s\n",buffer);
return 0;
}
同样,用 C 标准库的 atoi 函数可以实现从字符串到数字的转换,atoi的例子代码:
/* atoi example */
#include <stdio.h>
#include <stdlib.h>
int main ()
{
int i;
char szInput [256];
printf ("Enter a number: ");
fgets ( szInput, 256, stdin );
i = atoi (szInput);
printf ("The value entered is %d. The double is %d.\n",i,i*2);
return 0;
}
一般来讲,就上面这么四种常用的方法就够用了。
Boost 被人们誉为 C++ 的准标准库,尝试着为 C++ 提供一个可跨平台使用的、大而全的库。作为一个软件工程师,一直没有机会对 Boost 进行了解与学习,现在正是迎头赶上的时候了!
今天在 Cygwin 下试着编译与安装了 Boost 库(boost_1_40_0版本),非常的简单与方便,大体步骤如下:
1) 下载源代码,解压到任何你想要的地方,我是放在 ~/source_code 目录下,解压后所有 Boost 的文件都在文件夹 boost_1_40_0 里面。
2) 编辑一段最简单的、只需要用到头文件的例子代码。在目录 ~/source_code/boost_1_40_0 下新建一个名叫 example.cpp 的文件,复制下面的代码:
#include <boost/lambda/lambda.hpp> #include <iostream> #include <iterator> #include <algorithm> int main() { using namespace boost::lambda; typedef std::istream_iterator<int> in; std::for_each( in(std::cin), in(), std::cout << (_1 * 3) << " " ); }
从命令行编译:
$ g++ -I /home/water/source_code/boost_1_40_0/ example.cpp -o example
上面 -I 后的参数,请根据 Boost 解压后所在的目录填写。编译成功后,运行 ./example,试着输入几个数字看看。
这里补充说明一下有关 C++ 头文件包含问题:如果在上面的命令中,你不想使用 -I 选项,可以把 Boost 的头文件放到 Cygwin 的 #include 目录里去,一般来讲,是 /usr/local/include 或是 /usr/include 目录。你可以把 Boost 源码包里的 Boost 文件夹,一股脑地拷贝到 /usr/local/include 目录下(当然,不支持手动这样做)。
如果你用了下面的命令:
$ g++ example.cpp -o example
而又没有按上面说的把 Boost 的头文件复制到 #include 目录,则会提示类似下面的错误:
$ g++ example.cpp -0 exmaple
g++: exmaple: No such file or directory
g++: unrecognized option `-0′
example.cpp:1:35: boost/lambda/lambda.hpp: No such file or directory
example.cpp: In function `int main()’:
example.cpp:8: error: `boost’ has not been declared
example.cpp:8: error: expected namespace-name before ‘;’ token
example.cpp:8: error: `<type error>’ is not a namespace
example.cpp:12: error: `_1′ undeclared (first use this function)
example.cpp:12: error: (Each undeclared identifier is reported only once for each function it appears in.)
3) 编译与安装 Boost 库的最简单方法
先生成命令行工具 bjam,它是专门负责编译、安装 Boost 库的工具。可以先查看一下相关帮助信息:
$ cd path/to/boost_1_40_0
$ ./bootstrap.sh –help
执行下面的命令就可以生成 bjam:
$ ./bootstrap.sh –prefix=path/to/installation/prefix
最后再利用 bjam 自动编译库文件:
$ ./bjam install
Boost 的编译与安装时间比较长,编译完成后,默认配置下头文件会安装到 /usr/local/include/boost 目录下,而生成的库文件会放到 /usr/local/lib 目录下。更详细的安装可以看看官方文档。
4) 以后写完 Boost 代码,就可以直接编译代码了。现在可以试着不指定 Boost 头文件的路径,再编译一把上面的 example.cpp 的例子:
$ g++ example.cpp -o example
现在 g++ 就能自动找到相关的头文件。
如果是 Linux 的话,编译与安装 Boost 的步骤应该大体上差不多;推荐使用各 Linux 发行版编译好的二进制版本,直接下载安装更省事。
在VC++ 2005里,有一个Start Page标签页面,方便你在不同的工程里进行切换而不需要重启VC++ 2005。
如果你不小心关掉了Start Page页面,可以用这个方法再打开这个页面:
View –> Other Windows –> Start Page
Windows的VSS是指给磁盘打快照的服务,可以方便实施热备份等,MSDN里的相关文档有着详细地介绍。
下载VSS SDK包,这个安装包的安装路径默认为:
C:\Program Files\Microsoft\VSSSDK72\
当然,如果你的VSS版本号不太一样的话,路径会有所区别。
SDK自带了几个例子,对我们熟悉VSS非常有帮助,放在SDK安装路径下的TestApps目录,如果为默认安装,则是:
C:\Program Files\Microsoft\VSSSDK72\TestApps
不过我在Visual Studio 2005里编译vshadow这个例子工程时,编译器提示类似如下错误:
error C4430: missing type specifier – int assumed. Note: C++ does not support default-int e:\watercode\vsssamplecode\testapps\vshadow\src\shadow.cpp 30
这是因为VS 2005的C++编译器严格地检查函数的返回值,无返回值函数的返回值不再默认为整数,因此,可以修改main函数的定义,使之返回一个整数值来解决这个编译问题:
把shadow.cpp文件里的主函数
extern “C” __cdecl wmain(int argc, WCHAR ** argv)
根据需要改为类似于
int wmain(int argc, WCHAR ** argv)
即可。
MySQL提供了C++语言的操作接口,用这个接口可以针对自己的数据库写一个C++的客户端出来,安装的方法请参看官方文档。
这个文章已经把在Visual Studio 2008里如何编写MySQL Connector C++的应用程序进行了详细的说明,此方法是针对MySQL Connector C++的安装包来介绍的。而另一篇文章则介绍了如何从MySQL Connector C++的源码包编译。
这里介绍一下Visual Studio 2005下面,用安装二进制包的方法来使用MySQL Connector C++的方法:
1) 先安装MySQL
记得要把Developer Components – C Include Files / Lib Files选上。当然,你不安装MySQL而只装这个单独的包也行,不过我还是建议在本地装一个MySQL,否则怎么测试呢?远程测试太麻烦了~~
2) 下载与Visual Studio 2005相对应的MySQL Connector C++版本
3) 在Visual Studio 2005里创建一个Win32 Console工程
File->New Project->Visual C++->Win32->Win32 Console Application
注意:”Application Settings”里的”Additional options: Precompiled header”默认是会被选上的,而我们这里,基本上可以不用这个。
4) 正确地配置工程属性
不管是Debug还是Release,都是用下面的方法设置就可以了,主要是把相关的头文件include到工程,再指定相关的动态链接库所在路径。
(1) 打开”project”->”properties”对话框,选择”configuration properties”
把MySQL Connector/C++的安装目录添加到Additional Include Directory里:
Project->Properties
Configuration Properties -> open tree view
C/C++ -> General -> Additional Include Directory
(2) 让编译器能找到MySQL Connector/C++的libraries,只要把MySQL Connector/C++安装目录里的lib/opt目录添加到搜索路径即可:
Linker -> General -> Additional Library Directories
(3) 编译器在编译的时候,让linker去链接MySQL Connector/C++的mysqlcppconn.lib库
把mysqlcppconn.lib添加到这里:
Linker -> Input -> Additional Dependencies
5) 可以试着编译下面的这段最基本的代码:
/*
examples/standalone_example_docs1.cpp
*/
/* Standard C++ includes */
#include
#include
/*
Include directly the different
headers from cppconn/ and mysql_driver.h + mysql_util.h
(and mysql_connection.h). This will reduce your build time!
*/
#include "mysql_connection.h"
#include "cppconn/driver.h"
#include "cppconn/exception.h"
#include "cppconn/resultset.h"
#include "cppconn/statement.h"
using namespace std;
int main(void)
{
cout << endl;
cout << "Running 'SELECT 'Hello World!' AS _message'..." << endl;
try {
sql::Driver *driver;
sql::Connection *con;
sql::Statement *stmt;
sql::ResultSet *res;
/* Create a connection */
driver = get_driver_instance();
con = driver->connect("tcp://127.0.0.1:3306", "root", "password");
/* Connect to the MySQL test database */
con->setSchema("test");
stmt = con->createStatement();
res = stmt->executeQuery("SELECT 'Hello World!' AS _message");
while (res->next()) {
cout << "\t... MySQL replies: ";
/* Access column data by alias or column name */
cout << res->getString("_message") << endl;
cout << "\t... MySQL says it again: ";
/* Access column fata by numeric offset, 1 is the first column */
cout << res->getString(1) << endl;
}
delete res;
delete stmt;
delete con;
} catch (sql::SQLException &e) {
cout << "# ERR: SQLException in " << __FILE__;
cout << "(" << __FUNCTION__ << ") on line " << __LINE__ << endl;
cout << "# ERR: " << e.what();
cout << " (MySQL error code: " << e.getErrorCode();
cout << ", SQLState: " << e.getSQLState() << " )" << endl;
}
cout << endl;
return EXIT_SUCCESS;
}
如果一切顺序,应该就能连上本地的MySQL进行操作了。
最近在VC里写一个程序,要求把日志显示到界面上来。要做这种事情的情况很少,一般来说,我们都是把日志写到文本文件里。
如果只是很简单的程序,可以选用Edit控件,在界面上实现简单的日志显示功能。以下是最基本的步骤:
1) 创建Edit控件,并设置适当的属性
先用资源编辑器添加一个Edit控件到界面上,关联资源ID为IDC_LOG。注意选上风格WantReturn和MultiLine(多行);因为输出的是日志,Edit的可视空间可能会不够用,因此风格里最好选上Vertical Scroll和Auto Scroll这两个选项!
2) 添加与日志有关的数据成员
在对话框类的头文件里,添加数据成员:
CString _log; //存储日志的内容
CString _newline; //存储换行符
3) 初始化工作
在对话框的构造函数里,添加如下的代码:
char re[3] = {VK_RETURN, 0x0a};
_newline = re;
_log = “系统启动,已设置好与日志有关的一切”;
当然,也可以用\r\n赋值给_newline实现换行代码。
4) 在每次要输出日志的地方,用以下语句就可以在Edit控件里实现日志的刷新:
_log += _newline;
_log += “欲追加的日志”;
SetDlgItemText(IDC_LOG, _log);
因为是小程序,没有考虑到日志变量CString _log的容量问题。
基本的原理就是这样,可以根据情况进行适当的改进。
1) 用MFC里的CFileFind类
下面是用CFileFind类读特定目录下的所有bmp格式文件的例子代码:
CString path;//需要枚举文件的路径
CFileFind finder;
BOOL bWorking = finder.FindFile(path + “\\” + “*.bmp”);
while (bWorking)
{
bWorking = finder.FindNextFile();
cout << (LPCTSTR) finder.GetFileName() << endl;
}
2) 用FindFirstFile(),FindNextFile()和FindClose()这几个API函数。
今天在用MFC写程序的时候,碰到一个奇怪的问题:在我用CFileDialog选择文件后,程序的其它地方,就提示我说找不到某个文件;这个文件的路径,我是用hard code的方法硬写在程序里方便测试的。
如果这个路径我用的是绝对路径,并不会出问题;如果是用相对路径,则会提示找不到文件。
查了一会MSDN,原来用CFileDialog打开文件后,程序默认的执行路径就得到了改变。这样的话,我在用CFileDialog打开文件后,上述的相对路径自然就要换一换了。于是程序就出了一些莫名其妙的错误~~
切记,使用CFileDialog会改变当前目录,比较稳妥的办法还是绝对路径来访问文件比较好。在程序刚一跑起来的时候,先用GetCurrentDirectory()或是GetModuleFileName()获得当前可执行文件所在的路径,并保存起来。以后即使是用CFileDialog改变了当前的路径,也能很容易地找回来。