C++Builder 程序员博客
6 Nov
比如:要在一个动态参数中查找是否有DY?如DY001中获取前两个字母判断是否DY?或者是ZX等?
用什么函数?怎么做?
希望能给个例子。
谢谢。
如果是C的字串,且在头上判,可用strncmp
也可用strstr
如果是AnsiString可用SubString或LeftStr取2位再判
也可直接用Pos判
字串处理是C/C++的强项
SubString(1,2)
把字串赋值给一个ITMP
然后,
if(ITMP.SubString(1,2)=="DY"||ITMP.SubString(1,2)=="ZX")
{
…..
}
SubString(1,2)
4楼正解
SubString(1,2)
Copy(str,1,2);
AnsiString as = "DY001";
if (as[1] == 'D' && as[2] == 'Y')
{
//….
}
28 Oct
我在bitmap上作图,用TextOutA函数输出字符串,我想让字符串右对齐,请问各位达人如何办到?谢谢!
for(int i = Text->Length()-1;i>0;i–) { str = Text.SubString(Text->Length()-i,1); Bufmap->Canvas->TextOutA(Bufmap->Width-i,0,str); }
计算一下各字符串最大的宽度,然后在不足的字符串前面加入空格,这样字符串就都对齐了,直接按照默认输出(左对齐)即可
得到字符串的宽度,然后
strwidth = Bufmap->Canvas->TextWidth
Bufmap->Canvas->TextOutA(Bufmap->Width-strwidth,0,str);
没有个直接的函数类的吗。字符串的宽度不一定啊。
看得出你是做图像处理甚至流媒体传输的。没有直接的函数,即使是右对齐,也没有直接的函数。
Bufmap->Canvas->TextWidth(Edit->SelText);//字符串的宽度
根据这个,再结合我在2楼的代码,你自己调整下算法。
哎~,还是.net好用啊。哪用这么麻烦。哎~,无奈
汗… 自己算下不就得了,总得干点事情撒…
22 Oct
根据硬盘序列号算出注册号,我用的下面的算法 http://topic.csdn.net/t/20040918/11/3385562.html这个帖子的算法
if(Ser=="" || Ser.Length() <8) Ser="MR771007";
if(Mode=="" || Mode.Length() <2) Mode="WL";
AnsiString ID=UpperCase(Mode.SubString(1,2) + Ser.SubString(1,8));
AnsiString sourID="";
char tmpID[10];
strcpy(tmpID,ID.c_str());
for(int i=0;i <10;i++)
{
sourID+=IntToStr(tmpID[i]).SubString(1,1);
sourID+=IntToStr(tmpID[i]).SubString(2,1);
}
char showID[21];
strcpy(showID,sourID.c_str());
char tmpChar;
tmpChar=showID[0];showID[0]=showID[5];showID[5]=tmpChar;
tmpChar=showID[2];showID[2]=showID[7];showID[7]=tmpChar;
tmpChar=showID[4];showID[4]=showID[9];showID[9]=tmpChar;
tmpChar=showID[10];showID[10]=showID[15];showID[15]=tmpChar;
tmpChar=showID[12];showID[12]=showID[17];showID[17]=tmpChar;
tmpChar=showID[14];showID[14]=showID[19];showID[19]=tmpChar;
AnsiString desID=""; //83845-17488-52488-16982 //878855344816488
for(int i=0;i <20;i++)
{
desID+=AnsiString(showID[i]);
}
desID是算出的注册号
—
我要把算出来的注册号在还原成硬盘的序列号,该怎么写?看了帖子没明白怎么还原成硬盘序列号
帮帮忙谢谢
你能加密,肯定能解密啊,就是反运算而已
自己写的算法自己回溯吧
20 Oct
字符串A是由数字组成的,每2位为一个数字,如"05060203182308"
长度不固定,怎样按照数字大小进行排序呢?
我的算法:用一个数组a[i],i=A.lenth()/2;
然后把数字赋给数组,再对数组排序,完了再拼成字符串B,B即为结果
不过感觉比较笨,大家有没有好一些的算法,求教~
应该都差不多吧,
不过你可以用冒泡,或快速排序法。
主要是你这串字符串没有分割标记,要是有个空格,逗号什么的,把数字隔开也好了。
就目前这个状况,你的思路是正确的,能简化的,也就是在排序算法上。可是数字的排序算法扯来扯去也就哪几种了。
还有,大部分能实现结果的算法就是好算法了,因为在PC上,这些算法时间量并不是要求很严格的。
数组排序,推荐堆排序。如果字符串不是很长,冒泡比较简单。
如果只有两位,而且还是不重复的,桶排序简单。哈哈
而且桶排序的复杂度只有 f(N),缺点是太大的数组无法支持。
堆排序是f(NlogN)
String str1 = "05060203182308";
TStringList *sg = new TStringList;
for(int i = 1; i <= str1.Length() - 1; i=i+2)
{
String str = str1.SubString(i,2);
if(sg->Count == 0)
{
sg->Add(str);
}
else if(str >= sg->Strings[sg->Count - 1])
{
sg->Add(str);
}
else
{
for(int j = 0; j < sg->Count; j++)
{
if(str < sg->Strings[j])
{
sg->Insert(j,str);
break;
}
}
}
}
String mystr = "";
for(int i = 0; i < sg->Count; i++)
{
mystr += sg->Strings[i];
}
delete sg;
ShowMessage(mystr);
试一下效率应该还可以
嗯,ls的方法不错~
等下看看yuanreid说的桶排序是啥 - -
桶排序针对该问题的处理:
创建一个100元素的bool数组,sort[100]。
while循环你的字符串,每次获取两个字符转换为int,将下标为int的bool数组值设置为true,
即sort[int值]=true
直到字符串处理结束。
然后sort数组中值为true的表示其下标值在你的字符串中出现过,顺序是排好的。一个for循环就将排序的字符串生成了。
String str1 = "05060203182308"; TStringList *sg = new TStringList; for(int i = 1; i <= str1.Length() - 1; i=i+2) { String str = str1.SubString(i,2); if(sg->Count == 0) { sg->Add(str); } else if(str >= sg->Strings[sg->Count - 1]) { sg->Add(str); } else { for(int j = 0; j < sg->Count; j++) { if(str < sg->Strings[j]) { sg->Insert(j,str); break; } } } } String mystr = ""; for(int i = 0; i < sg->Count; i++) { mystr += sg->Strings[i]; } delete sg; ShowMessage(mystr);
如果借助TStringList的话,就可以直接使用Sort()方法了,不需要自己判断排序了,我以为是要考虑算法问题。
AnsiString str = "01993122336693"; TStringList* a = new TStringList(); while(str.Length()>0) { a->Add(str.SubString(1,2)); str.Delete(1,2); } a->Sort(); Memo1->Lines = a;
不太清楚sort是怎么做的
但是直接sort的话估计不会按照2位一个数那样排序吧?
比如"0103050907"
排序完的结果估计就是"0000013579"了
20 Oct
rt,我用bcb6封装了一个继承自TPanel的控件。现在其他的功能都调通了,就是有一个要戒收字符串的函数搞不定。
比如说,我在默认接口里加入了一个HRESLULT f([in]BSTR b1,[in]long l2,[out,retval]long* l3);用BCB导入OCX后,这个方法对应为 long f(LPSTR,long)型。
但是我调用时出现内存错误。哪么我应该怎样调用才能避免错误呢?
我想问一下这种情怎样处理?怎样才能让的方法的为LPSTR?LPCTSTR呢?
ps:bcb的类型库编辑器是不是有问题啊?怎么我以refresh类型库的改动,机器就生成的代码就变得乱七八糟的?
改成这样试试,我在ActiveX控件中基本都是用char*,免去很多麻烦
HRESLULT f([in]char* b1,[in]long l2,[out,retval]long* l3);
改成这样试试,我在ActiveX控件中基本都是用char*,免去很多麻烦
HRESLULT f([in]char* b1,[in]long l2,[out,retval]long* l3);
//————————————
我开始也是这样写的,然后我用VC导入,发现相应的方法被注释掉了……
upup
不会吧,你试试LPSTR,这个肯定好使。我是在BCB的控件中char*,BCB自动转换到ActiveX控件后,再改成参数为char*,其实就是LPSTR,你试试看。
我知道该怎么弄了,谢谢。
在BCB里写OCX时用BSTR类型,VC导入时就是LPCTSTR了
5 Oct
ListBox应该是OwnerDraw的。并且我用Spy++截获了一下它发送接收的消息
<00001> 002F0502 S LB_GETCOUNT wParam:00000000 lParam:00000000
<00002> 002F0502 R LB_GETCOUNT cItems:0 [lResult:00000000]
<00003> 002F0502 S LB_GETCOUNT wParam:00000000 lParam:00000000
<00004> 002F0502 R LB_GETCOUNT cItems:0 [lResult:00000000]
<00005> 002F0502 S LB_INSERTSTRING index:0 lpsz:003F47A0 [wParam:00000000 lParam:003F47A0]
<00006> 002F0502 S LB_GETITEMDATA index:0 [wParam:00000000 lParam:00000000]
<00007> 002F0502 R LB_GETITEMDATA dwData:003F47A0 [lResult:003F47A0]
<00008> 002F0502 S LB_GETITEMDATA index:0 [wParam:00000000 lParam:00000000]
<00009> 002F0502 R LB_GETITEMDATA dwData:003F47A0 [lResult:003F47A0]
<00010> 002F0502 R LB_INSERTSTRING dwData:00000000 [lResult:00000000]
<00011> 002F0502 S LB_GETCOUNT wParam:00000000 lParam:00000000
<00012> 002F0502 R LB_GETCOUNT cItems:1 [lResult:00000001]
<00013> 002F0502 S LB_INSERTSTRING index:0 lpsz:003F5AE8 [wParam:00000000 lParam:003F5AE8]
<00014> 002F0502 S LB_GETITEMDATA index:0 [wParam:00000000 lParam:00000000]
<00015> 002F0502 R LB_GETITEMDATA dwData:003F5AE8 [lResult:003F5AE8]
<00016> 002F0502 S LB_GETITEMDATA index:0 [wParam:00000000 lParam:00000000]
<00017> 002F0502 R LB_GETITEMDATA dwData:003F5AE8 [lResult:003F5AE8]
<00018> 002F0502 R LB_INSERTSTRING dwData:00000000 [lResult:00000000]
<00019> 002F0502 S LB_GETCOUNT wParam:00000000 lParam:00000000
<00020> 002F0502 R LB_GETCOUNT cItems:2 [lResult:00000002]
<00021> 002F0502 S LB_INSERTSTRING index:0 lpsz:003F5E48 [wParam:00000000 lParam:003F5E48]
<00022> 002F0502 S LB_GETITEMDATA index:0 [wParam:00000000 lParam:00000000]
<00023> 002F0502 R LB_GETITEMDATA dwData:003F5E48 [lResult:003F5E48]
<00024> 002F0502 S LB_GETITEMDATA index:0 [wParam:00000000 lParam:00000000]
<00025> 002F0502 R LB_GETITEMDATA dwData:003F5E48 [lResult:003F5E48]
<00026> 002F0502 R LB_INSERTSTRING dwData:00000000 [lResult:00000000]
<00027> 002F0502 S LB_GETCOUNT wParam:00000000 lParam:00000000
<00028> 002F0502 R LB_GETCOUNT cItems:3 [lResult:00000003]
<00029> 002F0502 S LB_GETITEMDATA index:0 [wParam:00000000 lParam:00000000]
<00030> 002F0502 R LB_GETITEMDATA dwData:003F5E48 [lResult:003F5E48]
<00031> 002F0502 S LB_GETITEMDATA index:1 [wParam:00000001 lParam:00000000]
<00032> 002F0502 R LB_GETITEMDATA dwData:003F5AE8 [lResult:003F5AE8]
<00033> 002F0502 S LB_GETITEMDATA index:2 [wParam:00000002 lParam:00000000]
<00034> 002F0502 R LB_GETITEMDATA dwData:003F47A0 [lResult:003F47A0]
DWORD test = SendMessage(hListBox, LB_GETITEMDATA, 0, 0); SendMessage(hListBox, LB_INSERTSTRING, 0, test);
以上代码成功向该ListBox添加一行和原第一行相同的文字。
DWORD test是一个地址?可以当指针用吗?
我怎么能获得它的具体内容并赋值给char * str?谢谢!
既然是要获取ListBox的某行字符串,直接用LB_GETTEXT消息就可以了。
ListBox1->Clear(); //分2个部分1个是串,后面的串携带的数据 ListBox1->AddItem("GGG",(TObject*)1999); //下面的test就是1999,是串的附加数据,不是串的内容 DWORD test = SendMessage(ListBox1->Handle , LB_GETITEMDATA, 0, 0); char lpszText[]="hello world"; SendMessage(ListBox1->Handle , LB_INSERTSTRING, 0, (long) lpszText); //获取第0项条目的串,放入lpszText SendMessage(ListBox1->Handle , LB_GETTEXT, 0, (long) lpszText);
补充一下是别人程序里的ListBox。 该程序是用VC写的
用Spy++截获了一下ListBox的消息,
发现我用GETITEMDATA获得的只是该程序INSERTSTRING时候的LPARAM参数
这个值是不是对于这个程序所在内存的起始位置 关于字符串的偏移量?
我现在获得的是一个DWORD值。我只是想把它的字符串找回来.GETTEXT获得的只是一些乱码
LB_GETTEXT可以获取其他进程中的ListBox的字符串,不过建议在GETTEXT之前,先用LB_GETTEXTLENGTH获取字符串的长度,开辟适当的缓冲来接收文本。
如果可行的话,你把那个VC程序发给我参观一下:cbfans#163.com
关注下。。
学习~~
用LB_GETTEXT试试:
An application sends an LB_GETTEXT message to retrieve a string from a list box.
LB_GETTEXT
wParam = (WPARAM) index; // item index
lParam = (LPARAM) (LPCTSTR) lpszBuffer; // address of buffer
取第一个:
char *s;
SendMessage(hListBox, LB_GETTEXT , 0, s);
取第二项
SendMessage(hListBox, LB_GETTEXT , 1, s);
GETTEXT,LB_GETTEXTLEN我都试过了。
我已经把程序发给了老妖大哥。
期待他的研究吧~
12 Sep
怎样把一个带数字,带汉字和英文字符的字符串分解出来。
例如 str="1234你好hello";
分解成 str1="1234"; str2="你好"; str3="hello".
WideString chinese=""; WideString source="1234你好hello"; int len = source.Length(); for (int i = 0 ;i<len;i++ ) { if (source[i] > 128 ) { ShowMessage(WideString(source[i])); chinese = chinese + WideString(source[i]); } } ShowMessage(chinese);
逐一判断字符的ASIC码,就可以区分出来了
具体怎么判断?
正确
字符串操作用正则表达式
WideString source="1234你好hello";
int len = source.Length();
for (int i = 0 ;i <len;i++ )
{
if (source[i] > 128 )
{
ShowMessage(WideString(source[i]));
chinese = chinese + WideString(source[i]);
}
else ((source[i] >= 0×30) && (source[i] <= 0×39))
{
dig = dig + WideString(source[i]);
}
else
{
english = english+ WideString(source[i]);
}
}
18 Aug
sql server2000 字符串max的问题
一个字段,char(20)的,用select max(lsh) as mylsh from DB2008 where bumen='企划部' and ruzahng='是';
查询的结果,全是9999,好几十个大于一万的号。比如‘10029’等。
select max(cast(lsh as int)) as mylsh from DB2008 where bumen='企划部' and ruzahng='是';
转成整型再max吧
谢谢。还是对sql server自身带的函数和方法不熟啊。给分。感谢帮助。
18 Aug
在网上找到了GB2312转化为utf-8的算法:
void CChineseCodeLib::UTF_8ToUnicode(WCHAR* pOut,char *pText) { char* uchar = (char *)pOut; uchar[1] = ((pText[0] & 0×0F) << 4) + ((pText[1] >> 2) & 0×0F); uchar[0] = ((pText[1] & 0×03) << 6) + (pText[2] & 0×3F); return; } void CChineseCodeLib::UnicodeToGB2312(char* pOut,WCHAR *uData) { WideCharToMultiByte(CP_ACP,NULL,uData,1,pOut,sizeof(WCHAR),NULL,NULL); return; } void CChineseCodeLib::Gb2312ToUnicode(WCHAR* pOut,char *gbBuffer) { ::MultiByteToWideChar(CP_ACP,MB_PRECOMPOSED,gbBuffer,2,pOut,1); return; } void CChineseCodeLib::UnicodeToUTF_8(char* pOut,WCHAR* pText) { // 注意 WCHAR高低字的顺序,低字节在前,高字节在后 char* pchar = (char *)pText; pOut[0] = (0xE0 | ((pchar[1] & 0xF0) >> 4)); pOut[1] = (0×80 | ((pchar[1] & 0×0F) << 2)) + ((pchar[1] & 0xC0) >> 6); pOut[2] = (0×80 | (pchar[0] & 0×3F)); return; } void CChineseCodeLib::GB2312ToUTF_8(char *pOut,char *pText, int pLen) { char buf[4]; char* rst = new char[pLen + (pLen >> 2) + 2]; memset(buf,0,4); memset(rst,0,pLen + (pLen >> 2) + 2); int i = 0; int j = 0; while(i < pLen) { //如果是英文直接复制就可以 if( *(pText + i) >= 0) { rst[j++] = pText[i++]; } else { WCHAR pbuffer; Gb2312ToUnicode(&pbuffer,pText+i); UnicodeToUTF_8(buf,&pbuffer); unsigned short int tmp = 0; tmp = rst[j] = buf[0]; tmp = rst[j+1] = buf[1]; tmp = rst[j+2] = buf[2]; j += 3; i += 2; } } rst[j] = ‘\0‘; //返回结果 strcpy(pOut,rst); delete []rst; return; } void CChineseCodeLib::UTF_8ToGB2312(string &pOut, char *pText, int pLen) { char * newBuf = new char[pLen]; char Ctemp[4]; memset(Ctemp,0,4); int i =0; int j = 0; while(i < pLen) { if(pText[i] > 0) { newBuf[j++] = pText[i++]; } else { WCHAR Wtemp; UTF_8ToUnicode(&Wtemp,pText + i); UnicodeToGB2312(Ctemp,&Wtemp); newBuf[j] = Ctemp[0]; newBuf[j + 1] = Ctemp[1]; i += 3; j += 2; } } newBuf[j] = ‘\0‘; pOut = newBuf; delete []newBuf; return; }
用下面的代码段调用
AnsiString srcStr = "中国加油,奥运加油"; int len = srcStr.Length(); char *dest = new char[len]; CChineseCodeLib *codeLib = new CChineseCodeLib(); codeLib->GB2312ToUTF_8(dest,srcStr.c_str(),len); TStringList *tSqlList = new TStringList(); tSqlList->Add(dest); tSqlList->SaveToFile("e:/test.txt"); delete []dest; delete codeLib; delete tSqlList;
最后得到的结果为乱码:
涔櫧鍓犳惫锟屽ゥ杈愬墵姹\xB9
是怎么回事呢?是调用不正确还是算法本身有问题?
小弟刚刚学C++,请高手们指点!!
你应该用ansi转UTF-8,不是GB
mark
BCB 有直接的API使用。
Unit
System
Category
character set conversions
extern PACKAGE UTF8String __fastcall AnsiToUtf8(const AnsiString S);
Description
AnsiToUtf8 converts the string specified by S, which uses the ANSI encoding system, to UTF-8.
LZ的做法是错误的;
utf8是针对unicode的另外一种存储方法;
我有现成的代码,已经经过实际使用了,绝对没有问题;
大体的方法是:
GB2312转到unicode,unicode再转utf8;
GB2312转unicode的办法,在CB里面,简单的要死:
AnsiString gb_str = "xxxx";
WideString un_str = gb_str;
wchar_t * pwstr = un_str.b_cstr();//pwstr就是unicode的字串了,每个字符占用2字,0结尾的;
unicode转到utf8,我是借用的linux的NLS_UTF8的内核代码,高效可靠;
如果你需要,我可以发一份给你;
29 Jul
Read_usb1(0,rcv_data,&Length); //从USB接收数据放入rcv_data,这里的数据正常
for(i=0;i <Length;i++)
{
sprintf(temp,"%c",rcv_data[i]); //一执行这条语句就有我下面说的问题
ascr+=temp;
}
Form1->Richedit_data->Text=ascr;
上面那段简单的代码,在执行过程中rcv_data里的值为什么会莫名其妙的多处一些字符,而且覆盖我前面的数据?
我反复调试了几遍发现只要一执行sprintf函数就会出现字符。
数组没有越界。
rcv_data,这里的数据正常 吗?
你设下断点看看那里的传入的数据吧.一步步来排除.
sprintf(temp,"%c",rcv_data[i]);
是打印字符的,可能你发送的数据就有非显示的字符,使用 0x%02x, 作为参数调试一下
还有 ascr 是否每次都初始化?
另外 sprintf 函数是非线程安全的,线程安全的函数为 wsprintf
sprintf(temp,"%c",rcv_data[i]); //一执行这条语句就有我下面说的问题
ascr+=temp;
temp的类型没见到,根据语法很可能是 char *temp;
ascr的类型也没见到,很可能中: AnsiString;
问题就出在这个语句 ascr+=temp,
如果只加一个字符应该: adcr += temp[0];
否则 temp是一个char *类型,被自动转换成 AnsiString,
而实际只有一个字符,也没有尾0,所以,temp后面的垃圾字符全写进串Acr中了
解决办法有三:adcr += temp[0];
adcr += *temp; // 跟上一样
temp[1]=0;adcr+=temp; // 有尾0就没关系了