1. 程式人生 > >CString/string /Char轉化、Vector、分割、New、Malloc、Memset、Memcpy、Strcpy、static

CString/string /Char轉化、Vector、分割、New、Malloc、Memset、Memcpy、Strcpy、static

#include "stdafx.h"
#include <string>
// #include <stdlib.h>
#include <stdio.h>
#include <iostream>
using namespace std;
int _tmain()
{
    //把字串轉成數字
 char *token="20";//或者 char token[10]="20";
 int n;
 n=atoi(token);
 n+=8;
  
    //把數字轉成字串
 char buf[200]; //不能轉換成 char *buf;  可以寫成char *buf=new char[200] 
 sprintf_s(buf,20,"%d",n);
 cout<<buf; 

 return 0;
}

 char *itoa(int value, char *string, int radix);

 int value 被轉換的整數,char *string 轉換後儲存的字元陣列,int radix 轉換進位制數,如2,8,10,16 進位制等

char charUnsharp[10];

int num= 3;
itoa(num,charUnsharp,10);//把整數num轉換成字串charUnsharp ,10進位制轉換。 

為TgImage自定義的結構體分配空間

 static char* pShowImgX;
 static TgImage outimage;//前面加了個static
 if ( bFirstreg )
 {
  bFirstreg = FALSE;
  pShowImgX = new char[384*288*3];
  outimage.pData = pShowImgX;
  outimage.width = g_Image.width;
  outimage.height = g_Image.height;
  outimage.nChannels = 3;

 }

在用MFC進行程式設計時,我們從對話方塊中利用GetWindowText得到的字串是 CString型別,CString是屬於MFC的類。

而一些標準C/C++庫函式是不能直接對CString型別進行操作的,所以我們經常遇到將 CString型別轉化char*等等其他資料型別的情況。這裡總結備忘於此!
首先要明確,標準C中是不存在string型別的,string是標準C++擴充字串操作的一個類。但是我們知道標準C中有string.h這個標頭檔案,這裡要區分清楚,此string非彼string。 string.h這個標頭檔案中定義了一些我們經常用到的操作字串的函式,如:strcpy、strcat、strcmp等等,但是這些函式的操作物件都是char*指向的字串。而C++的string類操作物件是string型別字串,

該類重灌了一些運算子,添加了一些字串操作成員函式,使得操作字串更加方便。有的時候我們要將string串和char*串配合使用,所以也會涉及到這兩個型別的轉化問題。

CString並非是你賦予多大長度的字串就佔有多大的記憶體空間。它的空間分配機制是事先申請一個比較大的記憶體空間來存放字串,在以後的操作中如果字串超出了這個記憶體區域,它才會先釋放原先的記憶體區域,重新申請一個更大的記憶體空間。同樣,如果字串變短了,它也不是立即釋放多餘空間,而是累積到了一定程度才釋放。這樣實現了“無長度限制”,又避免了頻繁的申請、釋放記憶體的操作。

CString的另外一個特色就是“寫入複製技術(CopyBeforeWrite)”。當使用一個CString物件A來初始化另外一個CString物件B時,B並不會被分配空間,而是將自己的指標指向物件A的儲存空間。除非對兩個中的某個做修改時,才會為物件B申請記憶體。

1.CString和string的轉化
string  str="ksarea";
CString cstr(str.c_str());//或者CString  cstr(str.data());初始化時才行
cstr = str.c_str();或者cstr = str.data();
str = cstr.GetBuffer(0); //CString -> string
cstr.format("%s", str.c_str()); //string->CString
cstr.format("%s", str.data()); //string->CString
str = LPCSTR(cstr); //CString->string
/*c_str()和data()區別是:前者返回帶'/0'的字串,後者則返回不帶'/0'的字串*/

string型別不能直接賦值給CString

2.CString和int的轉換
int i=123;
CString str;
str.format("%d",i);//int->CString 其他的基本型別轉化類似
i=atoi(str);//CString->int 還有(atof,atol)

3、判斷string是否為空

string類為空,實際也就是元素為0個。 可以按照如下方式判斷:

1、string類有自己的成員函式empty, 可以用來判斷是否為空。

1 2 3 string s; if(s.empty())//成立則為空 ...

2、判斷字串長度。如果長度為0,則為空。

1 2 3 string s; if(s.length()==0)//成立則為空 ...

3、與空串比較,如果相等則為空。

1 2 3 string s; if(s=="")//成立則為空 ...

幾種方法中,empty函式是效率最高也是最常用的一種。 

3、string型別轉換int型別

1、c
  1. std::string str;  
  2. int i = atoi(str.c_str());  

2、c++
  1. std::string str;  
  2. int i = std::stoi(str);  
3、從string中取某個字元    string  stem="123456"    stem[2] 裡面的值是字元3    int(stem[2])-'0'  得到數值3

 string怎樣判斷字串裡面是否含有某個字串

string::size_type string::find(string &);

1)

    string a="abcdefghigklmn";
    string b="def";
   
    idx=a.find(b);//在a中查詢b.
    if(idx == string::npos )//不存在。
        cout << "not found\n";
    else//存在。
        cout <<"found\n"; 

2)C語言風格。字串儲存為字元陣列,以'\0'結束。 在C的介面中,有strstr函式,可以在字串中查詢另一個字串。

char * strstr(const char *str1, const char *str2);

功能為在str1中查詢str2,如果存在,那麼返回查詢到的起始指標,否則返回NULL。

    string a="abcdefghigklmn";
    char *b="def";
     
    if(strstr(a.c_str(), b) == NULL)//在a中查詢b,如果不存在,
        cout << "not found\n";//輸出結果。
    else//否則存在。
        cout <<"found\n"; //輸出結果。


標準庫的string類提供了3個成員函式來從一個string得到c型別的字元陣列:c_str()、data()、copy(p,n)。

1. c_str():生成一個const char*指標,指向以空字元終止的陣列。

注:

①這個陣列的資料是臨時的,當有一個改變這些資料的成員函式被呼叫後,其中的資料就會失效。因此要麼現用先轉換,要麼把它的資料複製到使用者自己可以管理的記憶體中。注意看下例:

 const char* c;

string s="1234";
c = s.c_str(); 
cout<<c<<endl;//輸出:1234
s="abcd";
cout<<c<<endl;//輸出:abcd

上面如果繼續用c指標的話,導致的錯誤將是不可想象的。就如:1234變為abcd

其實上面的c = s.c_str(); 不是一個好習慣。既然c指標指向的內容容易失效,我們就應該按照上面的方法,那怎麼把資料複製出來呢?這就要用到strcpy等函式(推薦)。

//const char* c; //①
//char* c;       //②
//char c[20]; 
char* c=new char[20];
string s="1234";
//c = s.c_str(); 
strcpy(c,s.c_str());
cout<<c<<endl;//輸出:1234
s="abcd";
cout<<c<<endl;//輸出:1234

注意:不能再像上面一樣①所示了,const還怎麼向裡面寫入值啊;也不能②所示,使用了未初始化的區域性變數“c”,執行會出錯的 。

② c_str()返回一個客戶程式可讀不可改的指向字元陣列的指標,不需要手動釋放或刪除這個指標。

2. data():與c_str()類似,但是返回的陣列不以空字元終止。

3. copy(p,n,size_type _Off = 0):從string型別物件中至多複製n個字元到字元指標p指向的空間中。預設從首字元開始,但是也可以指定,開始的位置(記住從0開始)。返回真正從物件中複製的字元。------使用者要確保p指向的空間足夠儲存n個字元

string::copy()舉例:

char c2[11] = {0};

string s2 = "hello boy!";
int iRtn = s2.copy(c2, 10, 0);//功能為將s2的,從第0個開始的,共10個字元拷貝到c2中,iRtn為拷貝的字元個數,此處為10。

注意:iRtn返回的是實際拷貝的位元組數,當第二個引數比字串本身長時,返回的便是字串長度。


MFC問題int轉cstring


CString msg;   
int dep = disp.depth();
msg.Format(_T("depth:%d"),dep);
AfxMessageBox(msg);


3. char* 和CString的轉換
1) CString cstr = "ksarea"; 
      char* ptemp = cstr.getbuffer(0);

2) char* str;
        strcpy(str,ptemp);//CString->char*
        cstr.releasebuffer(-1);

        char* str="lovesha";
        CString cstr=str;//char*->CString

        至於int與float、string與char*之間的轉化可以使用強制轉化,或者標準庫函式進行。對於CString與其他型別的轉化方法很多,但其實都殊途同歸,朝著一個方向即將型別首先轉化為char*型別,因為char*是不同型別之間的橋樑。得到char*型別,轉化為其他型別就非常容易了。

3.1 把兩個char *字串複製到另一個char * 變數中

char str3[20];
strcpy(str3,str1);
strcat(str3,str2);
char* str=str3;

cout<<str<<endl;  //使用此句要包含:#include <iostream>   和  using namespace std;

string 轉換成 const char *

string s1 = "abcdeg";
const char *k = s1.c_str();或  const char *t = s1.data();
printf("%s%s",k,t);
cout<<k<<t<<endl;

如上,都可以輸出。內容是一樣的。但是隻能轉換成const char*,如果去掉const編譯不能通過。

那麼,如果要轉換成char*,可以用string的一個成員函式copy實現。

string s1 = "abcdefg";
char *data;
int len = s1.length();
data = (char *)malloc((len+1)*sizeof(char));
s1.copy(data,len,0);
printf("%s",data);
cout<<data;          //說明,如果字符集是unicode的話,可能字串後面有亂碼,如果選 為多字符集的話,就只輸出字串

3.2、char *轉換成string

可以直接賦值。

string s;
char *p = "adghrtyh";
s = p;

printf("%s",s1.c_str())// 這樣是正確的
//  printf("%s",s1)  這樣是錯誤的 

cout<<s.c_str()<<endl;  //正確

//cout<<s<<endl;             //錯誤


注:

1)用printf("%s",s1);輸出是會出問題的。這是因為“%s”要求後面的物件的首地址。但是string不是這樣的一個型別。所以肯定出錯。

那麼可以這樣:printf("%s",s1.c_str())

如何判斷一個 char * s 指標的內容是否為空

1、 CString strname;
      strname=m_bstr_name;  //m_bstr_name也是CString型別的
      if (strname=="")
        {
            AfxMessageBox("name is null");
       }

如果要判斷一個char *s 是否為空,要用strcmp(m_bstr_name.GetBuffer(0),"")進行判斷

2、if (strcmp(m_bstr_name.GetBuffer(0),"")==0) //m_bstr_name.GetBuffer(0)是把一個CString型別轉換成char *型別
      {
          AfxMessageBox("name is  null");
       }
      else
          AfxMessageBox("name is not null222");

(2)   char * s = new char[10];
         memset(s,'\0',10);
         if(strcmp(s,"")==0)  或者是 if(s[0]==0)

注意:如果寫成下面這樣,就是錯誤的

      if (m_bstr_name.GetBuffer(0) ==“”) //m_bstr_name.GetBuffer(0)是把一個CString型別轉換成char *型別
     上面這句是錯誤,m_bstr_name.GetBuffer(0)指向的內容一直都不是空。

String name==null;//是空引用 Null ::一個值,表示一個變數不包含任何有效資料。
String name="";//這是個空字串
String name="";這個在堆上分配了儲存空間.你可以呼叫String的所有方法.

第一個只是空引用.不能在第一個上呼叫String的任何方法.因為他是一個空引用.    空字串也是串. 3、兩個char * 字串的比較

char* str_1 = "abc" ; char * str_2 = "abc" ; char* str_3 = "ABC" ;

    if (strcmp(str_1, str_2) == 0)

    { 。。。。。

     }

1.首先正確包含標頭檔案
使用下面語句
#include <string>
沒有.h,
否則無法引用標準模板庫
2.使用名稱空間
即使用下面語句:
using namespace std;
3.string 所建立的物件不能夠直接使用裡面的字串
如 string str;
cout<<str<<endl;
這樣語句不能執行
要使用string的一個函式進行轉化 c_str() 才能正確使用其中的字串。

4、怎樣比較兩個型別為String的字串?

1)

 string s1="fsf";
 string s2="sdfnk";
// if(strcmp(s1,s2))//這樣寫錯誤,因為strcmp(s1,s2)中,要求s1,s2都是char * 型別
 if (s1.compare(s2)==0) // 這樣寫正確
     cout<<"s1 is equal to s2";
 else
     cout<<"s1 !=s2";


2)

 string s1="fsf";
 string s2="fsf";
 // if(strcmp(s1,s2))//這樣寫錯誤,因為strcmp(s1,s2)中,要求s1,s2都是char * 型別
// if (s1.compare(s2)==0)//正確
   if (s2 ==s1) //正確
       cout<<"s1  equal to s2"<<endl;
   else
       cout<<"s1 is not s2"<<endl;

說明:如果內容已經存在了,不會分配第二個,上面已經 String s1 = "fsf";了, 這個"fsf"已經存在了,下面String s2 = "fsf"; 就不會分配第二個"fsf"了,那麼s2指向誰?s2也指向上面s1指向的這個物件,現在是s1和s2同時指向同一個物件,那麼它們的地址當然一樣,==比較的是引用地址,所以s1 == s2 返回true。

在兩個物件之間使用 "==",會將“兩個物件是否有同一reference”的結果傳回。也就是說, 這等同於“兩個物件是否擁有同一地址 (address)”,或者“兩個物件物件是否為同一物件”。

如果您的意思是判斷兩個字串的內容是否相同那麼應該使用以下的方法才對:

if (s1.equals(s2) )

or if (s1.equalsIgnoreCase(s2) )

or if (s1.startsWith(s2) )

or if (s1.endsWith(s2) )

or if (s1.regionMatches(s1_offset, s2, s2_offset, length) )

or if (s1.compare(s2) )

1)strlen:計算字串s的長度,不包括'\0'在內 //const char * 的長度
如:

 string strName="abc";  char * data="bcd";

int len2=strlen(strName);//錯誤 要求:strName 為const char* 型別

int len2=strlen(data);//正確

 cout<<"len2: "<<len2<<endl; 結果是len2: 3

2)sizeof:判斷資料型別長度符
如:sizeof(int)結果就是4,
   sizeof(string)結果就是16,
   sizeof(char *)結果就是4,
   sizeof(char)結果就是1
3)length:是求字串長度,或陣列中長度最長的那一維的長度。
如: string strName="abc";
    int len = strName.length();//string 的長度 

    cout<<"len: "<<len<<endl;  結果就是 len: 3
總之:strlen是統計字串的字元個數,不包括結尾的\0;length是求字串長度,

5、轉換成相應的字串

vs2005:

 char *filename=new char[20];
 sprintf_s(filename,20,"air%d.jpg",i);

vc6.0:

 char *filename=new char[20];
 sprintf(filename,"air%d.jpg",i);   

 char buf[5];
 sprintf(buf,"%d",srcImg->nChannels);
 MessageBox(buf);

CString cstr;
cstr.format("%s", 123);

  IplImage* paintx=cvCreateImage( cvGetSize(src),IPL_DEPTH_8U, 1 );  
  IplImage* painty=cvCreateImage( cvGetSize(src),IPL_DEPTH_8U, 1 );  
  //  cvZero(paintx);   //全變為黑色
  cvSet(paintx,cvScalar(255,255,255,255),0);//全變為白色
  cvZero(painty);  

  int* v=new int[src->width];  
  int* h=new int[src->height];  
  memset(v,0,src->width*4);  
  memset(h,0,src->height*4);  

  delete v;
  delete h;

 CString str1;

    avg=totalwidthmy/(w.size()-6-sb);
    str1.Format("%d",avg);
    MessageBox(str1);

6、new 和 malloc 的區別

從函式宣告上可以看出。malloc 和 new 至少有兩個不同: new 返回指定型別的指標,並且可以自動計算所需要大小。比如:
int *p; 
p = new int;  //返回型別為int* 型別(整數型指標),分配大小為 sizeof(int); 

或:
int* parr; 
parr = new int [100];  //返回型別為 int* 型別(整數型指標),分配大小為 sizeof(int) * 100; 

而 malloc 則必須要由我們計算位元組數,並且在返回後強行轉換為實際型別的指標
int* p; 
p = (int *) malloc (sizeof(int)*128); //分配128個(可根據實際需要替換該數值)整型儲存單元,並將這128個連續的整型儲存單元的首地址儲存到指標變數p中 
double *pd=(double *) malloc (sizeof(double)*12); //分配12個double型儲存單元, //並將首地址儲存到指標變數pd中
第一、malloc 函式返回的是 void * 型別。對於C++,如果你寫成:p = malloc (sizeof(int)); 則程式無法通過編譯,報錯:“不能將 void* 賦值給 int * 型別變數”。所以必須通過 (int *) 來將強制轉換。而對於C,沒有這個要求,但為了使C程式更方便的移植到C++中來,建議養成強制轉換的習慣。 第二、函式的實參為 sizeof(int) ,用於指明一個整型資料需要的大小。如果你寫成: int* p = (int *) malloc (1);
程式碼也能通過編譯,但事實上只分配了1個位元組大小的記憶體空間,當你往裡頭存入一個整數,就會有3個位元組無家可歸,而直接“住進鄰居家”!造成的結果是後面的記憶體中原有資料內容被改寫。 7、 memset()、memcpy()、strcpy()、strncpy() 1)memset()的深刻內涵:用來對一段記憶體空間全部設定為某個字元,一般用在對定義的字串進行初始化為‘ ’或‘\0’; 例:char a[100];      memset(a, '\0', sizeof(a)*100);
#include<iostream> #include<cstring> using namespace std; int main() { char a[5]; memset(a,'1',5*sizeof(a));//sizeof(a) =1 for(int i=0;i<5;i++)    cout<<a[i]<<""; system("pause"); return0; }

以上這段程式是正確的,a[i]的值是1.

#include<iostream> #include<cstring> #include<windows.h> using namespace std; int main() { int a[5]; memset(a,1,20);//如果這裡改成memset(a,1,5*sizeof(int))也不可以,因為memset按位元組賦值 for(int i=0;i<5;i++)    cout<<a[i]<<" "; system("pause"); return0; }

問題是:

1,第一個程式為什麼可以,而第二個不行? 因為第一個程式的陣列a是字元型的,字元型佔據記憶體大小是1Byte,而memset函式也是以位元組為單位進行賦值的,所以你輸出沒有問題。 而第二個程式a是整型的,使用 memset還是按位元組賦值,這樣賦值完以後,每個陣列元素的值實際上是0x01010101即十進位制的16843009。 如果用memset(a,1,20) 就是對a指向的記憶體的20個位元組進行賦值,每個都用ASCⅡ為1的字元去填充,轉為二進位制後,1就是00000001,佔一個位元組。一個INT元素是4位元組,合一起就是0x01010101,就等於16843009,就完成了對一個int 元素的賦值了


2)memcpy用來做記憶體拷貝,你可以拿它拷貝任何資料型別的物件,可以指定拷貝的資料長度;

例:char a[100],b[50];         memcpy(b, a, sizeof(b));注意如用sizeof(a),會造成b的記憶體地址溢位。把a的前sizeof(b)個字元複製到b中

3)strcpy就只能拷貝字串了,它遇到'/0'就結束拷貝;
例:char a[100],   b[50];         strcpy(a,b);  如用strcpy(b,a),要注意a中的字串長度(第一個‘/0’之前)是否超過50位,如超過,則會造成b的記憶體地址溢位。 4)   strcpy 和strncpy 的差別在哪裡,各自的優缺點是什麼
strcpy  (目標串地址,源串的開始地址): 從源串的開始到結尾('\0')完全拷貝到目標串地址
strncpy(目標串地址,源串的開始地址,n):  從源串的開始拷貝n個字元到目標串地址,n大於源串長度時,遇到'\0'結束; n小於源串長度時,到第n個字元結束,但不會在目標串尾補'\0'

 char *p="hello";  char *p1="liulina";  char s[40]="how are you? where are you from";

 strncpy(s,p1,3);  cout<<s<<endl;// 輸出 liu are you? where are you from

 strcpy(s,p);//輸出 hello  cout<<s<<endl;

8、動態分配陣列大小 typedef std::vector<int> List;
List w; w.push_back(roi.width); w.size();//容器裡有多少個變數
用new分配的物件會呼叫物件建構函式,delete則會呼叫物件的解構函式
而malloc和free從不呼叫構造和解構函式,他們只是簡單的分配記憶體。
參考以下程式分析說明 new 和 malloc 的區別:
1#include <iostream> 
2#include <cstdio>
3#include <cstdlib>
4using namespace std;
5class T
6{
7 public:
8 T(){ cout << "T()" << endl; }
9 ~T(){ cout << "~T()" << endl; }
10 };
11int main()
12{
13 T* first = new T;
14 T* second = (T*)malloc(sizeof(T));
15 if( first ) delete first;
16 if( second ) free(second);
17 return 0;
18}

解答:
由第13、14行程式碼可見,new,malloc均能完成動態分配一個新的空間的功能,並把它的首地址交給一個指標。區別在於:
1. new直接寫在型別T的前面,是C++中的一個操作符,且直接分配T大小的記憶體空間。而malloc是C中的一個函式,且需要藉助於函式sizeof幫其判斷T型別的大小;
2. new直接返回一個T型別的指標,而且會呼叫類中的建構函式。而malloc返回一個void指標,需要在前面對其強制定義為一個T型別的指標,不用呼叫建構函式。
3. new與delete搭配使用,delete會呼叫類中的解構函式對記憶體進行釋放。malloc則與free搭配,不呼叫解構函式

9、 vetor容器

#include "stdafx.h"

#include "cv.h"
#include "highgui.h"
#include "cvaux.h"
#include "cxcore.h"
#include <stdio.h>
#include <vector>

#include <iostream>
#include <cv.h>   
#include <highgui.h>   
#pragma comment( lib, "cv.lib" )   
#pragma comment( lib, "cxcore.lib" )   
#pragma comment( lib, "highgui.lib" )    
using namespace std;

typedef std::vector<int> List;

void bubble_sort(List& a,int n)
{
    for(int i = 0; i < n; ++i)//[0..(n-1)]
    {
        //j < n - 1可以優化
        for( int j = 0 ; j < n - 1; ++j)//a[0..(n-2)]
			if ( a[j] > a[j+1] )
			{
				int t = a[j];
				a[j] = a[j+1];
				a[j+1] = t;
			}
    }
}

void print(List& a, int n)
{
    for(int i = 0; i < n; ++i)
    {
        printf("%2d  ",a[i]);
    }
    printf("\n");
}

int main()   
{      
    IplImage * src1=cvLoadImage("show1.bmp",0); 
	IplImage * src=cvCreateImage(cvSize(src1->width,src1->height),src1->depth,src1->nChannels); 
	cvErode(src1,src,NULL,1);//膨脹影象 
	cvSaveImage("c:\\src11.bmp",src);

	cvDilate(src,src,NULL,1);//腐蝕影象   
	cvSaveImage("c:\\src00.bmp",src);

    cvThreshold(src,src,150,255,/*CV_THRESH_BINARY_INV*/0);  
	
    IplImage* paintx=cvCreateImage( cvGetSize(src),IPL_DEPTH_8U, 1 );   
    IplImage* painty=cvCreateImage( cvGetSize(src),IPL_DEPTH_8U, 1 );   
//  cvZero(paintx);   //全變為黑色
	cvSet(paintx,cvScalar(255,255,255,255),0);//全變為白色
    cvZero(painty);   

    int* v=new int[src->width];   
    int* h=new int[src->height];   
    memset(v,0,src->width*4);   
    memset(h,0,src->height*4);   

    int x,y; 
	int mark=0,num1=0;
	int min=src->height,col=0;
	bool flag1=0;
	bool flag2=0;
	int leftnew=0,rightnew=0,left,right;
    CvScalar s,t;   
	IplImage * histgram;
	char * fname=new char[100];
	int tem