我在7分钟内编写的以下代码采用短字符串并将所有字母转换为小写:
void tolower(char *out,const char *in){
int l=strlen(in);int cc;int i;
for (i=0;i<l;i++){
cc=(int)in[i]-0;
if (cc >=65 && cc <=90){cc+=0x20;}
out[i]=(char)cc;
}
}
int main(int argc, char *argv[]){
const char *w="aBcDe";
char w2[6]=" ";
tolower(w2,w);
printf("x=%s %s\n",w,w2);
return EXIT_SUCCESS;
}
问题在于我将处理大量数据(每秒大约10KB的数据),我希望能够创建一个尽可能快的功能。
我已经看到那些可以处理机器寄存器的代码,当我过去使用Quick Basic这样的代码时,事情运行得更快。
所以我很好奇如何在我的C程序中使用与32位和64位处理器兼容的机器寄存器(如eax)。
如果我一次只能获取字符串的至少4个字节,然后同时对所有4个字节起作用,那么这将是最好的。
在Quick Basic中,我可以借助mkd $()和cvd()函数实现我的需要。
任何人都知道如何让我发布的功能更快?请不要说升级计算机处理器。
答案 0 :(得分:2)
两种方法,一种更快,取决于系统中的分析。
// tolower()
void Mike_tolower1(char *out, const char *in) {
while ((*out++ = tolower((unsigned char) (*in++) )) != 0);
}
}
// table lookup
void Mike_tolower2(char *out, const char *in) {
// fill in the table
static const char lwr[CHAR_MAX+1] = { '\0', '\1', '\2', ...
'a', 'b' ...
'a', 'b' ...
};
while (*in) {
*out++ = lwr[(unsigned char) (*in++)];
}
}
答案 1 :(得分:1)
最快的方法是不要使用strlen()
,因为它与下面的代码完全相同,它会计算'\0'
出现之前有多少个字符,所以你要遍历字符串两次,做到这一点这样
#include <ctype.h>
void string_tolower(char *string)
{
while (*string != '\0')
{
*string = tolower(*string);
string++;
}
}
并且不要调用你的函数tolower
它是ctype.h
中声明的标准函数,它将单个ascii字符转换为小写字母。
答案 2 :(得分:0)
最快取决于处理器,但速度很快的版本是:
int c;
char *cp;
for (cp = out; 0 != (c=*cp); ++cp) {
if ((c >= 'A') && (c <= 'Z'))
*cp = (char)(c + 'a' - 'A');
}
这包括Jester关于避免strlen的建议。
答案 3 :(得分:0)
如果要刻录一些RAM,则可以计算查找表。例如:
用于创建tolower查找表的伪代码
lookup["AA"] = "aa"
lookup["bb"] = "bb"
这样,您可以一次小写2个字节,并且不需要if语句。
如果你真的想要坚持下去,你可以写一个会尖叫的GPGPU实现。
有关在一次查询表中实现1个字符的示例,请参阅Chux答案。
答案 4 :(得分:0)
我将使用现在基于各种来源构建的代码,包括https://code.google.com/p/stringencoders/wiki/PerformanceAscii。
void tolower1(char *out,const char *in,int lg){
uint32_t x;
const uint32_t* s = (const uint32_t*) in;
uint32_t* d = (uint32_t*) out;
int l=(lg/sizeof(uint32_t));
int i;
for(i=0;i<l;++i){
x=s[i];
x=x-(((x+(0x05050505+0x1a1a1a1a)) >> 2) & 0x20202020);
d[i]=x;
}
}
答案 5 :(得分:0)
I suggest something more like:
#include <ctype.h>
int main()
{
const char *w="aBcDe";
// allow room for nul termination byte
char w2[6]=" " = {'\0'};
// this 'for' statement may need tweaking if
// w[] contains '\0' byte except at the end
for( int i=0; w[i]; i++)
{
w3[i] = tolower(w[i]);
}
printf("x=%s %s\n",w,w2);
return EXIT_SUCCESS;
} // end function: main
or, for a callable function,
that also allows for nul bytes within the string
char *myToLower( int byteCount, char *originalArray )
{
char *lowerArray = NULL;
if( NULL == (lowerArray = malloc(byteCount) ) )
{ // then, malloc failed
perror( "malloc failed" );
exit( EXIT_FAILURE );
}
// implied else, malloc successful
for( int i=0; i< byteCount; i++ )
{
lowerArray[i] = tolower(originalArray[i]);
}
return( lowerArray );
} // end function: myToLower