今天在寫一個字串字母大小寫互轉的一個函數的時候,修修改改終於完成了。代碼如下:
#include "stdafx.h"
#include <string.h>
#include <iostream.h>
char *transform(char *cstr,char *str,int length);
int main(int argc, char* argv[])
{
char *str="woaini38";
cout<<str<<endl;
char s[10];
transform(s,str,strlen(str));
cout<<s<<endl;
return 0;
}
char *transform(char *cstr,char *str,int length)
{
for(int i=0;i<length+1;i++)
{
if (str[i]>='A'&&str[i]<='Z')
{
cstr[i]=str[i]+'a'-'A';
continue;
}
if (str[i]>='a'&&str[i]<='z')
{
cstr[i]=str[i]-'a'+'A';
}
else
{
cstr[i]=str[i];
}
}
return cstr;
}
哎!我承認我基礎不是想象中的好。在寫下這段代碼的時候犯一個錯誤。
開始本來想把transform定義成(char *cstr,char *str)。然後在函數體中去為cstr業就是目標指標動態分配記憶體,於是我寫道:
char *transform(char *cstr,char *str)
{
int len=strlen(str);
cstr=new char [len];//動態分配一個len長度的記憶體
for(int i=0;i<len+1;i++)//下面的是一樣的
{
if (str[i]>='A'&&str[i]<='Z')
{
cstr[i]=str[i]+'a'-'A';
continue;
}
if (str[i]>='a'&&str[i]<='z')
{
cstr[i]=str[i]-'a'+'A';
}
else
{
cstr[i]=str[i];
}
}
return cstr;
}
但是啟動並執行時候包記憶體出錯了,說某塊記憶體不能讀,或者某塊記憶體不能寫。編程這麼久了,我立即就想到了這樣的錯誤應該是用了null 指標而導致的。我仔細檢查但是沒有找到,單步啟動並執行時候知道是transform的cstr出了問題。但是我已經動態為他分配記憶體了啊!這個愁死我了。找不到原因,我試著用另一種寫法,於是我動態分配的語句刪除:但是迴圈的時候需要字串長度變數。於是我傳它一個length變數。然後在main函數我只能定義一個數組。然後給transform傳參了。於是你就看到了開頭的那段代碼。
後來就一切順利了。
但是我一直想不通為什麼不能傳遞給transform一個null 指標,然後在函數體中去動態分配記憶體呢?
在網上我看到這麼一篇文章http://99381837.iteye.com/blog/905237
作者分析的挺不錯了。他告訴我如果我要傳遞一個null 指標的話,我就應該這麼寫char *transform(char **cstr,char *str){*cstr=(char *)malloc(strlen(str)+1);}
後面的分析看著就疼痛了。一下不能完全看下來。
其實寫這篇文章也就是讓自己不要再犯這樣的一個錯誤。但是這個錯誤也讓我想起了一個編程習慣。說盡量不要去使用null 指標。但是我們在編程中卻有時候不知道自己正在使用null 指標。
於是我在VC中寫下這麼一段代碼:
#include "stdafx.h"
#include <iostream.h>
#include <string.h>
int main(int argc, char* argv[])
{
char *str="woaini";
char *s;
strcmp(s,str);
cout<<s<<endl;
return 0;
}
這個時候我猜你應該知道怎麼寫這段代碼了。
其實對於把一個null 指標作為參數的這個做法還有一個錯誤被忽略了。你想如果你可以在函數體中去動態分配記憶體的話,那麼你分配的這塊記憶體什麼時候可以得到釋放呢?動態分配的記憶體是要手動釋放的。這也是一個問題對吧。所以怎麼寫null 指標都不應該作為參數傳遞的。
在大部分MFC的編程中,像字串的傳參都是CString的一個對象。有時候需要SDK的一些函數的時候,參數是指標的話,一定要記得分配記憶體,要不會出現錯誤。