Posted on 06-11-2009
Filed Under (技术) by waterlin

默认情况下 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.

(0) Comments    Read More   
Posted on 04-09-2009
Filed Under (技术) by waterlin

我在用 C++ 实现一个缓存文件的程序,即把很多远程传输过来的文件作为临时文件存到本地,当然,为了避免文件名的冲突,需要按照一定的规律来重新给这些文件取名称。如果是用 C++,可以有以下几种简单的方法取一个临时的文件名:

1) 用一个整数作为文件名,比如说从 00001 开始一直增加到 99999,再把整数转成字符串作为文件名。

这里要注意的是,如果是多线程程序,考虑到多线程的安全性,需要在取整数的时候,加一个锁,取完整数后,让整数加1,再解锁。

2) 如果是 Windows 平台,则可以考虑用系统的API,比如说 GetTempFileName 这个函数可以很好地完成任务,有兴趣的可以看看 MSDN 里有关这个函数的使用例子

3) 如果是 Unix/Linux 主机上,则可以使用函数 tmpfile 来完成任务。

(0) Comments    Read More   
Posted on 03-09-2009
Filed Under (技术) by waterlin

在 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;
}

一般来讲,就上面这么四种常用的方法就够用了。

(0) Comments    Read More   
Posted on 03-09-2009
Filed Under (技术) by waterlin

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 发行版编译好的二进制版本,直接下载安装更省事。

(0) Comments    Read More   
Posted on 13-08-2009
Filed Under (技术) by waterlin

在VC++ 2005里,有一个Start Page标签页面,方便你在不同的工程里进行切换而不需要重启VC++ 2005。

如果你不小心关掉了Start Page页面,可以用这个方法再打开这个页面:

View –> Other Windows –> Start Page

(0) Comments    Read More   
Posted on 11-08-2009
Filed Under (技术) by waterlin

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)

即可。

(0) Comments    Read More   
Posted on 08-07-2009
Filed Under (技术) by waterlin

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进行操作了。

(0) Comments    Read More   
Posted on 03-07-2009
Filed Under (技术) by waterlin

最近在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的容量问题。

基本的原理就是这样,可以根据情况进行适当的改进。

(0) Comments    Read More   
Posted on 02-07-2009
Filed Under (技术) by waterlin

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函数。

(0) Comments    Read More   
Posted on 02-07-2009
Filed Under (技术) by waterlin

今天在用MFC写程序的时候,碰到一个奇怪的问题:在我用CFileDialog选择文件后,程序的其它地方,就提示我说找不到某个文件;这个文件的路径,我是用hard code的方法硬写在程序里方便测试的。

如果这个路径我用的是绝对路径,并不会出问题;如果是用相对路径,则会提示找不到文件。

查了一会MSDN,原来用CFileDialog打开文件后,程序默认的执行路径就得到了改变。这样的话,我在用CFileDialog打开文件后,上述的相对路径自然就要换一换了。于是程序就出了一些莫名其妙的错误~~

切记,使用CFileDialog会改变当前目录,比较稳妥的办法还是绝对路径来访问文件比较好。在程序刚一跑起来的时候,先用GetCurrentDirectory()或是GetModuleFileName()获得当前可执行文件所在的路径,并保存起来。以后即使是用CFileDialog改变了当前的路径,也能很容易地找回来。

(0) Comments    Read More