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

#include "stdafx.h"
#include 
// #include 
#include 
#include 
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<


 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中c_str()、data()、copy(p,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指针的话,导致的错误将是不可想象的。就如: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<

注意:不能再像上面一样①所示了,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<   和  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<

如上,都可以输出。内容是一样的。但是只能转换成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<

3.2、char *转换成string

可以直接赋值。

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

printf("%s",s1.c_str())// 这样是正确的
//  printf("%s",s1)  这样是错误的 

cout<

//cout<


注:

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)

    { 。。。。。

     }

error C2501: 'string' : missing storage-class or type specifiers

1.首先正确包含头文件
使用下面语句
#include
没有.h,
否则无法引用标准模板库
2.使用命名空间
即使用下面语句:
using namespace std;
3.string 所创建的对象不能够直接使用里面的字符串
如 string str;
cout<
这样语句不能执行
要使用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"<    else
       cout<<"s1 is not s2"<

说明:如果内容已经存在了,不会分配第二个,上面已经 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: "< 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: 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
#include
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< "" ;
system ( "pause" );
return0;
}

以上这段程序是正确的,a[i]的值是1.

 

#include
#include
#include
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< " " ;
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< 输出 liu are you? where are you from

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

8、动态分配数组大小
typedef std::vector List;
List w;
w.push_back(roi.width);
w.size();//容器里有多少个变量

用new分配的对象会调用对象 构造函数 ,delete则会调用对象的 析构函数
而malloc和free从不调用构造和 析构函数 ,他们只是简单的分配内存。
参考以下程序分析说明 new 和 malloc 的区别:
1#include  
2#include 
3#include 
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 
#include 

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

typedef std::vector 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 temp[500][500];
	int temp_cut[500];//分割出来的数字的宽度
	int start_index[100];//从此位置开始分割
	int temp_j1 = 0;
	int N=20;
   
	List w;  // FIXEME:
	//垂直
    for(x=0;xwidth;x++)   
    {   
		mark=0;
        for(y=0;yheight;y++)   
        {   
            s=cvGet2D(src,y,x);            
            if(s.val[0]==0)   
			{
				v[x]++;//一列的黑点个数
				mark++;
			}
        }  
        //以下是分割,针对白底黑字的进行分割
		if( flag1 == 0 )
		{
			if(v[x]!= 0)
			{
				flag2 = 1;
			}
		}
		else
		{
			if(v[x] ==0)
			{
				flag2 = 1;
			}
			else
			{
				flag2 = 0;
			//	break;
			}
		}
		if (x==src->width-1 && flag2==0)
		{
			flag2=1;
		}
		if( flag1 == 0 && flag2 == 1 )
		{
			leftnew = x;//leftnew表示从此位置开始分割
			start_index[num1] = x;//某个数字开始分割的起始位置
			flag1 = 1;
			flag2 = 0;
		}
		if( flag1 == 1 && flag2 == 1)
		{
		
			rightnew=x;
			flag1 = flag2 = 0;
			
			//取字符			
			CvRect roi;
			roi.x=leftnew;
			roi.y=0;
			roi.width=rightnew-leftnew+1;
			roi.height=src->height;
			sprintf(fname,"%d.bmp",num1);
			
			cvSetImageROI(src,roi);
			
			cvSaveImage(fname,src);
			cvResetImageROI(src);
		    
			//w[num1]=roi.width;
			num1++;
			w.push_back(roi.width);
		}

    }   

   
    bubble_sort(w, w.size());//排序
     print(w, w.size());
    int sb=0;
    int total=0,avg=0;
	for (int i=3;iwidth;x++)   
    {   
        for(y=0;yheight-y-1),x,t);         
        }          
    }
	cvSaveImage("paintx.bmp",paintx);


    cvNamedWindow("二值图像",1);   
    cvNamedWindow("垂直积分投影",1);   
    cvShowImage("二值图像",src);   
    cvShowImage("垂直积分投影",paintx);   
    cvWaitKey(0);   
    cvDestroyAllWindows();   
    cvReleaseImage(&src);   
    cvReleaseImage(&paintx);   
    cvReleaseImage(&painty);   
    return 0;   
}  

CString/string /Char转化、Vector、分割、New、Malloc、Memset、Memcpy、Strcpy、static_第1张图片

10、static的作用

   

在C语言中,static的字面意思很容易把我们导入歧途,其实它的作用有三条。

(1)先来介绍它的第一条也是最重要的一条:隐藏。

当我们同时编译多个文件时,所有未加static前缀的全局变量和函数都具有全局可见性。为理解这句话,我举例来说明。我们要同时编译两个源文件,一个是a.c,另一个是main.c。

下面是a.c的内容

char  a  =   ' A ' //  global variable
void  msg() 
{
    printf(
" Hello\n " ); 
}
 

下面是main.c的内容

int  main( void )
{    
    
extern   char  a;     //  extern variable must be declared before use
    printf( " %c  " , a);
    (
void )msg();
    
return   0 ;
}
 

程序的运行结果是:

A Hello

你可能会问:为什么在a.c中定义的全局变量a和函数msg能在main.c中使用?前面说过,所有未加static前缀的全局变量和函数都具有全局可见性,其它的源文件也能访问。此例中,a是全局变量,msg是函数,并且都没有加static前缀,因此对于另外的源文件main.c是可见的。

如果加了static,就会对其它源文件隐藏。例如在a和msg的定义前加上static,main.c就看不到它们了。利用这一特性可以在不同的文件中定义同名函数和同名变量,而不必担心命名冲突。Static可以用作函数和变量的前缀,对于函数来讲,static的作用仅限于隐藏,而对于变量,static还有下面两个作用。

(2)static的第二个作用是保持变量内容的持久。存储在静态数据区的变量会在程序刚开始运行时就完成初始化,也是唯一的一次初始化。共有两种变量存储在静态存储区:全局变量和static变量,只不过和全局变量比起来,static可以控制变量的可见范围,说到底static还是用来隐藏的。虽然这种用法不常见,但我还是举一个例子。
#include  < stdio.h >

int  fun( void ){
    
static   int  count  =   10 ;     //  事实上此赋值语句从来没有执行过
     return  count -- ;
}

int  count  =   1 ;

int  main( void )
{    
    printf(
" global\t\tlocal static\n " );
    
for (; count  <=   10 ++ count)
        printf(
" %d\t\t%d\n " , count, fun());    
    
    
return   0 ;
}
 

程序的运行结果是:

global          local static

1               10

2               9

3               8

4               7

5               6

6               5

7               4

8               3

9               2

10              1

 

(3)static的第三个作用是默认初始化为0。其实全局变量也具备这一属性,因为全局变量也存储在静态数据区。在静态数据区,内存中所有的字节默认值都是0x00,某些时候这一特点可以减少程序员的工作量。比如初始化一个稀疏矩阵,我们可以一个一个地把所有元素都置0,然后把不是0的几个元素赋值。如果定义成静态的,就省去了一开始置0的操作。再比如要把一个字符数组当字符串来用,但又觉得每次在字符数组末尾加’\0’太麻烦。如果把字符串定义成静态的,就省去了这个麻烦,因为那里本来就是’\0’。不妨做个小实验验证一下。

#include  < stdio.h >
int  a;
int  main( void )
{
    
int  i;
    
static   char  str[ 10 ];

    printf(
" integer: %d;  string: (begin)%s(end) " , a, str);

    
return   0 ;
}

 

程序的运行结果如下 :

integer: 0; string: (begin)(end)

 

(4)在公用类中定义全局变量和全局函数,均使用static修饰,静态变量还必须在类外定义和初始化

Public.h:(公用类头文件)

class CPublic
{
public:
CPublic();
virtual ~CPublic();

public:
static int x; //全局变量
static int time; //全局变量
static int f(int y); //全局函数
…………
}

在公用类中对静态变量进行初始化和定义函数体:

Public.cpp:(公用类程序文件)(注意:下面的初始化

int CPublic::x = 0; //初始化全局变量
int CPublic::time; //定义全局变量

CPublic::CPublic()
{

}

CPublic::~CPublic()
{

}

int CPublic::f(int y) //全局函数,这里不要再加static
{
y++;
return y;
}

4、全局量的使用

使用变量:CPublic::变量名

使用函数:CPublic::函数()

如在视图的某函数中访问变量x和函数f():

void CTestView::xyz()
{
CPublic::x = 0; //访问变量x
CPublic::time = CPublic::f(1); //访问函数f()
…………
}

最后对static的三条作用做一句话总结:

1)首先static的最主要功能是隐藏

2)其次因为static变量存放在静态存储区,所以它具备持久性和默认值0。


返回字符串本身都是一件很危险的事情,
实在没想到,没有多少人回答这个问题。

1. 普遍情况下,使用VC6,一定不要返回string, CString.
string function() {}

这种应该杜绝,
在VC7和以后的版本中,是没有问题的,源于Allocator的实现问题。
也就是CRT的堆分配内存的问题。

2. 一般用法,
BSTR function(){}
char* function(){}
这种可以,
但是你的模块,最好提供一个响应的Release函数。

Release(BSTR);
Release(char*);

3. 推荐做法:
int function(char* ret, int buffer_size); // return string length.
function(string& ret);
 

只取图片名称或只取不带扩展名的图片名称
void CImgIncreaceDlg::OnBnClickedButOpenimg()
{
	// TODO: 在此添加控件通知处理程序代码

	CFileDialog fileDlg(TRUE, _T("*.bmp"), "",
		OFN_FILEMUSTEXIST|OFN_PATHMUSTEXIST|OFN_HIDEREADONLY, 
		"Image Files (*.jpg; *.bmp)|*.jpg; *.bmp|All Files (*.*)|*.*||", NULL);

	//设置打开对话框的标题
	char title[]= {"打开图片"};
	fileDlg.m_pOFN->lpstrTitle= title;

	if(fileDlg.DoModal()==IDOK)
	{
		CString pathName= fileDlg.GetPathName();//C:\Pictures\doudou.bmp
		m_openPath= pathName;

		int i=m_openPath.ReverseFind('\\');
		CString fn= m_openPath.Right(m_openPath.GetLength()-i-1);//此时fn = doudou.bmp		
		int j=fn.ReverseFind('.');//从左往右的最后一个.  返回值为字符的索引
		fn = fn.Left(j);//此时fn =doudou
//		MessageBox(fn);
    	UpdateData(FALSE);
//		IplImage *srcImg = cvLoadImage(m_openPath);
		//cvNamedWindow(pathName,1);
		//cvShowImage(pathName,srcImg);
		int numUnsharp,numIncreace,numconstrast;
		char charUnsharp[10],charIncreace[10],charConstrast[10];

		GetDlgItem(IDC_EDIT1_UNSHARP)->GetWindowText(charUnsharp,10);
		GetDlgItem(IDC_EDIT2_INCREACE)->GetWindowText(charIncreace,10);		
		GetDlgItem(IDC_EDIT_CONSTAST)->GetWindowText(charConstrast,10);
		numUnsharp = atoi(charUnsharp);
		numIncreace = atoi(charIncreace);
		numconstrast = atoi(charConstrast);

		char *str= fn.GetBuffer(0);
		char filename[200];
		CxImage cimg;
		cimg.Load(m_openPath,CXIMAGE_SUPPORT_BMP);
		if (cimg.IsValid())
		{
			cimg.Light(numIncreace,numconstrast);//图像亮度增强,numIncreace>0,调亮,numIncreace<0,调暗,numconstrast是对比度
			//cimg.Light(20,50);
			for (int i=0;i


  char *itoa(int value, char *string, int radix);
  int value 被转换的整数,char *string 转换后储存的 字符 数组 ,int radix 转换进制数,如2,8,10,16 进制等

你可能感兴趣的:(char,*int,Cstring,memset,memcp)