??xml version="1.0" encoding="utf-8" standalone="yes"?>亚洲天堂在线播放,666精品国产精品亚洲,亚洲AV人无码综合在线观看http://www.tkk7.com/jinfeng_wang/category/485.htmlG-G-S,D-D-U!zh-cnSun, 19 Aug 2007 05:06:22 GMTSun, 19 Aug 2007 05:06:22 GMT60Using Event Objects (zz)http://www.tkk7.com/jinfeng_wang/archive/2007/08/17/137579.htmljinfeng_wangjinfeng_wangFri, 17 Aug 2007 08:20:00 GMThttp://www.tkk7.com/jinfeng_wang/archive/2007/08/17/137579.htmlhttp://www.tkk7.com/jinfeng_wang/comments/137579.htmlhttp://www.tkk7.com/jinfeng_wang/archive/2007/08/17/137579.html#Feedback0http://www.tkk7.com/jinfeng_wang/comments/commentRss/137579.htmlhttp://www.tkk7.com/jinfeng_wang/services/trackbacks/137579.htmlApplications use event objects in a number of situations to notify a waiting thread of the occurrence of an event. For example, overlapped I/O operations on files, named pipes, and communications devices use an event object to signal their completion. For more information about the use of event objects in overlapped I/O operations, see Synchronization and Overlapped Input and Output.

In the following example, an application uses event objects to prevent several threads from reading from a shared memory buffer while a master thread is writing to that buffer. First, the master thread uses the CreateEvent function to create a manual-reset event object. The master thread sets the event object to nonsignaled when it is writing to the buffer and then resets the object to signaled when it has finished writing. Then it creates several reader threads and an auto-reset event object for each thread. Each reader thread sets its event object to signaled when it is not reading from the buffer.

#define NUMTHREADS 4
HANDLE hGlobalWriteEvent;
void CreateEventsAndThreads(void)
{
HANDLE hReadEvents[NUMTHREADS], hThread;
DWORD i, IDThread;
// Create a manual-reset event object. The master thread sets
// this to nonsignaled when it writes to the shared buffer.
hGlobalWriteEvent = CreateEvent(
NULL,         // no security attributes
TRUE,         // manual-reset event
TRUE,         // initial state is signaled
"WriteEvent"  // object name
);
if (hGlobalWriteEvent == NULL) {
// error exit
}
// Create multiple threads and an auto-reset event object
// for each thread. Each thread sets its event object to
// signaled when it is not reading from the shared buffer.
for(i = 1; i <= NUMTHREADS; i++)
{
// Create the auto-reset event.
hReadEvents[i] = CreateEvent(
NULL,     // no security attributes
FALSE,    // auto-reset event
TRUE,     // initial state is signaled
NULL);    // object not named
if (hReadEvents[i] == NULL)
{
// Error exit.
}
hThread = CreateThread(NULL, 0,
(LPTHREAD_START_ROUTINE) ThreadFunction,
&hReadEvents[i],  // pass event handle
0, &IDThread);
if (hThread == NULL)
{
// Error exit.
}
}
}

Before the master thread writes to the shared buffer, it uses the ResetEvent function to set the state of hGlobalWriteEvent (an application-defined global variable) to nonsignaled. This blocks the reader threads from starting a read operation. The master then uses the WaitForMultipleObjects function to wait for all reader threads to finish any current read operations. When WaitForMultipleObjects returns, the master thread can safely write to the buffer. After it has finished, it sets hGlobalWriteEvent and all the reader-thread events to signaled, enabling the reader threads to resume their read operations.

VOID WriteToBuffer(VOID)
{
DWORD dwWaitResult, i;
// Reset hGlobalWriteEvent to nonsignaled, to block readers.
if (! ResetEvent(hGlobalWriteEvent) )
{
// Error exit.
}
// Wait for all reading threads to finish reading.
dwWaitResult = WaitForMultipleObjects(
NUMTHREADS,   // number of handles in array
hReadEvents,  // array of read-event handles
TRUE,         // wait until all are signaled
INFINITE);    // indefinite wait
switch (dwWaitResult)
{
// All read-event objects were signaled.
case WAIT_OBJECT_0:
// Write to the shared buffer.
break;
// An error occurred.
default:
printf("Wait error: %d\n", GetLastError());
ExitProcess(0);
}
// Set hGlobalWriteEvent to signaled.
if (! SetEvent(hGlobalWriteEvent) )
{
// Error exit.
}
// Set all read events to signaled.
for(i = 1; i <= NUMTHREADS; i++)
if (! SetEvent(hReadEvents[i]) ) {
// Error exit.
}
}

Before starting a read operation, each reader thread uses WaitForMultipleObjects to wait for the application-defined global variable hGlobalWriteEvent and its own read event to be signaled. When WaitForMultipleObjects returns, the reader thread's auto-reset event has been reset to nonsignaled. This blocks the master thread from writing to the buffer until the reader thread uses the SetEvent function to set the event's state back to signaled.

VOID ThreadFunction(LPVOID lpParam)
{
DWORD dwWaitResult;
HANDLE hEvents[2];
hEvents[0] = *(HANDLE*)lpParam;  // thread's read event
hEvents[1] = hGlobalWriteEvent;
dwWaitResult = WaitForMultipleObjects(
2,            // number of handles in array
hEvents,      // array of event handles
TRUE,         // wait till all are signaled
INFINITE);    // indefinite wait
switch (dwWaitResult)
{
// Both event objects were signaled.
case WAIT_OBJECT_0:
// Read from the shared buffer.
break;
// An error occurred.
default:
printf("Wait error: %d\n", GetLastError());
ExitThread(0);
}
// Set the read event to signaled.
if (! SetEvent(hEvents[0]) )
{
// Error exit.
}
}


jinfeng_wang 2007-08-17 16:20 发表评论
]]>
Using Mutex Objects (zz)http://www.tkk7.com/jinfeng_wang/archive/2007/08/17/137574.htmljinfeng_wangjinfeng_wangFri, 17 Aug 2007 08:13:00 GMThttp://www.tkk7.com/jinfeng_wang/archive/2007/08/17/137574.htmlhttp://www.tkk7.com/jinfeng_wang/comments/137574.htmlhttp://www.tkk7.com/jinfeng_wang/archive/2007/08/17/137574.html#Feedback0http://www.tkk7.com/jinfeng_wang/comments/commentRss/137574.htmlhttp://www.tkk7.com/jinfeng_wang/services/trackbacks/137574.htmlUsing Mutex Objects

You can use a mutex object to protect a shared resource from simultaneous access by multiple threads or processes. Each thread must wait for ownership of the mutex before it can execute the code that accesses the shared resource. For example, if several threads share access to a database, the threads can use a mutex object to permit only one thread at a time to write to the database.

In the following example, a process uses the CreateMutex function to create a named mutex object or open a handle to an existing mutex object.

HANDLE hMutex;
// Create a mutex with no initial owner.
hMutex = CreateMutex(
NULL,                       // no security attributes
FALSE,                      // initially not owned
"MutexToProtectDatabase");  // name of mutex
if (hMutex == NULL)
{
// Check for error.
}

When a thread of this process writes to the database, as in the next example, it first requests ownership of the mutex. If it gets ownership, the thread writes to the database and then releases its ownership.

The example uses structured exception-handling syntax to ensure that the thread properly releases the mutex object. The __finally block of code is executed no matter how the __try block terminates (unless the __try block includes a call to the TerminateThread function). This prevents the mutex object from being abandoned inadvertently.

BOOL FunctionToWriteToDatabase(HANDLE hMutex)
{
DWORD dwWaitResult;
// Request ownership of mutex.
dwWaitResult = WaitForSingleObject(
hMutex,   // handle to mutex
5000L);   // five-second time-out interval
switch (dwWaitResult)
{
// The thread got mutex ownership.
case WAIT_OBJECT_0:
__try {
// Write to the database.
}
__finally {
// Release ownership of the mutex object.
if (! ReleaseMutex(hMutex)) {
// Deal with error.
}
break;
}
// Cannot get mutex ownership due to time-out.
case WAIT_TIMEOUT:
return FALSE;
// Got ownership of the abandoned mutex object.
case WAIT_ABANDONED:
return FALSE;
}
return TRUE;
}


jinfeng_wang 2007-08-17 16:13 发表评论
]]>
VC 6 调试调试子进E?zzhttp://www.tkk7.com/jinfeng_wang/archive/2007/08/09/135515.htmljinfeng_wangjinfeng_wangThu, 09 Aug 2007 07:43:00 GMThttp://www.tkk7.com/jinfeng_wang/archive/2007/08/09/135515.htmlhttp://www.tkk7.com/jinfeng_wang/comments/135515.htmlhttp://www.tkk7.com/jinfeng_wang/archive/2007/08/09/135515.html#Feedback0http://www.tkk7.com/jinfeng_wang/comments/commentRss/135515.htmlhttp://www.tkk7.com/jinfeng_wang/services/trackbacks/135515.html  然后重新~译你的子程序的调试版本。现在调试主E序Q? 
  子程序的调试版本在运行的q程中,?nobr oncontextmenu="return false;" onmousemove=kwM(4); id=key4 onmouseover="kwE(event,4, this);" style="COLOR: #6600ff; BORDER-BOTTOM: 0px dotted; BACKGROUND-COLOR: transparent; TEXT-DECORATION: underline" onclick="return kwC();" onmouseout="kwL(event, this);" target="_blank">执行到DebugBreak()Ӟ会抛出一个异常,  
  q个异常会由操作pȝ捕捉刎ͼ然后弹出一个对话框Q说E序遇到了问题,问你要不要发送错?nobr oncontextmenu="return false;" onmousemove=kwM(6); id=key5 onmouseover="kwE(event,6, this);" style="COLOR: #6600ff; BORDER-BOTTOM: #6600ff 1px dotted; BACKGROUND-COLOR: transparent; TEXT-DECORATION: underline" onclick="return kwC();" onmouseout="kwL(event, this);" target="_blank">报告Q点击该对话框的调试按钮Q系l又会弹Z个对话框Q选择相应的调试器q行调试Q然后子q程׃中断在代码DebugBreak()处,接下来就可以正常调试了?nbsp; 


jinfeng_wang 2007-08-09 15:43 发表评论
]]>
详细解说STL string (zz)http://www.tkk7.com/jinfeng_wang/archive/2007/06/05/122189.htmljinfeng_wangjinfeng_wangTue, 05 Jun 2007 09:33:00 GMThttp://www.tkk7.com/jinfeng_wang/archive/2007/06/05/122189.htmlhttp://www.tkk7.com/jinfeng_wang/comments/122189.htmlhttp://www.tkk7.com/jinfeng_wang/archive/2007/06/05/122189.html#Feedback0http://www.tkk7.com/jinfeng_wang/comments/commentRss/122189.htmlhttp://www.tkk7.com/jinfeng_wang/services/trackbacks/122189.htmlhttp://www.stlchina.org/twiki/bin/view.pl/Main/STLDetailString 

详细解说STL string

  • 详细解说STL string
    • 1 string 使用
    • 3 string ?Charactor Traits
    • 4 string
    • 5 结
    • 6 附录
    • 0 前言: string 的角? C++ 语言是个十分优秀的语aQ但优秀q不表示完美。还是有许多Z愿意使用C或者C++Qؓ什么?原因众多Q其中之一是C/C++的文本处理功能太ȝQ用h很不方便。以前没有接触过其他语言Ӟ每当别hq么_我L不屑一,认ؓ他们Ҏ没有领会C++的精华,或者不太懂C++Q现在我接触perl, php, 和Shell脚本以后Q开始理解了以前Z么有C++文本处理不方便了?

      举例来说Q如果文本格式是Q用户名 电话LQ文件名name.txt BeautifierPlugin Error: Unable to handle "bash" syntax.

      Tom 23245332
      Jenny 22231231
      Heny 22183942
      Tom 23245332
      ...
      
      现在我们需要对用户名排序,且只输出不同的姓名?

      那么?a class=twikiLink >shell ~程中,可以q样用: BeautifierPlugin Error: Unable to handle "bash" syntax.

      awk '{print $1}' name.txt | sort | uniq
      
      单吧Q?

      如果使用C/C++ 麻烦了Q他需要做以下工作Q?

      1. 先打开文gQ检文件是否打开Q如果失败,则退出?
      2. 声明一个够大得二l字W数l或者一个字W指针数l?
      3. d一行到字符I间
      4. 然后分析一行的l构Q找到空|存入字符数组中?
      5. 关闭文g
      6. 写一个排序函敎ͼ或者用写一个比较函敎ͼ使用qsort排序
      7. 遍历数组Q比较是否有相同的,如果有,则要删除Qcopy...
      8. 输出信息
      你可以用C++或者C语言d现这个流E。如果一个h的主要工作就是处理这U类似的文本(例如做apache的日志统计和分析),你说他会喜欢C/C++么?

      当然Q有了STLQ这些处理会得到很大的简化。我们可以?fstream来代曉K烦的fopen fread fclose, 用vector 来代替数l。最重要的是?string来代替char * 数组Q?a class=twikiLink >sort排序法来排序,?a target=_top>unique 函数来去重。听h好像很不?smile 。看看下面代?例程1Q:

      #include <string>
      #include <iostream>
      #include <algorithm>
      #include <vector>
      #include <fstream>
      using namespace std;
      int main(){
      ifstream in("name.txt");
      string strtmp;
      vector<string> vect;
      while(getline(in, strtmp, '\n'))
      vect.push_back(strtmp.substr(0, strtmp.find(' ')));
      sort(vect.begin(), vect.end());
      vector<string>::iterator it=unique(vect.begin(), vect.end());
      copy(vect.begin(), it, ostream_iterator<string>(cout, "\n"));
      return 0;
      }
      
      
      也还不错吧,臛_会比惌得要单得多!Q代码里面没有对错误q行处理Q只是ؓ了说明问题,不要效仿).

      当然Q在q个文本格式中,不用vector而用map会更有扩充性,例如Q还可通过人名扄话号码等{,但是使用了map׃那么好用sort了。你可以用map试一试?

      q里string的作用不只是可以存储字符Ԍq可以提供字W串的比较,查找{。在sort和unique函数中就默认使用了less 和equal_to函数, 上面的一D代码,其实使用了string的以下功能:

      1. 存储功能Q在getline() 函数?
      2. 查找功能Q在find() 函数?
      3. 子串功能Q在substr() 函数?
      4. string operator < , 默认在sort() 函数中调?
      5. string operator == , 默认在unique() 函数中调?

      MQ有了string 后,C++的字W文本处理功能ȝ得到了一定补充,加上配合STL其他容器使用Q其在文本处理上的功能已l与perl, shell, php的距ȝ很多了?因此掌握string 会让你的工作事半功倍?

      1 string 使用

      其实Qstringq不是一个单独的容器Q只是basic_string 模板cȝ一个typedef 而已Q相对应的还有wstring, 你在string 头文件中你会发现下面的代?
      extern "C++" {
      typedef basic_string <char> string;
      typedef basic_string <wchar_t> wstring;
      } // extern "C++"
      
      
      ׃只是解释string的用法,如果没有Ҏ的说明,本文q不区分string ?basic_string的区别?

      string 其实相当于一个保存字W的序列容器Q因此除了有字符串的一些常用操作以外,q有包含了所有的序列容器的操作。字W串的常用操作包括:增加、删除、修攏V查找比较、链接、输入、输出等。详l函数列表参?a class=twikiAnchorLink >附录。不要害怕这么多函数Q其实有许多是序列容器带有的Q^时不一定用的上?

      如果你要想了解所有函数的详细用法Q你需要查?a class=twikiLink >basic_stringQ或者下?a target=_top rel=nofollow>STL~程手册。这里通过实例介绍一些常用函数?

      #include <string>
      #include <iostream>
      using namespace std;
      int main(){
      string strinfo="Please input your name:";
      cout << strinfo ;
      cin >> strinfo;
      if( strinfo == "winter" )
      cout << "you are winter!"<<endl;
      else if( strinfo != "wende" )
      cout << "you are not wende!"<<endl;
      else if( strinfo < "winter")
      cout << "your name should be ahead of winter"<<endl;
      else
      cout << "your name should be after of winter"<<endl;
      strinfo += " , Welcome to China!";
      cout << strinfo<<endl;
      cout <<"Your name is :"<<endl;
      string strtmp = "How are you? " + strinfo;
      for(int i = 0 ; i < strtmp.size(); i ++)
      cout<<strtmp[i];
      return 0;
      } 
      
      

下面是程序的输出 BeautifierPlugin Error: Unable to handle "bash" syntax.

-bash-2.05b$ make tt
c++  -O -pipe -march=pentiumpro  tt.cpp  -o tt
-bash-2.05b$ ./tt
Please input your name:Hero
you are not wende!
Hero , Welcome to China!
How are you? Hero , Welcome to China!

有了q些操作W,在STL中仿函数都可以直接用string作ؓ参数Q例?less, great, equal_to {,因此在把string作ؓ参数传递的时候,它的使用和int 或者float{已l没有什么区别了。例如,你可以用:

map<string, int> mymap;
//以上默认使用?less<string>

有了 operator + 以后Q你可以直接q加Q例如:
string strinfo="Winter";
string strlast="Hello " + strinfo + "!";
//你还可以q样Q?/font>
string strtest="Hello " + strinfo + " Welcome" + " to China" + " !";

看见其中的特点了吗?只要你的{式里面有一?string 对象Q你可以一直连l?+"Q但有一炚w要保证的是,在开始的两项中,必须有一Ҏ string 对象。其原理很简单:
  1. pȝ遇到"+"P发现有一Ҏstring 对象?
  2. pȝ把另一{化ؓ一个?string 对象?
  3. 执行 operator + 操作Q返回新的时string 对象?
  4. 如果又发?+"Pl箋W一步操作?
׃q个{式是由左到叛_始检执行,如果开始两w是const char* Q程序自己ƈ没有定义两个const char* 的加法,~译的时候肯定就有问题了?

有了操作W以后,assign(), append(), compare(), at(){函敎ͼ除非有一些特D的需求时Q一般是用不上。当然at()函数q有一个功能,那就是检查下标是否合法,如果是用:

string str="winter";
//下面一行有可能会引L序中断错?/font>
str[100]='!';
//下面会抛出异?throws: out_of_range
cout<<str.at(100)<<endl;

了解了吗Q如果你希望效率高,q是使用[]来访问,如果你希望稳定性好Q最好用at()来访问?

1.2 D~ؕ的string find 函数

׃查找是用最为频J的功能之一Qstring 提供了非怸富的查找函数。其列表如下Q?
函数? 描述
find 查找
rfind 反向查找
find_first_of 查找包含子串中的M字符Q返回第一个位|?
find_first_not_of 查找不包含子串中的Q何字W,q回W一个位|?
find_last_of 查找包含子串中的M字符Q返回最后一个位|?
find_last_not_of 查找不包含子串中的Q何字W,q回最后一个位|?
以上函数都是被重载了4ơ,以下是以find_first_of 函数Z说明他们的参敎ͼ其他函数和其参数一P也就是说d?4个函?smile Q?
size_type find_first_of(const basic_string& s, size_type pos = 0)
size_type find_first_of(const charT* s, size_type pos, size_type n)
size_type find_first_of(const charT* s, size_type pos = 0)
size_type find_first_of(charT c, size_type pos = 0)

所有的查找函数都返回一个size_typecdQ这个返回g般都是所扑ֈ字符串的位置Q如果没有找刎ͼ则返回string::npos。有一炚w要特别注意,所有和string::npos的比较一定要用string::size_type来用,不要直接使用int 或者unsigned int{类型。其实string::npos表示的是-1, 看看头文Ӟ
template <class _CharT, class _Traits, class _Alloc>
const basic_string<_CharT,_Traits,_Alloc>::size_type
basic_string<_CharT,_Traits,_Alloc>::npos
= basic_string<_CharT,_Traits,_Alloc>::size_type) -1;

find ?rfind 都还比较Ҏ理解Q一个是正向匚wQ一个是逆向匚wQ后面的参数pos都是用来指定起始查找位置。对于find_first_of 和find_last_of ׃是那么好理解?

find_first_of 是给定一个要查找的字W集Q找到这个字W集中Q何一个字W所在字W串中第一个位|。或许看一个例子更Ҏ明白?

有这样一个需求:qo一行开头和l尾的所有非英文字符。看看用string 如何实现Q?

#include <string>
#include <iostream>
using namespace std;
int main(){
string strinfo="   //*---Hello Word!......------";
string strset="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";
int first = strinfo.find_first_of(strset);
if(first == string::npos) {
cout<<"not find any characters"<<endl;
return -1;
}
int last = strinfo.find_last_of(strset);
if(last == string::npos) {
cout<<"not find any characters"<<endl;
return -1;
}
cout << strinfo.substr(first, last - first + 1)<<endl;
return 0;
}

q里把所有的英文字母大小写作Z需要查扄字符集,先查扄一个英文字母的位置Q然后查找最后一个英文字母的位置Q然后用substr 来的C间的一部分Q用于输出结果。下面就是其l果Q?
Hello Word

前面的符号和后面的符号都没有了。像q种用法可以用来查找分隔W,从而把一个连l的字符串分割成为几部分Q达?shell 命o中的 awk 的用法。特别是当分隔符有多个的时候,可以一ơ指定。例如有q样的需求:
张三|3456123, 湖南
李四,4564234| 湖北
王小? 4433253|北京
...

我们需要以 "|" ","为分隔符Q同时又要过滤空|把每行分成相应的字段。可以作Z的一个家庭作业来试试Q要求代码简z?

1.3 string insert, replace, erase

了解了string 的操作符Q查扑և数和substrQ其实就已经了解了string?0%的操作了。insert函数, replace函数和erase函数在用v来相对简单。下面以一个例子来说明其应用?

string只是提供了按照位|和区间的replace函数Q而不能用一个string字串来替换指定string中的另一个字丌Ӏ这里写一个函数来实现q个功能Q?

void string_replace(string & strBig, const string & strsrc, const string &strdst) {
string::size_type pos=0;
string::size_type srclen=strsrc.size();
string::size_type dstlen=strdst.size();
while( (pos=strBig.find(strsrc, pos)) != string::npos){
strBig.replace(pos, srclen, strdst);
pos += dstlen;
}
}

看看如何调用Q?
#include <string>
#include <iostream>
using namespace std;
int main() {
string strinfo="This is Winter, Winter is a programmer. Do you know Winter?";
cout<<"Orign string is :\n"<<strinfo<<endl;
string_replace(strinfo, "Winter", "wende");
cout<<"After replace Winter with wende, the string is :\n"<<strinfo<<endl;
return 0;
}

其输出结果:
Orign string is :
This is Winter, Winter is a programmer. Do you know Winter?
After replace Winter with wende, the string is :
This is wende, wende is a programmer. Do you know wende?

如果不用replace函数Q则可以使用erase和insert来替换,也能实现string_replace函数的功能:
void string_replace(string & strBig, const string & strsrc, const string &strdst) {
string::size_type pos=0;
string::size_type srclen=strsrc.size();
string::size_type dstlen=strdst.size();
while( (pos=strBig.find(strsrc, pos)) != string::npos){
strBig.erase(pos, srclen);
strBig.insert(pos, strdst);
pos += dstlen;
}
}

当然Q这U方法没有用replace来得直接?

string_replace(strinfo, "Winter", "wende");


来代?
void string_replace(string & strBig, const string & strsrc, const string &strdst) 

在C语言中只有char* ?const char*Qؓ了用v来方便,string提供了三个函数满_要求Q?
const charT* c_str() const
const charT* data() const
size_type copy(charT* buf, size_type n, size_type pos = 0) const 

其中Q?
  1. c_str 直接q回一个以\0l尾的字W串?
  2. data 直接以数l方式返回string的内容,其大ؓsize()的返回|l尾q没有\0字符?
  3. copy 把string的内Ҏ贝到bufI间中?
你或怼问,c_str()的功能包含data()Q那q需要data()函数q什么?看看源码Q?
const charT* c_str () const
{ if (length () == 0) return ""; terminate (); return data (); }

原来c_str()的流E是Q先调用terminate()Q然后在q回data()。因此如果你Ҏ率要求比较高Q而且你的处理又不一定需要以\0的方式结束,你最好选择data()。但是对于一般的C函数中,需要以const char*入参敎ͼ你就要用c_str()函数?

对于c_str() data()函数Q返回的数组都是由string本n拥有Q千万不可修改其内容。其原因是许多string实现的时候采用了引用机制Q也是_有可能几个string使用同一个字W存储空间。而且你不能用sizeof(string)来查看其大小。详l的解释和实现查?a target=_top rel=nofollow>Effective STL的条?5Q?a target=_top rel=nofollow>心string实现的多h?/font>?

另外在你的程序中Q只在需要时才用c_str()或者data()得到字符Ԍ每调用一ơ,下次再用就会失效,如:

string strinfo("this is Winter");
...
//最好的方式?
foo(strinfo.c_str());
//也可以这么用:
const char* pstr=strinfo.c_str();
foo(pstr);
//不要再用了pstr? 下面的操作已lpstr无效了?/font>
strinfo += " Hello!";
foo(pstr);//错误Q?/font>

会遇C么错误?当你q运的时候pstr可能只是指向"this is Winter Hello!"的字W串Q如果不q运Q就会导致程序出现其他问题,M有一些不可遇见的错误。M不会是你预期的那个结果?

3 string ?Charactor Traits

了解了string的用法,该详l看看string的真怺。前面提到string 只是basic_string的一个typedef。看看basic_string 的参敎ͼ
template <class charT, class traits = char_traits<charT>,
class Allocator = allocator<charT> >
class basic_string
{
//...
}

char_traits不仅是在basic_string 中有用,在basic_istream ?basic_ostream中也需要用到?

像Steve Donovan?a target=_top>q度使用C++模板中提到的Q这些确实有些过头了Q要不是pȝ自己定义了相关的一些属性,而且用了个typedefQ否则还真不知道如何使用?

但复杂L复杂道理。有了char_traitsQ你可以定义自己的字W串cd。当Ӟ有了char_traits < char > 和char_traits < wchar_t > 你的需求用已l够了Qؓ了更好的理解string Q咱们来看看char_traits都有哪些要求?

如果你希望用你自己定义的字W,你必d义包含下列成员的l构Q?
表达?/font> 描述
char_type 字符cd
int_type int cd
pos_type 位置cd
off_type 表示位置之间距离的类?
state_type 表示状态的cd
assign(c1,c2) 把字Wc2赋值给c1
eq(c1,c2) 判断c1,c2 是否相等
lt(c1,c2) 判断c1是否于c2
length(str) 判断str的长?
compare(s1,s2,n) 比较s1和s2的前n个字W?
copy(s1,s2, n) 把s2的前n个字W拷贝到s1?
move(s1,s2, n) 把s2中的前n个字W移动到s1?
assign(s,n,c) 把s中的前n个字W赋gؓc
find(s,n,c) 在s的前n个字W内查找c
eof() q回end-of-file
to_int_type(c) c转换成int_type
to_char_type(i) i转换成char_type
not_eof(i) 判断i是否为EOF
eq_int_type(i1,i2) 判断i1和i2是否相等
想看看实际的例子Q你可以看看sgi STL?a target=_top>char_traitsl构源码.

现在默认的string版本中,q不支持忽略大小写的比较函数和查扑և敎ͼ如果你想l练手,你可以试试改写一个char_traits , 然后生成一个case_stringc? 也可以在string 上做l承Q然后派生一个新的类Q例如:ext_stringQ提供一些常用的功能Q例如:

  1. 定义分隔W。给定分隔符Q把string分ؓ几个字段?
  2. 提供替换功能。例如,用winter, 替换字符串中的wende
  3. 大小写处理。例如,忽略大小写比较,转换{?
  4. 整Ş转换。例如把"123"字符串{换ؓ123数字?
q些都是常用的功能,如果你有兴趣可以试试。其实有人已l实CQ看?a target=_top rel=nofollow>Extended STL string。如果你惛_懒,下蝲一个头文g可以用Q有了它实方便了很多。要是有提供一个支持正则表辑ּ的stringQ我会非怹意用?

4 string

使用string 的方便性就不用再说了,q里要重点强调的是string的安全性?
  1. stringq不是万能的Q如果你在一个大工程中需要频J处理字W串Q而且有可能是多线E,那么你一定要慎重(当然Q在多线E下你用Q何STL容器都要慎重)?
  2. string的实现和效率q不一定是你想象的那样Q如果你对大量的字符串操作,而且特别兛_其效率,那么你有两个选择Q首先,你可以看看你使用的STL版本中string实现的源码;另一选择是你自己写一个只提供你需要的功能的类?
  3. string的c_str()函数是用来得到C语言风格的字W串Q其q回的指针不能修改其I间。而且在下一ơ用时重新调用获得新的指针?
  4. string的data()函数q回的字W串指针不会?\0'l束Q千万不可忽视?
  5. 量M用操作符Q这样可以让E序更加易懂Q特别是那些脚本E序员也可以看懂Q?

5 结

难怪有Q?br>string 使用方便功能强,我们一直用它!

6 附录

string 函数列表
函数? 描述
begin 得到指向字符串开头的Iterator
end 得到指向字符串结Iterator
rbegin 得到指向反向字符串开头的Iterator
rend 得到指向反向字符串结Iterator
size 得到字符串的大小
length 和size函数功能相同
max_size 字符串可能的最大大?
capacity 在不重新分配内存的情况下Q字W串可能的大?
empty 判断是否为空
operator[] 取第几个元素Q相当于数组
c_str 取得C风格的const char* 字符?
data 取得字符串内容地址
operator= 赋值操作符
reserve 预留I间
swap 交换函数
insert 插入字符
append q加字符
push_back q加字符
operator+= += 操作W?
erase 删除字符?
clear 清空字符容器中所有内?
resize 重新分配I间
assign 和赋值操作符一?
replace 替代
copy 字符串到I间
find 查找
rfind 反向查找
find_first_of 查找包含子串中的M字符Q返回第一个位|?
find_first_not_of 查找不包含子串中的Q何字W,q回W一个位|?
find_last_of 查找包含子串中的M字符Q返回最后一个位|?
find_last_not_of 查找不包含子串中的Q何字W,q回最后一个位|?
substr 得到字串
compare 比较字符?
operator+ 字符串链?
operator== 判断是否相等
operator!= 判断是否不等?
operator< 判断是否于
operator>> 从输入流中读入字W串
operator<< 字符串写入输出流
getline 从输入流中读入一?



jinfeng_wang 2007-06-05 17:33 发表评论
]]>便利的开发文档工?doxygenhttp://www.tkk7.com/jinfeng_wang/archive/2007/06/01/121339.htmljinfeng_wangjinfeng_wangFri, 01 Jun 2007 05:17:00 GMThttp://www.tkk7.com/jinfeng_wang/archive/2007/06/01/121339.htmlhttp://www.tkk7.com/jinfeng_wang/comments/121339.htmlhttp://www.tkk7.com/jinfeng_wang/archive/2007/06/01/121339.html#Feedback0http://www.tkk7.com/jinfeng_wang/comments/commentRss/121339.htmlhttp://www.tkk7.com/jinfeng_wang/services/trackbacks/121339.htmlhttp://www.moon-soft.com/doc/39077.htm


便利的开发文档工?doxygen
mounton @ {www.ihere.org} ( mount0n@yahoo.com)
2003q??/p>

0. 序言
Z码写注释一直是大多数程序员有些困扰的事情。当前程序员都能接受ZE序的可l护性、可L编码的同时写注释的说法Q但对哪些地方应该写注释Q注释如何写Q写多少{这些问题,很多E序员仍然没有答案。更头痛的是写文档,以及l护文档的问题,开发h员通常可以忍受~写或者改动代码时~写或者修改对应的注释Q但之后需要修正相应的文档却比较困难。如果能从注释直接{化成文档Q对开发h员无疑是一U福韟뀂而doxygenp把遵守某U格式的注释自动转化为对应的文档?/p>

Doxygen是基于GPL的开源项目,是一个非怼U的文档系l,当前支持在大多数unixQ包括linuxQ,windows家族QMacpȝ上运行,完全支持C++, C, Java, IDLQCorba和Microsoft 家族Q语aQ部分支持PHP和C#语言Q输出格式包括HTML、latex、RTF、ps、PDF、压~的HTML和unix manpage。有很多开源项目(包括前两文章介l的log4cpp和CppUnitQ都使用了doxygen文档pȝ。而国内的开发h员却使用的不多,q里从开发h员用的角度介绍q个工具Q开发h员用最的代h快掌握q种技术,q结合这个工h讨如何撰写注释的问题。以下以linux下的C++语言Zq行介绍Q以下讨论基于doxygen1.3.3?/p>

1. doxygen使用步骤
׃只是工具的用,q里不介l它的原理,直接从用步骤开始。Doxygen的用步骤非常简单。主要可以分为:
 1Q第一ơ用需要安装doxygen的程?br> 2Q生成doxygen配置文g
 3Q编码时Q按照某U格式编写注?br> 4Q生成对应文?br>doxygen的安装非常简单, linux下可以直接下载安装包q行卛_Q下载源代码~译安装也是比较通用的编译安装命令。请参考其安装文档完成安装?/p>

Doxygen在生成文档时可以定义目属性以及文档生成过E中的很多选项Q用下面命令能够生一个缺省的配置文gQ?br>doxygen -g  [配置文g名]
可以Ҏ目的具体需求修攚w|文件中对应的项Q具体的修改q程在下面介l。修改过的配|文件可以作Z后项目的模板?/p>

让doxygen自动产生文档Q^常的注释风格可不行,需要遵循doxygen自己的格式。具体如何写doxygen认识的注释在W?节详l介l?/p>

OKQ代码编完了Q注释也按照格式写好了,最后的文档是如何的哪?非常单,q行下面的命令,相应的文档就会生在指定的目录中?br>  doxygen [配置文g名]

需要注意的是doxygenq不处理所有的注释Qdoxygen重点x与程序结构有关的注释Q比如:文g、类、结构、函数、变量、宏{注释,而忽略函数内变量、代码等的注释?/p>

2. doxygen配置文g
doxygen配置文g的格式是也是通常的unix下配|文件的格式Q注?#'开始;tag = value [,value2…]Q对于多值的情况可以使用 tag += value [,value2…]?/p>

对doxygen的配|文件的修改分ؓ两类Q一U就是输出选项Q控制如何解释源代码、如何输出;一U就是项目相关的信息Q比如项目名U、源代码目录、输出文档目录等。对于第一U设|好后,通常所有项目可以共用一份配|,而后一U是每个目必须讄的。下面选择重要的,有可能需要修改的选项q行解释说明Q其他选项在配|文仉有详l解释?/p>

TAG ~省?nbsp;含义
PROJECT_NAME  目名称
PROJECT_NUMBER  可以理解为版本信?br>OUTPUT_DIRECTORY  输出文g到的目录Q相对目录(doxygenq行目录Q或者绝对目?br>INPUT  代码文g或者代码所在目录,使用I格分割
FILE_PATTERNS *.c *.cc *.cxx *.cpp *.c++ *.java *.ii *.ixx *.ipp *.i++ *.inl *.h *.hh *.hxx *.hpp *.h++ *.idl *.odl 指定INPUT的目录中特定文gQ如Q?.cpp *.c *.h
RECURSIVE NO 是否递归INPUT中目录的子目?br>EXCLUDE  在INPUT目录中需要忽略的子目?br>EXCLUDE_PATTERNS  明确指定的在INPUT目录中需要忽略的文gQ如QFromOut*.cpp
  
OUTPUT_LANGUAGE English 生成文档的语aQ当前支??0U语aQ国内用户可以设|ؓChinese
USE_WINDOWS_ENCODING YESQwin版本Q?br>NOQunix版本Q?nbsp;~码格式Q默认即可?br>EXTRACT_ALL NO 为NOQ只解释有doxygen格式注释的代码;为YESQ解析所有代码,即没有注释。类的私有成员和所有的静态项由EXTRACT_PRIVATE?EXTRACT_STATIC控制
EXTRACT_PRIVATE NO 是否解析cȝU有成员
EXTRACT_STATIC NO 是否解析静态项
EXTRACT_LOCAL_CLASSES YES 是否解析源文Ӟcpp文gQ中定义的类
SOURCE_BROWSER NO 如果为YESQ源代码文g会被包含在文档中
INLINE_SOURCES NO 如果为YESQ函数和cȝ实现代码被包含在文档?br>ALPHABETICAL_INDEX NO 生成一个字母序的列表,有很多类、结构等Ҏ设ؓYES
GENERATE_HTML YES 是否生成HTML格式文档
GENERATE_HTMLHELP NO 是否生成压羃HTML格式文档Q?chmQ?br>GENERATE_LATEX YES 是否乘Rlatex格式的文?br>GENERATE_RTF NO 是否生成RTF格式的文?br>GENERATE_MAN NO 是否生成man格式文档
GENERATE_XML NO 是否生成XML格式文档
  

3. doxygen注释
3.1 注释风格
下面是工作量最大部分,安装doxygen格式写注释。通常代码可以附上一个注释块来对代码q行解释Q一个注释块׃行或者多行组成。通常一个注释块包括一个简要说明(briefQ和一个详l说明(detailedQ,q两部分都是可选的。可以有多种方式标识出doxygen可识别的注释块?br>1QJavaDoccd的多行注释?br>/**
 *  ….text….
 */
2QQT样式的多行注释?br>/*!
….text….
 */
3Q?/// …text….
4Q?//! …text….
要说明有多种方式标识Q这里推荐用@brief命o强制说明Q例如:
/**
 * @brief [some brief description ]
 *      [ brief description more. ]
 *
 * [some more detailed description…]
 */
以上q些注释格式用来对紧跟其后的代码q行注释。doxygen也允许把注释攑ֈ代码后面Q具体格式是放一?<'到注释开始部分。例如:
int var1 ; /**< ….text…. */
int var2; ///< ….text….

注释和代码完全分,攑֜其他地方也是允许的,但需要用特D的命o加上名称或者声明进行标识,比如Qclass、struct、union、enum、fn、var、def、file、namespace、package、interfaceQ这些也是doxygenx的注释类型)。这里不推荐使用Q徏议注释尽量放在代码前后。具体用方式参见doxygen手册?/p>

3.2 doxygen常用注释格式
通常的选择上面的一、两U注释风|遇到头文件中各种cd定义Q关键变量、宏的定义,在其前或者后使用 @brief 定义其简要说明,IZ行后l箋写其详细的注释即可?/p>

对函数的注释Q是比较常常需要注释的部分。除了定义其要说明以及详l注释,q可以用param命o对其各个参数q行注释Q用return命o对返回D行注释。常见的格式如下Q?br>/**
 *@brief func's brief comment.
 *
 * Some detailed comment.
 *@param a [param a 's comment.]
 *@param b [param b 's comment.]
 *@exception std::out_of_range [exception's comment.]
 *@return [return's comment.]
 */
int func1(int a, int b);

q行设计Ӟ通常有模块的概念Q一个模块可能有多个cL者函数组成,完成某个特定功能的代码的集合。如何对q个概念q行注释Qdoxygen提供了group的概念,生成的模块的注释会单独放在一个模块的面中。用下面的格式定义一个group?br>/** [group_name] [brief group description ]
 * detailed group description ]
 * @{
*/
code
/** @} */
group中的代码可以有自q注释。单U定义一个模块,去除{ 和}命o卛_。Q何其他代码项Q比如类、函数、甚xӞ如果要加入到某个模块Q可以在其doxygen注释中用ingroup命o卛_。Group之间使用ingroup命oQ可以组成树状关pR?br>/** @file util.cpp
* @ingroup [group_name]
 * @brief file's brief info.
 */
把多个代码项一h加到某个模块中可以用addtogroup命oQ格式和defgroup怼?/p>

对于某几个功能类似的代码(比如cR函数、变量){,如果希望一h加注释,而又不想提升到模块的概念Q可以通过下面的方式:
//@{
/** Comments for all below code. */
code…
//@}
对这U组q行命名可以使用name命o。此时中间代码可以有自己的注释。如Q?br>/** @name group_name
 * description for group.
 */
//@{
code…
//@}

3.3 doxygen常用注释命o
doxygen通过注释命o识别注释中需要特D处理的注释Q比如函数的参数、返回D行突出显C。上面也提到了一些注释命令(如:brief、param、return、以及group相关的命令)Q下面对其他一些常用的注释命oq行解释说明?br>@exception <exception-object> {exception description} 对一个异常对象进行注释?br>@warning {warning message } 一些需要注意的事情
@todo { things to be done }  对将要做的事情进行注?br>@see {comment with reference to other items } 一D包含其他部分引用的注释Q中间包含对其他代码的名称Q自动生对其的引用链接?br>@relates <name> 通常用做把非成员函数的注释文档包含在cȝ说明文档中?br>@since {text} 通常用来说明从什么版本、时间写此部分代码?br>@deprecated
@pre { description of the precondition } 用来说明代码的前提条g?br>@post { description of the postcondition } 用来说明代码之后的使用条g?br>@code 在注释中开始说明一D代码,直到@endcode命o?br>@endcode 注释中代码段的结束?/p>

到此为止Q常用的doxygen的注释格式讨论完毕,我们能够按照一定的格式撰写doxygen认识的注释,q能够用doxygen方便快捷的生成对应的文档Q不q注释中应该写些什么,如何撰写有效的注释可能是困扰开发h员的一个更深层ơ的问题?/p>

4. 注释的书?br>注释应该怎么写,写多q是写少。过多的注释甚至会干扰对代码的阅诅R写注释的一个ȝ原则是注释应该量用来表明作者的意图Q至也应该是对一部分代码的ȝQ而不应该是对代码的重复或者解释。对代码的重复或者解释的代码Q看代码可能更容易理解。反映作者意囄注释解释代码的目的,从解决问题的层次上进行注释,而代码ȝ性注释则是从问题的解{的层次上进行注释?/p>

推荐的写注释的过E是首先使用注释勑֋Z码的主要框架Q然后根据注释撰写相应的代码。对各种主要的数据结构、输出的函数、多个函数公用的变量q行详细地注释。对代码中控制结构,单一目的的语句集q行注释。下面是一些写注释旉要注意的要点Q?br>  避免对单独语句进行注释;
  通过注释解释Z么这么做、或者要做什么,使代码的读者可以只阅读注释理解代码Q?br>  对读者可能会有疑问的地方q行注释Q?br>  Ҏ据定义进行注释,而不是对其用过E进行注释;
  对于难于理解的代码,q行改写Q而不要试N过注释加以说明Q?br>  对关键的控制l构q行注释Q?br>  Ҏ据和函数的边界、用前提等q行注释Q?/p>

5. 参考资?br> 1. doxygen homepage
 http://www.stack.nl/~dimitri/doxygen/

 2. doxygen manual
 http://www.stack.nl/~dimitri/doxygen/manual.html

 3. Code Complete: A Practical Handbook of Software Construction. Redmond, Wa.: Microsoft Press, 880 pages, 1993. ISBN: 1-55615-484-4.
 
 4. 介doxygen
 http://www.stack.nl/~dimitri/doxygen/doxygen_intro_cn.html
 
 5. 10 Minutes to document your code
 http://www.codeproject.com/tips/doxysetup.asp

 6. 使用doxygen
 http://www.csdn.net/Develop/article/16%5C16383.shtm

 
6. 关于作?br>mounton @ {www.ihere.org} 当前x于网l安全品的开发、研IӞ软g开发过E等斚w。您可以通过mount0n@yahoo.com和他联系?br>




jinfeng_wang 2007-06-01 13:17 发表评论
]]>
Graphviz & Doxygen ゟ냼ド構造を視覚化せよ!Q?/title><link>http://www.tkk7.com/jinfeng_wang/archive/2007/06/01/121338.html</link><dc:creator>jinfeng_wang</dc:creator><author>jinfeng_wang</author><pubDate>Fri, 01 Jun 2007 05:07:00 GMT</pubDate><guid>http://www.tkk7.com/jinfeng_wang/archive/2007/06/01/121338.html</guid><wfw:comment>http://www.tkk7.com/jinfeng_wang/comments/121338.html</wfw:comment><comments>http://www.tkk7.com/jinfeng_wang/archive/2007/06/01/121338.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.tkk7.com/jinfeng_wang/comments/commentRss/121338.html</wfw:commentRss><trackback:ping>http://www.tkk7.com/jinfeng_wang/services/trackbacks/121338.html</trackback:ping><description><![CDATA[<h2 align=center>ゟ냼ド構造を視覚化せよ!Q?br>Graphviz & Doxygen</h2> <hr> <p><a >http://skazami.web.infoseek.co.jp/tools/Graphviz_Doxygen.htm</a><br><br><br><br><br>ゟ냼ドの構造を視覚化するためのツールです。コヹ{解析に有劏Vどうかはともかく、なかなか面白いツールです?br><br>それぞれのツヹ{のサイトQたぶん、公式サイトQはこちら?br><br><a ><font color=#0000ff><u>Graphviz</u></font></a><br><a ><u><font color=#0000ff>Doxygen</font></u></a><br><br>どちらもオープンソーわVすので、開発に参加することもできるようです。Doxygenは寄付も受け付けているようです?/p> <p>前置きはこのくらいにして、説明いきます?/p> <hr> <h3>インわVヹ{</h3> <p>自分のプラットフォームにあったパッケヹ{をダウンロードします。Linux用、Windows用、Mac用などあります?/p> <p>Graphvizは、上aサイト内にある<a ><u><font color=#0000ff>download</font></u></a>をクリックして、パッケヹ{を持ってきます?br>Doxygenも、上aサイトの右のほうにある<a ><u><font color=#0000ff>Binaries</font></u></a>をクリックして、パッケヹ{を持ってきます?br><br>インわVヹ{?strong>必ずGraphviz→Doxygenの順?/strong>で行います?br><br>以下の説明はWindows用についてのものです?br>インわVヹ{はイミ낹トーラ(exeファイルQを起動してウィザードに従うだけなので、悩むこともないと思います?/p> <dl> <dt><strong>わVップバイわVップインわVヹ{手順</strong>Q?a ><u><font color=#0000ff>Graphviz</font></u></a>?a ><u><font color=#0000ff>Doxygen</font></u></a>Q? <dd>インわVヹ{慣れしている斏VわVップしてください。ほとんどデフォルトでのインわVヹ{ですので。どちらかとaうと、自分用作業メモです?</dd></dl> <hr> <h3>使用?/h3> <ol> <li>インわVヹ{時に入れておいた「doxygen example Project」を例にゟ냼ドの構造を視覚化してみます <li>「スѝト?#8594;「プログラム?#8594;「doxygen?#8594;「Doxywizard」を起動します。このツヹ{により、設定ファイルの作成とDoxygenの実行をGUIから行うことができます? <p><a ><img height=253 src="http://skazami.web.infoseek.co.jp/tools/doxygen/image_small/doxygen01.jpg" width=324 border=0></a><br></p> <li>OUTPUT_LANGUAGEを「Japanese」にしま? <p><a ><img height=253 src="http://skazami.web.infoseek.co.jp/tools/doxygen/image_small/doxygen02.jpg" width=324 border=0></a><br></p> <li>Buildѝをクリックし、「EXTRACT_ALL」にチェックを入れま? <p><a ><img height=253 src="http://skazami.web.infoseek.co.jp/tools/doxygen/image_small/doxygen04.jpg" width=324 border=0></a><br></p> <li>LaTeXѝをクリックし、「GENERATE_LATEX」のチェックを外します。もちろん、LaTeXの出力が必要ならチェックを入れておいてくださ? <p><a ><img height=253 src="http://skazami.web.infoseek.co.jp/tools/doxygen/image_small/doxygen06.jpg" width=324 border=0></a><br></p> <li>Dotѝをクリックし、「HAVE_DOT」にチェックを入れま? <p><a ><img height=253 src="http://skazami.web.infoseek.co.jp/tools/doxygen/image_small/doxygen08.jpg" width=324 border=0></a><br></p> <li>「CALL_GRAPH」にもチェックを入れときます。関数の呹{出し状況を図にしてくれます? <p><a ><img height=253 src="http://skazami.web.infoseek.co.jp/tools/doxygen/image_small/doxygen09.jpg" width=324 border=0></a><br></p> <li>「File?#8594;「Save as...」でa定ファイルを保存しますが、保存先?strong>「C:\Program Files\doxygen\examples」(デフォルト設定でインわVヹ{した場合Q?/strong>としてください。ファイル名は何でもいいですが、とりあえず「Doxyfile」とでもしておきましょう <p><br></p> <li>「Doxygen?#8594;「Run」で実行します。コミ낽ヹ{が出現し、処理が逌Ӂます <p><a ><img height=241 src="http://skazami.web.infoseek.co.jp/tools/doxygen/image_small/doxygen10.jpg" width=334 border=0></a></p> <li><strong>「C:\Program Files\doxygen\examples?/strong>にhtmlというフォルダが作成されます。そのフォルダの中のindex.htmlを開いてѝ? <p><a ><img height=360 src="http://skazami.web.infoseek.co.jp/tools/doxygen/image_small/doxygen11.jpg" width=446 border=0></a><br><br>どうでしょう、こんな画面になりましたか?</p> <li>「ファイル一覧?#8594;example_test.cppを開いてѝください。関数の呹{出しグラフが表示されましたかQグラフがクリッカブルマップになっていますかQ? <li>「ファイル一覧?#8594;diagrams_a.hを開いてѝください。ファイルの依存関係のグラフが表Cされましたか?グラフがクリッカブルマップになっていますか? </li> </ol> <p>問題がなければ、基本的ない方は以上です。あとはマニュアルを読みながら高度なѝ斏V模烦してください。私自n、あまり高度ない方はできていないので、面白いѝ斏Vあったら教えていただきたいです?br><br>Doxygenのマニュアルを日本語化している方がいらっしゃるようです?br><a ><u><font color=#0000ff>http://www.fides.dti.ne.jp/~oka-t/doxygen-manual/html/</font></u></a></p> <u><font color=#0000ff> <hr> </font></u> <h3><strong>Doxygenで変換した結果の?/strong></h3> <p>Uが変換してѝものを以下に|いておきます。同じような感じになっているかどうかを確認するためにѝてみてください?/p> <p><a ><font color=#0000ff><u>doxygen付属のexampleプロジェクト</u></font></a><br><br><a ><u><font color=#0000ff>デフォルト設定で作成直後のWin32アプリケヹ{ョンプロジェクト</font></u></a>Q作成環境はVisual Studio .net 2003Q?/p> <p>[余談]<br>doxygenのexampleプロジェクトの変換結果で、「関連ペヹ{?#8594;「バC覧?#8594;「WindowsNT」は、あからさま過ぎるくらいあからさまで、まぁまぁ面白いです。これ以上のゟ냡ミ냈は控えます?br>[余談i]</p> <img src ="http://www.tkk7.com/jinfeng_wang/aggbug/121338.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.tkk7.com/jinfeng_wang/" target="_blank">jinfeng_wang</a> 2007-06-01 13:07 <a href="http://www.tkk7.com/jinfeng_wang/archive/2007/06/01/121338.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Doxygen的用体?(zz)http://www.tkk7.com/jinfeng_wang/archive/2007/06/01/121337.htmljinfeng_wangjinfeng_wangFri, 01 Jun 2007 05:06:00 GMThttp://www.tkk7.com/jinfeng_wang/archive/2007/06/01/121337.htmlhttp://www.tkk7.com/jinfeng_wang/comments/121337.htmlhttp://www.tkk7.com/jinfeng_wang/archive/2007/06/01/121337.html#Feedback0http://www.tkk7.com/jinfeng_wang/comments/commentRss/121337.htmlhttp://www.tkk7.com/jinfeng_wang/services/trackbacks/121337.html 

Doxygen的用体?

 

Doxygen是一Ƒּ源YӞ可用于从已经存在的VC工程中提炼出软g文档QHTML{格式)Q包括文件说明、类说明、属性方法说明、类关系{内宏V一般常Doxygen和graphviz两款软g一起安装,后者是一Ƅ图YӞ可在前者生成的软g文档中增加图表。Doxygen的细节可以上|搜索。这里脓一下个Z会,可帮助感兴趣的朋友迅速上手这个YӞ

1Q安装DOXYGEN和graphviz后,可以?#8220;DOXYGEN安装目录\bin”下用命o行方式运行doxygen.exe -g 生成一个名为Doxyfile的配|文件?

2Q将文gDoxyfile复制到想生成文档的VC工程目录下?

修改该文件中的如下选项Q?

  1. PROJECT_NAME          = 填上目名称    
  2. OUTPUT_LANGUAGE        = 改ؓChinese    
  3. GENERATE_LATEX        = 改ؓNO    
  4. EXTRACT_ALL            = 改ؓYES    
  5. HAVE_DOT              = 改ؓYES    
  6. DOT_IMAGE_FORMAT      = 该ؓJPG    
  7. DOT_PATH              = 填上"C:/Program Files/ATT/Graphviz/bin/"    
  8. DOTFILE_DIRS          = 填上"c:/Program Files/ATT/Graphviz/bin/"   

 

3Q对VC工程q行如下修改

Q?Q在stdAfx.h中增加预定义Q以支持DOTd?

  1. #ifndef _DIAGRAMS_A_H    
  2. #define _DIAGRAMS_A_H    
  3. #endif   

 

Q?Q在重要的类、方法、属性前面增加注释,以支持DOXYGEN分析?

  1. ///    @brief 最主要的业务实现类    
  2. ///    
  3. ///            所有的法内容基本都在q个cM实现?nbsp;   
  4. ///    
  5. ///    @author lipp   

 

或者放在语句后?

  1. char sFilename[400];            ///< LOG文g?nbsp;  

 

q在重要文g前增加注?

  1. ///    @file xxx.cpp    
  2. ///    被其他程序调用的Q实C法的DLLȝ序?nbsp;   
  3. ///    包括各个Ҏ输出接口?nbsp;  

 

4Q运行DOXYGEN.exe。LOAD以上的Doxyfile文g。点击START。这时会生成一个新的HTML目录在VC工程目录中?

5Q用IE打开新生成的HTML目录中的INDEX.htm文g?

 



jinfeng_wang 2007-06-01 13:06 发表评论
]]>
Endian 介绍 (zz)http://www.tkk7.com/jinfeng_wang/archive/2007/05/28/120455.htmljinfeng_wangjinfeng_wangMon, 28 May 2007 07:08:00 GMThttp://www.tkk7.com/jinfeng_wang/archive/2007/05/28/120455.htmlhttp://www.tkk7.com/jinfeng_wang/comments/120455.htmlhttp://www.tkk7.com/jinfeng_wang/archive/2007/05/28/120455.html#Feedback0http://www.tkk7.com/jinfeng_wang/comments/commentRss/120455.htmlhttp://www.tkk7.com/jinfeng_wang/services/trackbacks/120455.html阅读全文

jinfeng_wang 2007-05-28 15:08 发表评论
]]>
automake:自动生成makefile文g (zz)http://www.tkk7.com/jinfeng_wang/archive/2007/05/28/120428.htmljinfeng_wangjinfeng_wangMon, 28 May 2007 04:37:00 GMThttp://www.tkk7.com/jinfeng_wang/archive/2007/05/28/120428.htmlhttp://www.tkk7.com/jinfeng_wang/comments/120428.htmlhttp://www.tkk7.com/jinfeng_wang/archive/2007/05/28/120428.html#Feedback0http://www.tkk7.com/jinfeng_wang/comments/commentRss/120428.htmlhttp://www.tkk7.com/jinfeng_wang/services/trackbacks/120428.html  Makefile的宗旨就是:让编译器知道要编译一个文仉要依赖其他的哪些文g。当那些依赖文g有了改变Q编译器会自动的发现最l的生成文g已经q时Q而重新编译相应的模块?/p>

  Makefile的基本结构不是很复杂Q但当一个程序开发h员开始写MakefileӞl常会怀疑自己写的是否符合惯例,而且自己写的Makefilel常和自q开发环境相兌Q当pȝ环境变量或\径发生了变化后,Makefile可能q要跟着修改。这样就造成了手工书写Makefile的诸多问题,automake恰好能很好地帮助我们解决q些问题?/p>

  使用automakeQ程序开发h员只需要写一些简单的含有预定义宏的文Ӟ由autoconfҎ一个宏文g生成configureQ由automakeҎ另一个宏文g生成Makefile.inQ再使用configure依据Makefile.in来生成一个符合惯例的Makefile。下面我们将详细介绍Makefile的automake生成Ҏ?/p>

  二、用的环境

  本文所提到的程序是ZLinux发行版本QFedora Core release 1Q它包含了我们要用到的autoconfQautomake?/p>

  三、从helloworld入手

  我们从大家最怋用的例子E序helloworld开始?/p>

  下面的过E如果简单地说来是Q?/p>

  新徏三个文gQ?/p>

   helloworld.c
   configure.in
   Makefile.am

  然后执行Q?/p>

aclocal; autoconf; automake --add-missing; ./configure; make; ./helloworld

  可以看到Makefile被生出来,而且可以helloworld.c~译通过?/p>

  很简单吧Q几条命令就可以做出一个符合惯例的MakefileQ感觉如何呀?/p>

  现在开始介l详l的q程Q?/p>

  1、徏目录

  在你的工作目录下Z个helloworld目录Q我们用它来存放helloworldE序及相xӞ如在/home/my/build下:

$ mkdir helloword
$ cd helloworld

  2?helloworld.c

  然后用你自己最喜欢的编辑器写一个hellowrold.c文gQ如命oQvi helloworld.c。用下面的代码作ؓhelloworld.c的内宏V?/p>

int main(int argc, char** argv)
{
printf("Hello, Linux World!\n");
return 0;
}

  完成后保存退出?/p>

  现在在helloworld目录下就应该有一个你自己写的helloworld.c了?/p>

  3、生成configure

  我们使用autoscan命o来帮助我们根据目录下的源代码生成一个configure.in的模板文件?/p>

  命oQ?/p>

$ autoscan
$ ls
configure.scan helloworld.c

  执行后在hellowrold目录下会生成一个文Ӟconfigure.scanQ我们可以拿它作为configure.in的蓝本?/p>

  现在configure.scan改名为configure.inQƈ且编辑它Q按下面的内容修改,L无关的语句:

============================configure.in内容开?========================================
# -*- Autoconf -*-
# Process this file with autoconf to produce a configure script.

AC_INIT(helloworld.c)
AM_INIT_AUTOMAKE(helloworld, 1.0)

# Checks for programs.
AC_PROG_CC

# Checks for libraries.

# Checks for header files.

# Checks for typedefs, structures, and compiler characteristics.

# Checks for library functions.
AC_OUTPUT(Makefile)
============================configure.in内容l束=========================================

  然后执行命oaclocal和autoconfQ分别会产生aclocal.m4及configure两个文gQ?/p>

$ aclocal
$ls
aclocal.m4 configure.in helloworld.c
$ autoconf
$ ls
aclocal.m4 autom4te.cache configure configure.in helloworld.c


  大家可以看到configure.in内容是一些宏定义Q这些宏lautoconf处理后会变成查系l特性、环境变量、Y件必ȝ参数的shell脚本?/p>

  autoconf 是用来生成自动配|Y件源代码脚本QconfigureQ的工具。configure脚本能独立于autoconfq行Q且在运行的q程中,不需要用Lq预?/p>

  要生成configure文gQ你必须告诉autoconf如何扑ֈ你所用的宏。方式是使用aclocalE序来生成你的aclocal.m4?/p>

  aclocalҎconfigure.in文g的内容,自动生成aclocal.m4文g。aclocal是一个perl 脚本E序Q它的定义是Q?#8220;aclocal - create aclocal.m4 by scanning configure.ac”?/p>

  autoconf从configure.inq个列D~译软g时所需要各U参数的模板文g中创建configure?/p>

  autoconf需要GNU m4宏处理器来处理aclocal.m4Q生成configure脚本?/p>

  m4是一个宏处理器。将输入拯到输出,同时宏展开。宏可以是内嵌的Q也可以是用户定义的。除了可以展开宏,m4q有一些内建的函数Q用来引用文Ӟ执行命oQ整数运,文本操作Q@环等。m4既可以作为编译器的前端,也可以单独作Z个宏处理器?/p>

4、新建Makefile.am

  新徏Makefile.am文gQ命令:


$ vi Makefile.am


  内容如下:


AUTOMAKE_OPTIONS=foreign
bin_PROGRAMS=helloworld
helloworld_SOURCES=helloworld.c


  automake会根据你写的Makefile.am来自动生成Makefile.in?/p>

  Makefile.am中定义的宏和目标,会指导automake生成指定的代码。例如,宏bin_PROGRAMS导致编译和q接的目标被生成?/p>

  5、运行automake

  命oQ?/p>


$ automake --add-missing
configure.in: installing `./install-sh'
configure.in: installing `./mkinstalldirs'
configure.in: installing `./missing'
Makefile.am: installing `./depcomp'


  automake会根据Makefile.am文g产生一些文Ӟ包含最重要的Makefile.in?/p>

  6、执行configure生成Makefile


$ ./configure
checking for a BSD-compatible install... /usr/bin/install -c
checking whether build environment is sane... yes
checking for gawk... gawk
checking whether make sets $(MAKE)... yes
checking for gcc... gcc
checking for C compiler default output... a.out
checking whether the C compiler works... yes
checking whether we are cross compiling... no
checking for suffix of executables...
checking for suffix of object files... o
checking whether we are using the GNU C compiler... yes
checking whether gcc accepts -g... yes
checking for gcc option to accept ANSI C... none needed
checking for style of include used by make... GNU
checking dependency style of gcc... gcc3
configure: creating ./config.status
config.status: creating Makefile
config.status: executing depfiles commands
$ ls -l Makefile
-rw-rw-r-- 1 yutao yutao 15035 Oct 15 10:40 Makefile


你可以看刎ͼ此时Makefile已经产生出来了?/p>

7、用Makefile~译代码

 

$ make
if gcc -DPACKAGE_NAME="" -DPACKAGE_TARNAME="" -DPACKAGE_VERSION="" -

DPACKAGE_STRING="" -DPACKAGE_BUGREPORT="" -DPACKAGE="helloworld" -DVERSION="1.0"

-I. -I. -g -O2 -MT helloworld.o -MD -MP -MF ".deps/helloworld.Tpo" \
-c -o helloworld.o `test -f 'helloworld.c' || echo './'`helloworld.c; \
then mv -f ".deps/helloworld.Tpo" ".deps/helloworld.Po"; \
else rm -f ".deps/helloworld.Tpo"; exit 1; \
fi
gcc -g -O2 -o helloworld helloworld.o 


  q行helloworld

 

$ ./helloworld
Hello, Linux World!


  q样helloworldq译出来了Q你如果按上面的步骤来做的话Q应该也会很Ҏ地编译出正确的helloworld文g。你q可以试着使用一些其他的make命oQ如make cleanQmake installQmake distQ看看它们会l你什么样的效果。感觉如何?自己也能写出q么专业的MakefileQ老板一定会对你刮目相看?/p>

  四、深入浅?/p>

  针对上面提到的各个命令,我们再做些详l的介绍?/p>

  1?autoscan

  autoscan是用来扫描源代码目录生成configure.scan文g的。autoscan可以用目录名做ؓ参数Q但如果你不使用参数的话Q那么autoscan认Z用的是当前目录。autoscan扫描你所指定目录中的源文Ӟq创建configure.scan文g?/p>

  2?configure.scan

  configure.scan包含了系l配|的基本选项Q里面都是一些宏定义。我们需要将它改名ؓconfigure.in

  3?aclocal

  aclocal是一个perl 脚本E序。aclocalҎconfigure.in文g的内容,自动生成aclocal.m4文g。aclocal的定义是Q?#8220;aclocal - create aclocal.m4 by scanning configure.ac”?/p>

  4?autoconf

  autoconf是用来生configure文g的。configure是一个脚本,它能讄源程序来适应各种不同的操作系l^収ͼq且Ҏ不同的系l来产生合适的MakefileQ从而可以你的源代码能在不同的操作pȝq_上被~译出来?/p>

  configure.in文g的内Ҏ一些宏Q这些宏l过autoconf 处理后会变成查系l特性、环境变量、Y件必ȝ参数的shell脚本。configure.in文g中的宏的序q没有规定,但是你必d所有宏的最前面和最后面分别加上AC_INIT宏和AC_OUTPUT宏?/p>

  在configure.ini中:

  #可C注释,q个宏后面的内容被忽略?/p>

  AC_INIT(FILE)

  q个宏用来检查源代码所在的路径?/p>

AM_INIT_AUTOMAKE(PACKAGE, VERSION) 

   q个宏是必须的,它描qC我们要生成的Y件包的名字及其版本号QPACKAGE是Y件包的名字,VERSION是版本号。当你用make dist命oӞ它会l你生成一个类似helloworld-1.0.tar.gz的Y件发行包Q其中就有对应的软g包的名字和版本号?/p>

AC_PROG_CC

  q个宏将查系l所用的C~译器?

AC_OUTPUT(FILE)

  q个宏是我们要输出的Makefile的名字?/p>

  我们在用automakeӞ实际上还需要用到其他的一些宏Q但我们可以用aclocal 来帮我们自动产生。执行aclocal后我们会得到aclocal.m4文g?/p>

  产生了configure.in和aclocal.m4 两个宏文件后Q我们就可以使用autoconf来生configure文g了?/p>

  5?Makefile.am

  Makefile.am是用来生成Makefile.in的,需要你手工书写。Makefile.am中定义了一些内容:

AUTOMAKE_OPTIONS

  q个是automake的选项。在执行automakeӞ它会查目录下是否存在标准GNU软g包中应具备的各种文gQ例如AUTHORS、ChangeLog、NEWS{文件。我们将其设|成foreignӞautomake会改用一般Y件包的标准来查?/p>

bin_PROGRAMS

  q个是指定我们所要生的可执行文件的文g名。如果你要生多个可执行文gQ那么在各个名字间用I格隔开?

helloworld_SOURCES

  q个是指定?#8220;helloworld”时所需要的源代码。如果它用到了多个源文gQ那么请使用I格W号它们隔开。比如需要helloworld.hQhelloworld.c那么请写成helloworld_SOURCES= helloworld.h helloworld.c?/p>

  如果你在bin_PROGRAMS定义了多个可执行文gQ则对应每个可执行文仉要定义相对的filename_SOURCES?/p>

  6?automake

  我们使用automake --add-missing来生Makefile.in?/p>

  选项--add-missing的定义是“add missing standard files to package”Q它会让automake加入一个标准的软g包所必须的一些文件?/p>

  我们用automake产生出来的Makefile.in文g是符合GNU Makefile惯例的,接下来我们只要执行configureq个shell 脚本可以生合适的 Makefile 文g了?/p>

  7?Makefile

  在符合GNU Makefiel惯例的Makefile中,包含了一些基本的预先定义的操作:

make

  ҎMakefile~译源代码,q接Q生成目标文Ӟ可执行文件?/p>

make clean

  清除上次的make命o所产生的object文gQ后~?#8220;.o”的文Ӟ及可执行文g?/p>

make install

  编译成功的可执行文件安装到pȝ目录中,一般ؓ/usr/local/bin目录?/p>

make dist

  产生发布软g包文Ӟ即distribution packageQ。这个命令将会将可执行文件及相关文g打包成一个tar.gz压羃的文件用来作为发布Y件的软g包?/p>

  它会在当前目录下生成一个名字类?#8220;PACKAGE-VERSION.tar.gz”的文件。PACKAGE和VERSIONQ是我们在configure.in中定义的AM_INIT_AUTOMAKE(PACKAGE, VERSION)?/p>

make distcheck

  生成发布软g包ƈ对其q行试查,以确定发布包的正性。这个操作将自动把压~包文g解开Q然后执行configure命oQƈ且执行makeQ来认~译不出现错误,最后提CZ软g包已l准备好Q可以发布了?/p>

===============================================
helloworld-1.0.tar.gz is ready for distribution
===============================================
make distclean

  cMmake cleanQ但同时也将configure生成的文件全部删除掉Q包括Makefile?/p>

  五、结束语

  通过上面的介l,你应该可以很Ҏ地生成一个你自己的符合GNU惯例的Makefile文g及对应的目文g?/p>

  如果你想写出更复杂的且符合惯例的MakefileQ你可以参考一些开放代码的目中的configure.in和Makefile.am文gQ比如:嵌入式数据库sqliteQ单元测试cppunit?



jinfeng_wang 2007-05-28 12:37 发表评论
]]>
Window+GCC+CDT用Eclipse開發C、C++ (zz)http://www.tkk7.com/jinfeng_wang/archive/2007/05/28/120421.htmljinfeng_wangjinfeng_wangMon, 28 May 2007 04:00:00 GMThttp://www.tkk7.com/jinfeng_wang/archive/2007/05/28/120421.htmlhttp://www.tkk7.com/jinfeng_wang/comments/120421.htmlhttp://www.tkk7.com/jinfeng_wang/archive/2007/05/28/120421.html#Feedback0http://www.tkk7.com/jinfeng_wang/comments/commentRss/120421.htmlhttp://www.tkk7.com/jinfeng_wang/services/trackbacks/120421.htmlhttp://www.javaworld.com.tw/jute/post/view?bid=10&id=53262&sty=1&tpg=1&age=0


Eclipse除了可以開發Java之外Q還支援了許多語aQ現在先介紹
C、C++的開發環境設定,以後有機會再介紹其它的。Enjoy itQ?

OSQWindows XP Professional SP1
使用版本QEclipse 2.1.2

一.首先要下載CDTQEclipse 2.1.2使用者,請下載這項Q?
CDT 1.2 Full for Windows R2.1.1 1.2.0 GA - Full - Windows?
Eclipse 2.1.3使用者請下載QCDT 1.2.1?
Eclipse 3.0 M7使用者請下載QCDT 2.0 M7?
Eclipse 3.0 M8使用者請下載QCDT 2.0 M8?
Eclipse 3.0 M9使用者請下載QCDT 2.0 M9?
下載E址Q?a class=ilink target=_blank>http://www.eclipse.org/cdt/

安裝Q將解壓^後的features、plugins整個資料夾複製到Eclipse安裝資料
裡,重新開啟Eclipse卛_?

?下載可在Windows上用的GNU C、C++R譯器,這裡要下載的是:MinGW?
Download頁面很長的一Ԍ請選擇這個版本:
MinGW bin MinGW-3.1.0-1.exe 14863 kb Sep 15, 2003 11:14
下載E址Q?a class=ilink target=_blank>http://www.mingw.org/download.shtml

安裝Q安裝目錄選C槽,然後狂點下一?Next)p了。安裝完後\徑是?
?>C:\MinGW?

?先在Command Line模式下測試編譯與埯。先C:\MinGW\bin底下?
mingw32-make.exe更名為make.exeQ因為待會在Eclipse使用時它預設
會抓pȝ裡make這個檔名而不是mingw32-make?

(a:如果不更名或是還有其他makeE式時,也可以在E後的Eclipsea定
中,在make targets view的地方,新增一個task時,build command 取消
use default , 使用 mingw32-makeQ或在project properties->make project ->
make 改為 mingw32-make )
-- ?strong> snpshu 補充?/font>

在環境變數裡加入下列a定Q?
PATH Q?C:\MinGW\bin; (如果pȝ已經有裝其它C/C++R譯器,請把C:\MinGW\bin加在最前面?
LIBRARY_PATH QC:\MinGW\lib
C_INCLUDE_PATH QC:\MinGW\include
CPLUS_INCLUDE_PATH QC:\MinGW\include\c++\3.2.3;C:\MinGW\include\c++\3.2.3\mingw32;
C:\MinGW\include\c++\3.2.3\backward;C:\MinGW\include

先用文字編輯器R寫測試用的原始檔,檔名Qmain.cpp?
1
2
3
4
5
6
7
8
#include <iostream>
            using namespace std;
             
            int main(void) {
            cout << "Can You Feel My WorldQ? ;
             
            return 0;
            }
            

在Command Line下編譯指令:
1
C:\g++ main.cpp -O3 -o hello
            

(O3的O是英文大??)
R譯成功後:便會產生hello.exe的執行檔?
埯畫面如下Q?
1
2
3
4
5
6
7
8
9
10
Microsoft Windows XP [版本 5.1.2600]
            (C) Copyright 1985-2001 Microsoft Corp.
             
            C:\Documents and Settings\Sungo>cd\
             
            C:\>g++ main.cpp -O3 -o hello
             
            C:\>hello
            Can You Feel My WorldQ?
            C:\>
            

a:-O3 旗標表示採最高級R譯最佛_Q編譯速度最慢,但產生的埯?
檔案會最,埯速度會最快;-o 旗標表示編譯完?.exe重新更名?

◎步驟一.開啟Eclipse後,首先先開啟C/C++用視景?
Windows->Open Perspective->C/C++ Development

◎步驟二.建立一個C++用的案?
File-New->Project->C++->Standard Make C++ Project
(接下來的步驟跟徏立一般的Java案一樣,皆採預設卛_)

◎步驟三.把我們剛剛寫的main.cpp import進來Q加到專案裡?
File->Import->File System->瀏覽C:\main.cpp

◎步驟四.建立一個makefile?
File->New->FileQ檔案名E填Qmakefile?不需打副檔名)

makefile內容如下Q?
1
2
all:
            g++  main.cpp -g -o run
            

注意Qmakefile^排要以Tab鍵作^排Q不能以I格4作縮排,
否則Build會有問題?/font>

◎步驟五.a定Make Targets?
Windows-Show View->Make Targets
在Make Targets視窗裡按滑鼠右鍵QAdd Build Target
Qname打:R譯。Build Target打:all?

◎步驟六.R譯?
在剛剛徏立的Make Targets "R譯" 上點滑鼠2下,x開始R譯Q?
此時我們可以發現hello.exe已經產生在我們專案下了。可在底?
C-Build視窗看到以下輸出i果Q?
1
2
make -k all
            g++  main.cpp -g -o run
            


◎步驟七. *.exe埯前設定。因為在Windows下RunQ所以要先作個設?
Q請開啟Project->Properties->C/C++ Make Project->Binary Parser頁面?
Binary Parser下拉式選單,ELF ParserҎPE Windows Parser?

◎步驟八.埯?
Run->Run as->C Local Application?
在底下Consloe視窗看到hello.exe的執行結果?

a:當原始檔有修改,要重新編譯時Q只要滑鼠雙擊我們在步驟?
所建立的Make Targets "R譯"Q即可Rebuilding?

jinfeng_wang 2007-05-28 12:00 发表评论
]]>
Splint User’s Manual(zz)http://www.tkk7.com/jinfeng_wang/archive/2007/05/25/120049.htmljinfeng_wangjinfeng_wangFri, 25 May 2007 09:59:00 GMThttp://www.tkk7.com/jinfeng_wang/archive/2007/05/25/120049.htmlhttp://www.tkk7.com/jinfeng_wang/comments/120049.htmlhttp://www.tkk7.com/jinfeng_wang/archive/2007/05/25/120049.html#Feedback0http://www.tkk7.com/jinfeng_wang/comments/commentRss/120049.htmlhttp://www.tkk7.com/jinfeng_wang/services/trackbacks/120049.htmlhttp://www.splint.org/manual/html/sec1.html



Splint[1] is a tool for statically checking C programs for security vulnerabilities and programming mistakes.  Splint does many of the traditional lint checks including unused declarations, type inconsistencies, use before definition, unreachable code, ignored return values, execution paths with no return, likely infinite loops, and fall through cases.  More powerful checks are made possible by additional information given in source code annotations.  Annotations are stylized comments that document assumptions about functions, variables, parameters and types.  In addition to the checks specifically enabled by annotations, many of the traditional lint checks are improved by exploiting this additional information.

 

As more effort is put into annotating programs, better checking results. A representational effort-benefit curve for using Splint is shown in Figure 1.  Splint is designed to be flexible and allow programmers to select appropriate points on the effort-benefit curve for particular projects.  As different checks are turned on and more information is given in code annotations the number of bugs that can be detected increases dramatically.

 

Problems detected by Splint include:

·      Dereferencing a possibly null pointer (Section 2);

·      Using possibly undefined storage or returning storage that is not properly defined (Section 3);

·      Type mismatches, with greater precision and flexibility than provided by C compilers (Section 4.1–4.2);

·      Violations of information hiding (Section 4.3);

·      Memory management errors including uses of dangling references and memory leaks  (Section 5);

·      Dangerous aliasing (Section 6);

·      Modifications and global variable uses that are inconsistent with specified interfaces (Section 7);

·      Problematic control flow such as likely infinite loops (Section 8.3.1), fall through cases or incomplete switches (Section 8.3.2), and suspicious statements (Section 8.4);

·      Buffer overflow vulnerabilities (Section 9);

·      Dangerous macro implementations or invocations (Section 11); and

·      Violations of customized naming conventions.  (Section 12).

 

 



Figure 1.  Typical Effort-Benefit Curve

 

Splint checking can be customized to select what classes of errors are reported using command line flags and stylized comments in the code.  In addition, users can define new annotations and associated checks to extend Splint’s checking or to enforce application specific properties (Section 10).

 

About This Document

This document is a guide to using Splint.  Section 1 explains how to run Splint, interpret messages and control checking.  Sections 2–13 describe particular checks done by Splint.  There are some minor dependencies between sections, but in general they can be read in any order.  Section 14 covers issues involving libraries and header file inclusion important for running Splint on large systems.

 

This document does not describe technical details of the checking.  For technical background and analysis of Splint’s effectiveness in practice, see the papers available at http://www.splint.org



jinfeng_wang 2007-05-25 17:59 发表评论
]]>
PCLint Qzz Q?/title><link>http://www.tkk7.com/jinfeng_wang/archive/2007/05/24/119598.html</link><dc:creator>jinfeng_wang</dc:creator><author>jinfeng_wang</author><pubDate>Thu, 24 May 2007 02:46:00 GMT</pubDate><guid>http://www.tkk7.com/jinfeng_wang/archive/2007/05/24/119598.html</guid><wfw:comment>http://www.tkk7.com/jinfeng_wang/comments/119598.html</wfw:comment><comments>http://www.tkk7.com/jinfeng_wang/archive/2007/05/24/119598.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.tkk7.com/jinfeng_wang/comments/commentRss/119598.html</wfw:commentRss><trackback:ping>http://www.tkk7.com/jinfeng_wang/services/trackbacks/119598.html</trackback:ping><description><![CDATA[<div id="nfjtflt" class=postTitle><a ><img height=13 src="http://blog.csdn.net/images/authorship.gif" width=15 border=0><u><font color=#0000ff> 【原创】VC中多文g工程的PCLint使用详解</font></u></a> </div> <div id="3h99b9t" class=postText> <p>2006-4-14 Lander 整理<br>介绍Q对于多个源E序文g且多个头文g目录的项目进行PCLint语法查?/p> <p>1.安装<br> 我用的是PC.Lint.v8.00e,是不用安装的版本?br> 解开到E:\PC.Lint.v8.00e目录Q可执行文g为Lint.exeQlint-nt.exe与其相同Q可能ؓNTq_用的Q在Win2000下都可运??br> 子目录lnt内是查的规则及选项文gQ这两种文g扩展名全?lnt?/p> <p>2.准备自己工程的选项文g<br> 在E:\PC.Lint.v8.00e\lnt下新建MyProj.lnt文本文gQ我们将自己工程的很多头文g目录Q在其中一一列出来,内容如下Q?br> <br> std.lnt/*注释Q包含的规则?或选项文g*/<br> env-vc6.lnt<br> /*下面为各头文件目?可以在字串中不要双引?可以有多?/<br> -i"C:\MyProj\IncludeA" -i"C:\MyProj\IncludeB" -iC:\MyProj\IncludeC<br> -iC:\MyProj\IncludeD<br> -e641//另一U注?/q是省略#641错误<br> 【注意】指明各头文件目录很重要。头文g各目录的名称可能在VC的Project\Project Settings\Project Options栏中Q?br>  /I "../Include/PS",可供借鉴(相对路径暂未试)?br>  当后面运行Lint时出现无法打开某个头文件时Q需要不断添加头文g所在目录的名称到本选项文g中?/p> <p>3.在VC中运行PCLintQ针对单个文件但需包含多个头文件目录)Q?br>    A 点击Tools/Customize/Tools出现定制H口<br>    B 在Menu contents中双M面的I白拦,输入拟新增的Tool名称QPCLint<br>    C 双击PClint,在Command中填入要调用?exe文g名:lint<br>      Arguments:中填入:-i"E:\PC.Lint.v8.00e\lnt" MyProj.lnt $(FilePath)<br>      【注意?(FilePath)q个字串是个宏名Q也可以通过点击双的三角箭头选择;可能查的本文件的路径加文件名Q?br>      不能?(FileName)!!!因ؓ它可能只是文件名而不带\径,导致用时说无法发?<br>      另外,MyProj.lntq个选项文g必须?(FilePath)之前?br>      Initial Directory:在Arguments中若缺?i"E:\PC.Lint.v8.00e\lnt"时将报无法找到各?lnt文gQ可在此<br>      栏填E:\PC.Lint.v8.00e\lnt来指定?br>      选中"Use Output Window" (q将使PCLintq行的结果在VC下方OutputH口中,双击行号q可以蟩到指定行)<br>    D 打开一个项目,让焦点位于某个源E序~辑H口Q点击Tools/pclint菜单卛_</p> <p>【注意】直到VC OutputH口中出现Tool returned code: Q才Toolq行完,若未q行完,可能在再点击PCLint时报错?/p> <p>4.|上搜到的VC环境多个文g同时Lint的方法,大致为找到各?c文gQ将各文件名lxargs传给lint来实现。但需要find,xargs{?br>命oQ似乎需要模拟unix环境的Y件支持中才有Q我装的Cygwin的环境中对find命o后的格式有问题,无法支持unix中的<br>find . -name *.c,故无法由此找到各?c文g名。但可以用Cygwin的ls命o来代替find?br> 【原Ҏ如下Q?br>   A 点击Tools/Customize/Tools出现定制H口<br>  B 在Menu contents中双ȝ白拦Q输入:PCLint-project<br>  C 双击PCLint-project,在Command:中填入:find<br>      Arguments:中填入:$(FileDir) -name *.c | xargs pclint -i"c:\unix\usr" -u std.lnt env-vc6.lnt<br>      选中"Use Output Window"<br>  D 打开一个项目,让焦点位于最层目前的一个Source Window中,点击Tools/PCLint-project菜单卛_</p> <p> 【方?如下Q?br>  A 点击Tools/Customize/Tools出现定制H口<br>  B 在Menu contents中双ȝ白拦Q输入:PCLint-Proj<br>  C 双击PCLint-Proj,在Command:中填入:ls<br>      Arguments:中填入:*.c |xargs lint -i"E:\PC.Lint.v8.00e\lnt" MyProj.lnt<br>      Initial Directory:本栏填写工程的一个源文g子目?保证在Arguments中?i"E:\PC.Lint.v8.00e\lnt")<br>      选中"Use Output Window"<br>  D 打开一个项目,让焦点位于最层目前的一个Source Window中,点击Tools/PCLint-Proj菜单卛_</p> <p> 【最单的Ҏ如下Q?br>  A 在MyProj.lnt末尾d一?*.c Q即目标为本目录下所?c文gQ?br>  B 点击Tools/Customize/Tools出现定制H口<br>  C 在Menu contents中双ȝ白拦Q输入:PCLint-Proj<br>  D 双击PCLint-Proj,在Command:中填入:lint<br>      Arguments:中填入:-i"E:\PC.Lint.v8.00e\lnt" MyProj.lnt<br>      Initial Directory:本栏填写工程的一个源文g子目?保证在Arguments中?i"E:\PC.Lint.v8.00e\lnt")<br>      选中"Use Output Window"<br>  E 打开一个项目,让焦点位于最层目前的一个Source Window中,点击Tools/PCLint-Proj菜单卛_</p> <p>【注意】上q方法中的ls,xargs{命令位于Cygwin的目录中Q需要将路径d到系l的PATH中:<br>  "我的电脑"(叛_鼠标)->"属?->"高"->"环境变量"->"pȝ变量"->"Path"<br>    加入"C:\cygwin\bin"重启生效?br> ls *.c同时找?c文g?cpp文gQ但是也会将非工E所需?c文g~译q来Q需要手工把文g转走?br> 另外Q这U方法一ơ只能Lint一个目录,每完成一个目录就要重新设|Initial Directoryؓ新的要检查的目录?/p> <p>5.在DOSH口中对一个目录多个文件进行Lint<br>1)ZCygwin<br>cd C:\MyProj\SrcA\<br>ls *.c | xargs lint -i"E:\PC.Lint.v8.00e\lnt" MyProj.lnt >> LintOutput.txt<br>【注意】ls *.c 也可以用DOS命odir *.c/B来替换,/B的意思是仅列出各文g名?gt;>LintOutput.txt的意思是Lintl果输出?br>LintOutput.txt文g中?br>2)无Cygwin支持<br>cd C:\MyProj\SrcA\<br>dir *.c /B<br>所有列出的.c文g名称复制到E:\PC.Lint.v8.00e\lnt\MyProj.lnt中,内容如下Q?br> std.lnt/*注释Q包含的规则?或选项文g*/<br> env-vc6.lnt<br> /*下面为各头文件目?可以在字串中不要双引?可以有多?/<br> -i"C:\MyProj\IncludeA" -i"C:\MyProj\IncludeB" -iC:\MyProj\IncludeC<br> -iC:\MyProj\IncludeD<br> -e641//另一U注?/q是省略#641错误<br> a.c //指定要Lint的文?br> b.c<br> c.c<br> 最后几行指定的要Lint之文件也可以用通配W,如:<br> *.c<br>然后直接q行 lint -i"E:\PC.Lint.v8.00e\lnt" MyProj.lnt >> LintOutput.txt</p> </div> <br><br><br><br>===================================<br> <div class="h3r9rzp" id=art style="MARGIN: 15px" width="100%"> <p>LINT工具是一UY件质量保证工P许多国外的大型专业Y件公司,如微软公司,?nbsp; <br>把它作ؓE序查工P在程序合入正试版本或交付试之前一定要保证通过了LINT?nbsp; <br>Q他们要求Y件工E师在用LINT时要打开所有的~译开养I如果一定要关闭某些开养I  <br>那么要给出关闭这些开关的正当理由?nbsp; <br><br>  可想而知Q如果从我们~码后第一ơ编译程序时׃用LINT来检查程序,q且保证?nbsp; <br>除所有的LINT告警Q我们就不会遇到象今天这么多的告警信息。即使在今天Q我们如果能  <br>抽出一定的_֊来消除程序中的LINT告警Q以后再l持q种无告警状态就是很Ҏ的了?nbsp; <br>我们E序质量的提高也是不a而喻的?nbsp; <br><br>  PC-LINT是GIMPEL SOFTWARE公司的品,其中的内Ҏ非常q泛的,光是选项有30  <br>0多个Q涉及到E序~译及语法用中的方斚w面。本培训材料旨在引D者入门,学会  <br>PC-LINT的基本用方法,h砖引玉的作用Q能让读者从q里hl箋ȝI如何娴熟地  <br>使用PC-LINT的各U选项Q能让它充分为我们的开发工作服务?nbsp; <br><br>1.概述  <br>  如果要给LINT工具下一个Ş象点的定义,那就是:一U更加严格的~译器。它不仅?nbsp; <br>以象普通编译器那样查出一般的语法错误Q还可以查出那些虽然完全合乎语法要求Q?nbsp; <br>但很可能是潜在的、不易发现的错误。请看下面的例子Q?nbsp; <br>1Q?nbsp; <br>2Qchar *report( int m, int n, char *p )  <br>3Q{  <br>4Q?nbsp;int result;  <br>5Q?nbsp;char *temp;  <br>6Q?nbsp;long nm;  <br>7Q?nbsp;int i, k, kk;  <br>8Q?nbsp;char name[11] = "Joe Jakeson";  <br>9Q?nbsp; <br>10Q?nbsp;nm = n * m;  <br>11Q?nbsp;temp = p == "" ? "null" : p;  <br>12Q?nbsp;for( i = 0; i 13Q?nbsp;{  <br>14Q?nbsp;k++;  <br>15Q?nbsp;kk = i;  <br>16Q?nbsp;}  <br>17Q?nbsp; <br>18Q?nbsp;if( k== 1 ) result = nm;  <br>19Q?nbsp;else if( kk > 0 ) result = 1;  <br>20Q?nbsp;else if( kk < 0 ) result = -1;  <br>21Q?nbsp; <br>22Q?nbsp;if( m == result ) return( temp );  <br>23Q?nbsp;else return( name );  <br>24Q}  <br>  上面的代码用一般的~译器编译是一D|效的代码Q但是用PC-LINT~译׃有几个告  <br>警。首先第8行向name数组赋值时丢掉了nul字符Q第10行的乘法_ֺ会失准,W?1行的?nbsp; <br>较有问题Q第14行的变量k没有初始化,W?5行的kk可能没有被初始化Q第22行的result?nbsp; <br>有可能没有被初始化,W?3行返回的是一个局部对象的地址。这D代码在大部分编译器?nbsp; <br>是可以顺利编译通过的,l箋查找其中的错误就要靠人工调试E序Q如果程序很大,q将  <br>是一烦琐的工作Q没有h可以保证能找出所有的q类问题Q但PC-LINT只通过一ơ简单的  <br>~译可做到Q显然ؓ我们节省了大量的开发时间?nbsp; <br><br>  下面p我们看看如何安装使用PC-LINT?nbsp; <br>2.如何安装PC-LINT  <br>  PC-LINT的Y件的安装q程比较复杂Q选项较多Q下面根据安装过E,逐条说明每一?nbsp; <br>的含义?nbsp; <br>0Q如果是zip文gQ将ZIP安装文g展开到目录C:\lint.ins下,q入COMMAND PROMPTQ先  <br>q行目录映射 subst g: c:\lint.insQ然后{到G: , 执行install。其他步骤和下面的从  <br>软盘安装是一L?nbsp; <br><br>1Q在A:驱插入PC-LINT安装盘,输入A:\>install命oQ进入开始安装栏Q按L键l,  <br>q入PC-LINT介绍栏,再按L键l?nbsp; <br>2Q进入环境选择栏,q一栏中有三个选项Q?nbsp; <br>Windows NT/Windows 95  <br>MS-DOSQDOS extendedQ?nbsp; <br>OS/2Q?2bitQ?nbsp; <br>如果计算机安装了WIN95、WIN97、WIN98或WINNT要选择Windows NT/Windows 95Q如?nbsp; <br>只有DOS则选择DOS?nbsp; <br>3Q进入安装目录选择栏,它推荐的是C:\>LINTQ如不想安装在这个目录下Q可输入自己?nbsp; <br>要安装的目录Q然后按回R认Q如果要安装的目录不存在Q它会提CZؓ你徏立这个目?nbsp; <br>。我们这里选C:\>LINT  <br>4Q选择安装盘所在的盘驱动器,我们q里选A:  <br>5Q判断是否要选择多种~译器或~译库的配置Q如果要对不同编译环境下的程序进行L  <br><br>INTQ则选YESQ否则选NO。然后回车确认?nbsp; <br>6Q这时看C个编译器列表Q在q个表中选择自己使用的编译器Q如果表中没有自׃?nbsp; <br>的编译器Q可选择通用~译器:Generic Compilers。按回R认。这个选项会体现在co-  <br>xxx.lnt文g中?nbsp; <br>7Q接着安装E序会让你选择一个的内存模型Q可以根据自q序区和数据区的实际大?nbsp; <br>择一个恰当的内存模型。如果CPU?2?8KpdQ则要选择Q?2-bit Flat Module?nbsp; <br>内存模型的选项会体现在STD.LNT文g中?nbsp; <br>8Q选完内存模型后,会看C个库cd的列表,在这里选择一个或多个~译时用的库?nbsp; <br>q个选项会体现在LIB-xxx.LNT文g中?nbsp; <br>9Q接着是让你选择Z用C++~程提出q重要徏议的作者,选择的某作者后Q他提出的编  <br>E徏议方面的选项被打开。与作者选择有关的选项会体现在AU-xxx.LNT文g中?nbsp; <br>10Q下一步是讄包含文g目录。有两种选项Q第一U是使用环境变量INCLUDEQ环境变?nbsp; <br>在批处理文g中设|,环境变量后每个目录用分号隔开Q例如可设成“INCLUDE=C:\MRI\M  <br>CC68K;D:\LAP\SRC\INC”。第二种选项是?i选项Q?i选项体现在STD.LNT文g中,每个  <br>目录前以-I引导Q目录间以空格分隔,例如可设?#8220;-IC:\MRI\MCC68K -ID:\LAP\SRC\INC  <br>”。如果选择使用-I选项Q安装程序会接着让你输入包含文g所在的目录?nbsp; <br>11Q?nbsp;如果前面选择了用多个编译环境,q里会问你是否选择更多的编译环境,如果?nbsp; <br>YESQ将会从W?步开佉K复。如果选NO则会l束~译器选择?nbsp; <br>12Q接下来会准备产生一?nbsp;反映全局~译信息昄情况的选项文gOPTIONS.LNTQ该?nbsp; <br>件的产生方式有两U,一U是安装E序对几个核心选项逐一解释q提问你是否取消该选项  <br>Q如果你选择取消Q则会体现在OPTIONS.LNT文g中,具体体现方式是在该类信息~码前加  <br>-eQ后面第13~18步是逐一选择核心选项的过E。如果选择W二U选择方式Q安装文件会?nbsp; <br>生成一个空的OPTIONS.LNT文gQ等你以后在实际应用时加入必要的选项?nbsp; <br>13Q是否关闭赋值时的布测试告警,如:if(a=f()){...  <br>14Q是否关闭赋值时的有W号量和无符号量间的不匹配告警,通常情况下,q种赋g?nbsp; <br>带来问题Q选择关闭该告警信息的同时Q其他类型的有符号量和无W号量间混合操作的告  <br>警仍然是打开的?nbsp; <br>15Q当把一个整形量赋值给一个比它短的量Ӟ后者会丢失_ֺQ例如把一个INT量赋值给  <br>l一个CHAR量。本步是让你选择是否关闭该类告警?nbsp; <br>16Q是否关闭左UdW号量的告警。通常PC-LINT会对所有带W号量的Ud产生告警Q但?nbsp; <br>UM般是׃同的CPU来确定是否将W号位移入,左移一般是不会产生什么问题的Q所以可  <br>以选择关闭该告警?nbsp; <br>17Q在一个C函数被定义或声明前调用它Qƈ不L会生错误,在这里可以选择是否关闭  <br>该告警选项。该选项对C++E序不v作用?nbsp; <br>18Q是否关?#8220;调用不存在的函数原型”告警。有些程序员不愿遵守严格的函数原形定?nbsp; <br>U定Q但PC-LINT会在调用一个没有定义的函数原型时生一个告警,在这里可以选择关闭  <br>该告警?nbsp; <br>19Q通过上面的步骤确定OPTIONS.LNT文g的Ş式后Q接着是选择~译环境。PC-LINT提供  <br>了集成在多种开发环境中工作的功能,例如可集成在VC、BC、Source Insight中。假如我  <br>们在q里选择Source Insight。选择后安装程序会l箋问你是否q选择其它的环境,可根  <br>据自己应用的实际情况选择一U或多种开发环境。开发环境的选择情况记录在env-xxx.ln  <br>t文g中?nbsp; <br>20Q安装程序会生成一个LIN.BAT文gQ该文g是运行PC-LINT的批处理文gQؓ了该文  <br>件能在Q何\径下q行Q安装程序提供了两种Ҏ供你选择。第一U方法是让你选择把LI  <br>N.BAT拯CQ何一个PATH目录下,在安装结束运行LCOPY.BAT文gӞ会把LIN.BAT拯?nbsp; <br>你指定的目录。第二种Ҏ是生成一个LSET.BAT文gQ在每次使用PC-LINT前先q行它来?nbsp; <br>|\径,或者把LSET.BAT文g的内Ҏ贝到AUTOEXEC.BAT文g中?nbsp; <br>21Q在安装E序执行完后W一件事是在你安装的目录下执行LCOPY.BAT文g。它会从安装?nbsp; <br>拯一些文件拷贝到安装目录下,q根据你在安装过E中的选择来设|文件中的参数?nbsp; <br><br>3.LINT 一个C文g  <br>3.1用命令行方式q行LINT  <br>如果使用LIN.BAT批处理文件进行LINTQ在LINT前要先看一下该批处理文件中的内容,里面  <br>包含了LINT-NT命o和命令选项Q可以根据自q要求来修攏V增减选项。我们看刎ͼ在这  <br>个批命o中嵌套了一个std.lnt文gQ在std.lnt文g中还嵌套了co.lnt、options.lnt和l  <br>ib-stl.lnt文gQ原则上*.lnt文g是可以无限制嵌套Q该cL件中一般都是了LINT的选项  <br>Q可通过修改q些文g来修改LINT选项Q选项是按照从左到右的序执行的。可执行下面  <br>命o行:  <br>C:\abc\src>lin alpha.c beta.c gamma.c  <br>通常对于由多个C模块l成的程序,最好先分别Ҏ个C模块单元q行LINT查,做单元LI  <br>NT时可如下q行Q?nbsp; <br>C:\abs\src>lin -u alpha.c  <br>其中-u是单元选项Q?u后可以关闭一些检查多模块时会产生的告警,例如“函数未被  <br>使用”?#8220;函数没有定义”{?nbsp; <br>也可以不使用LIN.BAT批处理文Ӟ而直接用LINT命o。在DOS环境下LINT命o为LINT.E  <br>XEQ在Windows95/NT环境下ؓLINT-NT.EXEQ在OS2环境下ؓLINT-OS2.EXE。直接用LINT  <br>命o要注意的一Ҏ要在使用前预先设|LINT目录所在\径,最好的Ҏ是把该\径加?nbsp; <br>AUTOEXEC.BAT文g中。其它的使用Ҏ与用批处理文g相同。例如:  <br>C:\abs\src>lint-nt -ic:\lint\ std.lnt -os(_lint.tmp) *.c  <br>3.2用开发环境进行LINT  <br>也可以用开发环境来执行LINT操作Q一般开发环境都支持q行可执行文Ӟ但不一定支  <br>持运行批处理文gQ下面用Source Insight , Ultra Edit, MSVC 6.0 来D例说明如何在  <br>开发环境下q行LINT?nbsp; <br>3.2.1 在Source Insight中集?nbsp; <br>如果你在安装q程中选定了用某个开发环境,安装E序会在你安装的目录下生成一个en  <br>v-xxx.lnt的文Ӟ例如选择了Source Insight׃有一个env-si.lnt文g。用~辑器打开  <br>该文Ӟ在该文g开始的注释中说明了如何PC-LINT功能集成在开发环境中Q集成在Sou  <br>rce Insight中的q程如下Q?nbsp; <br>1Q从Options菜单中选择“Custom Commands”命oV?nbsp; <br>2Q在Name栏中输入“PC-lint ”Q原则上q个名称可以随便P只要你能搞清楚它的含?nbsp; <br>可以了?nbsp; <br>3Q在Run栏中输入“c:\lint\lint-nt -u -ic:\lint std env-si %f”其中c:\lint是你P  <br>C-LINT的安装目录?nbsp; <br>4Q在Output栏中选择“Iconic Window”?#8220;Capture Output”?nbsp; <br>5Q在Control栏中选择“Save Files First”?nbsp; <br>6Q在Source Links in Output栏中选择“Parse Links in Output”?#8220;FileQthen Lin  <br>e”?nbsp; <br>7Q在Pattern栏中输入“^\([^ ]*\) \([0-9]+\)”?nbsp; <br>8Q点Add键加入该命o。如下图Q?nbsp; <br>9Q用时Q在Source Insight下打开要LINT的文Ӟ打开Options菜单中的“Custom Com  <br>mands”命o,?#8220;Command”栏中选择“PC-lint unit check”命oq行卛_?nbsp; <br>注意到我的Run一栏的参数和上面的提示不一P其实我的其他古怪参数都攑ֈc:\lint\s  <br>td.lnt中了。请注意Q不Z怎样配置参数一定不要忘Csi-env.lnt包含在你的配|?nbsp; <br>文g里,否则无法进行错误信息和E序的自动对应了?nbsp; <br>Z使用方便Q你q可以配|一下Menu按钮Q将它加到系l菜0单里Q这属于一般性的  <br>Source Insight应用Q笔者就不在此赘qC?nbsp; <br>W二W者在NT中用Source InsightӞ好象集成不了Q原因暂时不明了。上面的例子?nbsp; <br>WIN 95下测试成功?nbsp; <br>如果要修改LINT选项Q可直接在Run栏中修改Q也可专门编辑一?.lnt文g攑֜c:\lint?nbsp; <br>录下Qƈ该文g名加入Run栏中Q和命o行方式是一L?nbsp; <br>3.2.2在Ultra Editor中集?nbsp; <br>选取 Menu | Advanced | Tool Configuration ... Q?nbsp;昄如下图:  <br>1Q点?#8220;Insert",  <br>2Q在command line:中填写:c:\lint\lint-nt c:\lint\std.lnt %f  <br>3Q在Menu Item中填写:PC-LINT  <br>4Q在Command Output中选择Q?nbsp;(x) Output to List Box ?nbsp;(x) Capture Output  <br>5Q点?OK"  <br>如图所C的配置W者在UE6.0 / NT 4.0 下测试成功?nbsp; <br>3.2.3 在MSVC 6.0中集?nbsp; <p>//q个好ɘq?br>基本原理是一LQ?nbsp; <br>1Q选取 menu | tools | customize.....  <br>2Q选取 Tools Tab:  <br>3Q点按主对话框上方的虚线方?nbsp;New a tool item  <br>4Q输?nbsp;name: PC-LINT  <br>5Q输?nbsp;Command: c:\lint\lint-nt.exe  <br>6Q输?nbsp;Arguments: c:\lint\std.lnt $(FilePath)  //注:替std.lnt为lnt\env-vc6.lnt<br>7) 选择 (x) Use Output Window  <br>8QClose  <br>完成后,在tools菜单下就会有一PC-LINT选项?nbsp; <br>下面是笔者在VC6 / Win NT 4.0 的情况下的TOOL配置图:  <br>3.3LINT选项  <br>LINT选项可以攑֜注释中,例如Q?nbsp; <br>/*lint option1 option2 ... optional commentary */  <br>//lint option1 option2 ... optional commentary  <br>选项间要以空格分开Qlint命o一定要写Qƈ且紧跟在/*?/后面Q不能有I格。如?nbsp; <br>选项qg操作W和操作数的部分l成Q例?esym(534, printf, scanf, operat or  <br>new)Q其中最后一个选项是operator newQ那么在operator和new中间只能有一个空  <br>根{?nbsp; <br>选项q可以放在宏定义中,例如Q?nbsp; <br>#define DIVZERO(x) /*lint -save -e54 */ ((x) /o) /*lint -restore */  <br>LINT的选项很多共有300多种Q大体可分ؓ以下几类Q?nbsp; <br>1Q错误信息禁止选项  <br>该类选项是用于禁止生成某c错误信息的选项Q最常用的是-e?eQ?e是禁止生成某c错  <br>误信息,+e是恢复生成某c错误信息。运行lint目录下的msg.exe可以得到msg.txt文gQ?nbsp; <br>q个长达5000行的文g包含了所有的错误信息号和解释?nbsp; <br>-w 对于所有大于别的告警信息都不昄?nbsp; <br>-wlib()对于所有大于别的关于库函数数的告警信息都不显C。我们可以用-wlib(0)来屏  <br>蔽所有的库函数的告警信息Q?wlib(1)只显C库函数中的句法错误?nbsp; <br>-esym(#,) 可以屏蔽对于特定W号的某告警信息?nbsp; <br>2Q变量类型大选项  <br>不同的目标机、编译系l变量类型的的大(如短整Ş变量、整形变量等Q会有所不同Q?nbsp; <br>该类选项用于为目标机讄变量cd的大。由于默认的讄与大部分的编译器是匹配的  <br>Q这些专门的讄通常情况下是不需要的Q只在特别的目标机结构中才用。例如一个M680  <br>00目标机,它的intcd和指针类型通常?2bit的,q时你应该用选项Q?si4  <br>-sp4。这些尺寸参数的当前值可以通过help屏来获得Q例如可以输入以下命令行Q?nbsp; <br>lin -si4 -sp4 Q?nbsp; <br>3Q冗长信息选项  <br>冗长信息指的是LINTq程中生的一些与~译q程有关的信息,而不是真正的告警信息?nbsp; <br>错误信息{。是否生成这些信息可以通过-v?v选项来决定?v是生成这些信息,-v是关  <br>闭这些信息,q组选项中除+v外,其它所有选项都可以关?v选项?nbsp; <br>4Q标记选项  <br>?f?+f?f?-f开头的选项是标记选项。他们的逻辑含义分别如下Q?nbsp; <br>+f...Q通过把标志置?而把它置为ON  <br>-f...Q通过把标志置?而把它置为OFF  <br>++f...Q标志增1  <br>--f...Q标志减1  <br>后面两个用于你想在局部把一个标志置为ON的情况,而不影响全局讄。例如你可以q样  <br>使用Q?nbsp; <br>/*lint ++flb */  <br>int printf( );  <br>/*lint --flb */  <br>标记选项的种cd多,基本含义是用于打开或关闭某c语法情况用,例如允许使用~写  <br>l构体名Uͼ允许使用无名联合体,把所有模块当作C++~译{?nbsp; <br>5Q消息显C选项  <br>消息昄选项用于定义消息输出格式。主要有消息高度选项、消息宽度选项、消息格式?nbsp; <br>等?nbsp; <br>6Q其它选项  <br>其它选项中的U类很多Q各U类间差异很大,在这里就不一一介绍了,大家看一看?nbsp; <br>PC-LINT》一书,W五章有ҎU选项的详l说明。lint本n也有一些说明信息, lint-n  <br>t 2> lint.txt 然后狂按几个回R可以生成一个lint选项的说明文件?nbsp; <br>4.LINT一个工E下的多个C文g  <br>4.1Z要LINT多个C文g  <br>在程序编码初期,我们兛_的可能只是单个C模块U中的语法问题,{到~程后期Q对于由  <br>多个C模块l成的程序,我们希望了解当把多个模块q接在一起后是否q有存在于模块间?nbsp; <br>语法问题。这时编译器虽然能给Z些告警,但PC-LINT的连接能l出更多的告警。还有当  <br>我们能保证其中的几个模块相对E_Q而另外几个模块仍有问题时可以先将几个E_的模  <br>块编译连接成一个目标文Ӟ文g每次修改完成后先单独~译Q然后连接入ȝ目标文g  <br>?nbsp; <br>4.2如何LINT一个工E下的多个C文g  <br>象我们^时用的~译工具一PPC-LINT在编译连接多个C文g时也会先把每个C文g~译  <br>生成中间的目标文?.lobQ然后再所有的LOB文gq接在一赗LOB是Lint Object Mod  <br>ule的羃写。这个文件中包含了一个C或C++模块的所有外部信息。生成LOB文g时有三种?nbsp; <br>要注意Q第一U是-uQ如果要LINT生成LOB文gQ就一定要?u选项Q第二种?zero?nbsp; <br>-zero(500)选项Qؓ了保证LOB文g在模块存在错误的情况下也能生成,׃定要加这个?nbsp; <br>;W三U是-oo[(filename)]Qfilename是生成的LOB文g的名Uͼ?oo后面Q可加,?nbsp; <br>可不加,如不加,则LOB文g名与原C模块的名U相同,例如Q?nbsp; <br>lint -u alpha.c -oo(a1)  <br>生成的LOB文g名ؓQa1.lob  <br>lint -u alpha.c -oo  <br>生成的LOB文g名ؓQalpha.lob  <br>LINT一个工E下的多个C模块Q在用户的源E序目录下一般需要三个文Ӟ 一个选项文g  <br>Q?.lntQ、一个批处理文gQ?.batQ和一个MAKEFILE文gQ?.makQ。下面一一讲述如何  <br>制作q些文g?nbsp; <br>1Q选项文gQ?.lntQ?nbsp; <br>选项文g在前面也提到q,你可以把你LINT每个C文g时时用到的所有公共选项|列在该?nbsp; <br>件中Q选项生效的顺序按照从左到叻I从上C的原则。该cL件可以层层嵌套,嵌套?nbsp; <br>层数没有限制。例如make.lnt文gQ?nbsp; <br>-iC:\lint  <br>std.lnt  <br>+os(temp)  <br>-e46  <br>+vm  <br>-zero  <br>2Q批处理文gQ?.batQ?nbsp; <br>制作批处理文件时要注意要在该文g中调用TCMAKE.EXE文g和MAKEFILE文gQ例如lintma  <br>ke.mak文gQ?nbsp; <br>@echo Lint Making 'makelap':  <br>tcmake -flintmake.mak  <br>@echo End of making  <br>3QMAKEFILE文gQ?.makQ?nbsp; <br>MAKEFILE使用的TCMAKE的语法,和我们^时开发编译时使用的MAKEFILE文g语法格式一?nbsp; <br>Q例如下面的lintmake.mak文gQ?nbsp; <br>MCCPATH = c:\mcc68k  <br>OPTION = -u make.lnt -oo  <br>GLOBLE = os.h l2lap.h  <br>mail_depend = $(GLOBLE) q931.h mail.h  <br>lapmain_depend = $(GLOBLE) l1pubdef.h q931.h mail.h  <br>lapos_depend = $(GLOBLE)  <br>fhdlc1_depend = $(GLOBLE) cpuhdlc.h bd_prar.h q931.h  <br>OBJ = mail.lob lapmain.lob lapos.lob fhdlc1.lob  <br>project.lob : $(OBJ)  <br>lint-nt make.lnt -e768 -e769 *.lob  <br>mail.lob: mail.c $(mail_depend)  <br>lint-nt $(OPTION) mail.c  <br>lapmain.lob: lapmain.c $(lapmain_depend)  <br>lint-nt $(OPTION) lapmain.c  <br>lapos.lob: lapos.c $(lapos_depend)  <br>lint-nt $(OPTION) lapos.c  <br>fhdlc1.lob: fhdlc1.c $(fhdlc1_depend)  <br>lint-nt $(OPTION) fhdlc1.c  <br>4.3单的LINT多个文g  <br>假设我们的工E不复杂Q我们可以负担v每次都将所有的文g都lint一遍的开销Q也可以  <br>不用上面的正规用法。笔者在实践中发玎ͼ所有的*.c文g攑֜一个lint命o中,同样  <br>能完成lint整个工程的目的?nbsp; <br>如:  <br>lint-nt c:\lint\std.lnt AllMySource.lnt  <br>在AllMySource.lnt中包括你的工E中的所有源文gQ?nbsp; <br>a1.c  <br>a2.c  <br>a3.c  <br>需要注意的是,在std.lnt文g中就不需?u选项了。因为我们已l提供了所有的信息  <br></p> <div></div> </div> <img src ="http://www.tkk7.com/jinfeng_wang/aggbug/119598.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.tkk7.com/jinfeng_wang/" target="_blank">jinfeng_wang</a> 2007-05-24 10:46 <a href="http://www.tkk7.com/jinfeng_wang/archive/2007/05/24/119598.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>[C++]static全局变量/全局变量Qstatic函数/普通函敎ͼ函数中static变量/函数中的变量Q类中的static成员变量/普通类成员变量 (zz)http://www.tkk7.com/jinfeng_wang/archive/2007/05/22/119155.htmljinfeng_wangjinfeng_wangTue, 22 May 2007 08:32:00 GMThttp://www.tkk7.com/jinfeng_wang/archive/2007/05/22/119155.htmlhttp://www.tkk7.com/jinfeng_wang/comments/119155.htmlhttp://www.tkk7.com/jinfeng_wang/archive/2007/05/22/119155.html#Feedback0http://www.tkk7.com/jinfeng_wang/comments/commentRss/119155.htmlhttp://www.tkk7.com/jinfeng_wang/services/trackbacks/119155.htmlhttp://blog.csdn.net/duckur/archive/2005/11/05/523545.aspx



static Global variable: 文g作用域:只在声明的文件中有效Q其他源文g中不可见Q同时有了static的生命周?br>Global variable:文g作用域:可以加上extern 声明为外部变量,跨文件作用域

static (Global) Function: 有文件作用域Q只在本文g中?br>Global Function:无文件作用域

static Member (in Function) variable:函数调用完成后,变量保存状态,再次调用函数Q不会重新分配空?br>Member(in Funcition) variable:函数内的生命周期

static Member(in Class) variable: 属于c范_
Member(in Class) variable:属于cL生的特定对象Q生命周期和对象一?/p>

jinfeng_wang 2007-05-22 16:32 发表评论
]]>
c/c++ file templatehttp://www.tkk7.com/jinfeng_wang/archive/2007/05/22/119105.htmljinfeng_wangjinfeng_wangTue, 22 May 2007 05:23:00 GMThttp://www.tkk7.com/jinfeng_wang/archive/2007/05/22/119105.htmlhttp://www.tkk7.com/jinfeng_wang/comments/119105.htmlhttp://www.tkk7.com/jinfeng_wang/archive/2007/05/22/119105.html#Feedback0http://www.tkk7.com/jinfeng_wang/comments/commentRss/119105.htmlhttp://www.tkk7.com/jinfeng_wang/services/trackbacks/119105.htmlhttp://bigwhite.blogbus.com/archives/1021158.html


//in ANSI_C_CODING_STANDARDS.h

/*
 * Copyright 2005, XX, Inc., China
 * All rights reserved.
 *
 * XX's source code is an unpublished work and the use of a copyright notice does
 * not imply otherwise. This source code contains confidential, trade secret material of
 * XX, Inc. Any attempt or participation in deciphering, decoding, reverse engineering
 * or in any way altering the source code is strictly prohibited, unless the prior written
 * consent of XX, Inc. is obtained.
 */

/*
 * @file ANSI_C_CODING_STANDARDS.h
 * @author tony_bai
 * @date 2005-07-01
 * @brief the template for ANSI C
 *        header file
 */

/*
 * @revision
 *   @version 0.1
 *   @date 2005-08-01
 *   @Revisor tony_bai
 *  
 * @revision
 *   @version 0.2
 *   @date 2005-09-01
 *   @Revisor tony_bai
 */

/*
 * @glossary
 *   xx - xxxxx
 *   xx - xxxxx
 */

/*
 * @usage
 *
 */

#ifndef ANSI_C_CODING_STANDARDS_H
#define ANSI_C_CODING_STANDARDS_H

#include <ANSI C Standard Library Header File>
#include <Operating System Library Header File>
#include "Your System Library Header File"

/*
 * ####################
 * # global constants #
 * ####################
 */

/*
 * #################
 * # global macros #
 * #################
 */

/*
 * ##############################
 * # global abstract data types #
 * ##############################
 */

/*
 * ####################
 * # global variables #
 * ####################
 */

/*
 * #############
 * # externals #
 * #############
 */

/*
 * ###############################
 * # global functions prototypes #
 * ###############################
 */

#endif ANSI_C_CODING_STANDARDS_H

//in ANSI_C_CODING_STANDARDS.c

/*
 * Copyright 2005, XX, Inc., China
 * All rights reserved.
 *
 * XX's source code is an unpublished work and the use of a copyright notice does
 * not imply otherwise. This source code contains confidential, trade secret material of
 * XX, Inc. Any attempt or participation in deciphering, decoding, reverse engineering
 * or in any way altering the source code is strictly prohibited, unless the prior written
 * consent of XX, Inc. is obtained.
 */

/*
 * @file ANSI_C_CODING_STANDARDS.c
 * @author tony_bai
 * @date 2005-07-01
 * @brief the template for ANSI C
 *        source file
 */

/*
 * @revision
 *   @version 0.1
 *   @date 2005-08-01
 *   @Revisor tony_bai
 *  
 * @revision
 *   @version 0.2
 *   @date 2005-09-01
 *   @Revisor tony_bai
 */

#include <ANSI C Standard Library Header File>
#include <Operating System Library Header File>
#include "Your System Library Header File"

/*
 * ###################
 * # local constants #
 * ###################
 */

/*
 * ################
 * # local macros #
 * ################
 */

/*
 * #############################
 * # local abstract data types #
 * #############################
 */

/*
 * ###################
 * # local variables #
 * ###################
 */

/*
 * ##############################
 * # local functions prototypes #
 * ##############################
 */

/*
 * ####################################
 * # global functions implementations #
 * ####################################
 */

/*
 * ###################################
 * # local functions implementations #
 * ###################################
 */



jinfeng_wang 2007-05-22 13:23 发表评论
]]>
GCC - 一切从q里开?zz)http://www.tkk7.com/jinfeng_wang/archive/2007/05/22/119077.htmljinfeng_wangjinfeng_wangTue, 22 May 2007 03:24:00 GMThttp://www.tkk7.com/jinfeng_wang/archive/2007/05/22/119077.htmlhttp://www.tkk7.com/jinfeng_wang/comments/119077.htmlhttp://www.tkk7.com/jinfeng_wang/archive/2007/05/22/119077.html#Feedback0http://www.tkk7.com/jinfeng_wang/comments/commentRss/119077.htmlhttp://www.tkk7.com/jinfeng_wang/services/trackbacks/119077.htmlhttp://www.linuxfocus.org/ChineseGB/March2002/article229.shtml



摘要
:

要想L本文Q你需要对C语言有基本的了解Q本文将介绍如何使用gcc~译器。首先,我们介绍如何在命令行方式下用编译器~译单的C源代码。然后,我们要介l一下编译器I竟作了那些工作Q以及如何控制编译过E。我们也要介l了调试器的使用Ҏ?

 

GCC rules

你能惌使用闭源代码的U有~译器编译自pY件吗Q你怎么知道~译器在你的可执行文件中加入了什么?可能会加入各U后门和木马。Ken Thompson是一个著名的黑客Q他~写了一个编译器Q当~译器编译自己时Q就?login'E序中留下后门和怹的木马。请?q里 阅读他对q个C的描q。幸q的是,我们有了gcc。当你进?configure; make; make install Ӟ gcc在幕后做了很多繁重的工作。如何才能让gcc为我们工作呢Q我们将开始编写一个纸牌游戏,不过我们只是Z演示~译器的功能Q所以尽可能地精了代码。我们将从头开始一步一步地做,以便理解~译q程Q了解ؓ了制作可执行文g需要做些什么,按什么顺序做。我们将看看如何~译CE序Q以及如何用编译选项让gcc按照我们的要求工作。步骤(以及所用工P如下Q?预编?(gcc -E)Q?~译 (gcc)Q?汇编 (as)Q和 q接 (ld)?

 

开?..

首先Q我们应该知道如何调用编译器。实际上Q这很简单。我们将从那个著名的W一个CE序开始。(各位老前辈,请原谅我Q?

#include <stdio.h>
int main()
{ printf("Hello World!\n"); }

 

把这个文件保存ؓ game.c?你可以在命o行下~译它:

gcc game.c
在默认情况下QC~译器将生成一个名?a.out 的可执行文g。你可以键入如下命oq行它:
a.out
Hello World
每一ơ编译程序时Q新?a.out 覆盖原来的E序。你无法知道是哪个程序创Z a.out。我们可以通过使用 -o ~译选项Q告?gcc我们x可执行文件叫什么名字。我们将把这个程序叫?gameQ我们可以用Q何名字,因ؓC没有Java那样的命名限制?
gcc -o game game.c
game
Hello World

 

到现在ؓ止,我们M个有用的E序q差得很q。如果你觉得沮Q你可以想一x们已l编译ƈq行了一个程序。因为我们将一点一点ؓq个E序d功能Q所以我们必M证让它能够运行。似乎每个刚开始学~程的程序员都想一下子~一?000行的E序Q然后一ơ修Ҏ有的错误。没有hQ我是说没有人,能做到这个。你应该先编一个可以运行的程序,修改它,然后再次让它q行。这可以限制你一ơ修改的错误数量。另外,你知道刚才做了哪些修改ɽE序无法q行Q因此你知道应该把注意力攑֜哪里。这可以防止q样的情况出玎ͼ你认Z~写的东西应该能够工作,它也能通过~译Q但它就是不能运行。请切记Q能够通过~译的程序ƈ不意味着它是正确的?

下一步ؓ我们的游戏编写一个头文g。头文g把数据类型和函数声明集中C一处。这可以保证数据l构定义的一致性,以便E序的每一部分都能以同L方式看待一切事情?

#ifndef DECK_H
#define DECK_H
#define DECKSIZE 52
typedef struct deck_t
{
int card[DECKSIZE];
/* number of cards used */
int dealt;
}deck_t;
#endif /* DECK_H */

把这个文件保存ؓ deck.h。只能编?.c 文gQ所以我们必M?game.c。在game.c的第2行,写上 #include "deck.h"。在W?行写?deck_t deck;。ؓ了保证我们没有搞错,把它重新~译一ơ?

gcc -o game game.c

 

如果没有错误Q就没有问题。如果编译不能通过Q那么就修改它直到能通过为止?

 

预编?

~译器是怎么知道 deck_t cd是什么的呢?因ؓ在预~译期间Q它实际上把"deck.h"文g复制C"game.c"文g中。源代码中的预编译指CZ"#"为前~。你可以通过在gcc后加?-E 选项来调用预~译器?

gcc -E -o game_precompile.txt game.c
wc -l game_precompile.txt
3199 game_precompile.txt
几乎?200行的输出Q其中大多数来自 stdio.h 包含文gQ但是如果你查看q个文g的话Q我们的声明也在那里。如果你不用 -o 选项指定输出文g名的话,它就输出到控制台。预~译q程通过完成三个主要dl了代码很大的灵zL?
  1. ?include"的文件拷贝到要编译的源文件中?
  2. 用实际值替?define"的文本?
  3. 在调用宏的地方进行宏替换?
q就使你能够在整个源文g中用符号常量(即用DECKSIZE表示一付牌中的U牌数量Q,而符号常量是在一个地方定义的Q如果它的值发生了变化Q所有用符号常量的地方都能自动更新。在实践中,你几乎不需要单独?-E 选项Q而是让它把输Z送给~译器?

 

 

~译

作ؓ一个中间步骤,gcc把你的代码翻译成汇编语言。它一定要q样做,它必通过分析你的代码搞清楚你I竟惌做什么。如果你犯了语法错误Q它׃告诉你,q样~译失败了。h们有时会把这一步误解ؓ整个q程。但是,实际上还有许多工作要gccd呢?

 

汇编

as 把汇~语a代码转换为目标代码。事实上目标代码q不能在CPU上运行,但它d成已l很q了。编译器选项 -c ?.c 文g转换Z .o 为扩展名的目标文件?如果我们q行

gcc -c game.c
我们p动创Z一个名为game.o的文件。这里我们碰C一个重要的问题。我们可以用L一?.c 文g创徏一个目标文件。正如我们在下面所看到的,在连接步骤中我们可以把这些目标文件组合成可执行文件。让我们l箋介绍我们的例子。因为我们正在编写一个纸牌游戏,我们已经把一付牌定义?deck_tQ我们将~写一个洗牌函数。这个函数接受一个指向deckcd的指针,q把一付随机的牌装入deckcd。它使用'drawn' 数组跟踪记录那些牌已l用q了。这个具有DECKSIZE个元素的数组可以防止我们重复使用一张牌?

 

#include <stdlib.h>
#include <stdio.h>
#include <time.h>
#include "deck.h"
static time_t seed = 0;
void shuffle(deck_t *pdeck)
{
/* Keeps track of what numbers have been used */
int drawn[DECKSIZE] = {0};
int i;
/* One time initialization of rand */
if(0 == seed)
{
seed = time(NULL);
srand(seed);
}
for(i = 0; i < DECKSIZE; i++)
{
int value = -1;
do
{
value = rand() % DECKSIZE;
}
while(drawn[value] != 0);
/* mark value as used */
drawn[value] = 1;
/* debug statement */
printf("%i\n", value);
pdeck->card[i] = value;
}
pdeck->dealt = 0;
return;
}

把这个文件保存ؓ shuffle.c。我们在q个代码中加入了一条调试语句,以便q行Ӟ能输出所产生的牌受这q没有ؓ我们的程序添加功能,但是现在C关键时刻Q我们看看究竟发生了什么。因为我们的游戏q在初阶段Q我们没有别的办法确定我们的函数是否实现了我们要求的功能。用那条printf语句Q我们就能准地知道现在I竟发生了什么,以便在开始下一阶段之前我们知道牌已l洗好了。在我们对它的工作感到满意之后,我们可以把那一行语句从代码中删掉。这U调试程序的技术看h很粗p,但它使用最的语句完成了调试Q务。以后我们再介绍更复杂的调试器?

h意两个问题?
  1. 我们用传址方式传递参敎ͼ你可以从'&'Q取地址Q操作符看出来。这把变量的机器地址传递给了函敎ͼ因此函数自己p改变变量的倹{也可以使用全局变量~写E序Q但是应该尽量少使用全局变量。指针是C的一个重要组成部分,你应该充分地理解它?
  2. 我们在一个新?.c 文g中用函数调用。操作系lLL名ؓ'main'的函敎ͼq从那里开始执行?shuffle.c 中没?main'函数Q因此不能编译ؓ独立的可执行文g。我们必L它与另一个具?main'函数q调?shuffle'的程序组合v来?

q行命o

gcc -c shuffle.c
q确定它创徏了一个名?shuffle.o 的新文g。编辑game.c文gQ在W?行,?deck_tcd的变?deck 声明之后Q加上下面这一行:
shuffle(&deck);
现在Q如果我们还象以前一样创建可执行文gQ我们就会得C个错?
gcc -o game game.c
/tmp/ccmiHnJX.o: In function `main':
/tmp/ccmiHnJX.o(.text+0xf): undefined reference to `shuffle'
collect2: ld returned 1 exit status
~译成功了,因ؓ我们的语法是正确的。但是连接步骤却p|了,因ؓ我们没有告诉~译?shuffle'函数在哪里。那么,到底什么是q接Q我们怎样告诉~译器到哪里Lq个函数呢?

 

 

q接

q接?code>ldQ用下面的命oQ接受前面由 as 创徏的目标文件ƈ把它转换为可执行文g

gcc -o game game.o shuffle.o
q将把两个目标文件组合v来ƈ创徏可执行文?game?

 

q接器从shuffle.o目标文g中找?shuffle 函数Qƈ把它包括q可执行文g。目标文件的真正好处在于Q如果我们想再次使用那个函数Q我们所要做的就是包?deck.h" 文gq把 shuffle.o 目标文gq接到新的可执行文g中?

象这L代码重用是经常发生的。虽然我们ƈ没有~写前面作ؓ调试语句调用?printf 函数Q连接器却能从我们用 #include <stdlib.h> 语句包含的文件中扑ֈ它的声明Qƈ把存储在C库(/lib/libc.so.6Q中的目标代码连接进来。这U方式我们可以使用已能正确工作的其他h的函敎ͼ只关心我们所要解决的问题。这是Z么头文g中一般只含有数据和函数声明,而没有函C。一般,你可以ؓq接器创建目标文件或函数库,以便q接q可执行文g。我们的代码可能产生问题Q因为在头文件中我们没有攑օM函数声明。ؓ了确保一切顺利,我们q能做什么呢Q?

 

另外两个重要选项

-Wall 选项可以打开所有类型的语法警告Q以便帮助我们确定代码是正确的,q且可能实现可UL性。当我们使用q个选项~译我们的代码时Q我们将看到下述警告Q?

game.c:9: warning: implicit declaration of function `shuffle'
q让我们知道q有一些工作要做。我们需要在头文件中加入一行代码,以便告诉~译器有?shuffle 函数的一切,让它可以做必要的查。听h象是一U狡辩,但这样做 可以把函数的定义与实现分d来,使我们能在Q何地方用我们的函数Q只要包含新的头文g q把它连接到我们的目标文件中可以了。下面我们就把这一行加入deck.h中?
void shuffle(deck_t *pdeck);
q就可以消除那个警告信息了?

 

另一个常用编译器选项是优化选项 -O# (?-O2)?q是告诉~译器你需要什么别的优化。编译器h一整套技巧可以你的代码q行得更快一炏V对于象我们q种程序,你可能注意不到差别,但对于大型程序来_它可以大q度提高q行速度。你会经常碰到它Q所以你应该知道它的意思?

 

调试

我们都知道,代码通过了编译ƈ不意味着它按我们得要求工作了。你可以使用下面的命令验证是否所有的L都被使用?

game | sort - n | less
q且查有没有遗漏。如果有问题我们该怎么办?我们如何才能深入底层查找错误呢?

 

你可以用调试器查你的代码。大多数发行版都提供著名的调试器Qgdb。如果那些众多的命o行选项让你感到无所适从Q那么你可以使用KDE提供的一个很好的前端工具 KDbg。还有一些其它的前端工具Q它们都很相伹{要开始调试,你可以选择 File->Executable 然后扑ֈ你的 game E序。当你按下F5键或选择 Execution->从菜单运行时Q你可以在另一个窗口中看到输出。怎么回事Q在那个H口中我们什么也看不到。不要担心,KDbg没有出问题。问题在于我们在可执行文件中没有加入M调试信息Q所以KDbg不能告诉我们内部发生了什么。编译器选项 -g 可以把必要的调试信息加入目标文g。你必须用这个选项~译目标文gQ扩展名?oQ,所以命令行成了Q?
gcc -g -c shuffle.c game.c
gcc -g -o game game.o shuffle.o
q就把钩子放入了可执行文Ӟ使gdb和KDbg能指行情c调试是一U很重要的技术,很值得你花旉学习如何使用。调试器帮助E序员的Ҏ是它能在源代码中讄“断点”。现在你可以用右键单击调?shuffle 函数的那行代码,试着讄断点。那一行边上会出现一个红色的圆圈。现在当你按下F5键时Q程序就会在那一行停止执行。按F8可以跛_shuffle函数。呵Q我们现在可以看?shuffle.c 中的代码了!我们可以控制E序一步一步地执行Qƈ看到I竟发生了什么事。如果你把光标暂停在局部变量上Q你能看到变量的内宏V太好了。这比那?printf 语句好多了,是不是?

 

 

本文大体介绍了编译和调试CE序的方法。我们讨Z~译器走q的步骤Q以及ؓ了让~译器做q些工作应该lgcc传递哪些选项。我们简qC有关q接׃n函数库的问题Q最后介l了调试器。真正了解你所从事的工作还需要付多努力,但我希望本文能让你正地h。你可以?gcc?as ?ld?man ?info page中找到更多的信息?

自己~写代码可以让你学到更多的东ѝ作为练习你可以以本文的U牌游戏为基Q编写一?1Ҏ戏。那时你可以学学如何使用调试器。用GUI的KDbg开始可以更Ҏ一些。如果你每次只加入一点点功能Q那么很快就能完成。切讎ͼ一定要保持E序一直能q行Q?

要想~写一个完整的游戏Q你需要下面这些内容:

  • 一个纸牌玩家的定义Q即Q你可以把deck_t定义为player_tQ?
  • 一个给指定玩家发一定数量牌的函数。记住在U牌中要增加“已发?#8221;的数量,以便能知道还有那些牌可发。还要记住玩家手中还有多牌?
  • 一些与用户的交互,问问玩家是否q要另一张牌?
  • 一个能打印玩家手中的牌的函数?card {于value % 13 Q得Cؓ0?2Q,suit {于 value / 13 Q得Cؓ0?Q?
  • 一个能定玩家手中的value的函数。Ace的value为零q且可以{于1?1。King的value?2q且可以{于10?

 

 

 

站点链接



jinfeng_wang 2007-05-22 11:24 发表评论
]]>
վ֩ģ壺 100000žž18| ޳Ļ| 椸Ƶ߹ۿ| aëƬѲȫ| Ʒר벻| ޹ۺ| AVþþƷɫ| ƷۺרƬþþ | è˳վ߹ۿ| С˵ͼƬƵ| ˳ɵӰ˳9999| ޾ҹþþþþ| ĻӰĻַ8848aa| Ļ| ޳AVƬ߲| Ƶ| ƵۿƵ18| 2021ھƷþþþþ| ԻȫƵ߹ۿ| ˳ɶ߲r18 | ھƵƷ| þ91Ƶۿվ| aëƬ߹ۿ| ëƬѹۿ| AAAAAٸ߳Ƭѿ| һëƬƵվ| ӰӴȫ߲| һƵ߲ | 椸Ƶ| ȫһëƬ߲| þþƷһ糱| ѿAVƬ| ŷߵӰ| ŮɫëƬѿ| ҹ˾Ƶ| ˾Ʒ123Ƶ| ƷƵƵѿ| 99߹ۿ| һػƬ| ޾ƷҺ| ߵӰ|