我想用utf8支持更好的性能来编写好的功能。
Replace()
候选人:char* replace(char* orig, char* rep, char* with)
{
//33-34
char* result; // the return string
char* ins; // the next insert point
char* tmp; // varies
size_t len_rep; // length of rep
size_t len_with; // length of with
size_t len_front; // distance between rep and end of last rep
int count; // number of replacements
/* char* strstr(char const* s1, char const* s2);
retourne un pointeur vers la première occurrence de s2 dans s1
(ou NULL si s2 n’est pas incluse dans s1). */
if (!orig)
return NULL;
if (!rep || !(len_rep = strlen(rep)))
return NULL;
if (!(ins = strstr(orig, rep)))
return NULL;
if (!with)
with = "";
len_with = strlen(with);
/* { initialisation;
while (condition) {
Instructions
mise_à_jour;
} }*/
// compte le nombre d'occurences de la chaîne à remplacer
for (count = 0; (tmp = strstr(ins, rep)); ++count) {
ins = tmp + len_rep;
}
// allocation de mémoire pour la nouvelle chaîne
tmp = result = malloc(strlen(orig) + (len_with - len_rep) * count + 1);
if (!result)
return NULL;
/* char* strcpy(char* dest, char const* src);
copie la chaîne src dans la chaîne dest. Retourne dest.
Attention ! aucune vérification de taille n’est effectuée ! */
/* char* strncpy(char* dest, char const* src, size_t n);
copie les n premiers caractères de src dans dest. Retourne dest.
Attention ! n’ajoute pas le '\0' à la fin si src contient plus de n
caractères !*/
// from here on,
// tmp points to the end of the result string
// ins points to the next occurrence of rep in orig
// orig points to the remainder of orig after "end of rep"
while (count--) { // count évaluée, puis incrémentée
// donc ici tant que count est > 0
ins = strstr(orig, rep);
len_front = ins - orig;
tmp = strncpy(tmp, orig, len_front) + len_front;
tmp = strcpy(tmp, with) + len_with;
orig += len_front + len_rep; // move to next "end of rep"
}
strcpy(tmp, orig);
return result;
}
char* replace8(char *str, char *old,char *new)
{
//1.2 :||||||||||
int i, count = 0;
int newlen = strlen(new);
int oldlen = strlen(old);
for (i = 0; str[i]; ++i)
if (strstr(&str[i], old) == &str[i])
++count, i += oldlen - 1;
char *ret = (char *) calloc(i + 1 + count * (newlen - oldlen), sizeof(char));
if (!ret) return "";
i = 0;
while (*str)
if (strstr(str, old) == str)
strcpy(&ret[i], new),
i += newlen,
str += oldlen;
else
ret[i++] = *str++;
ret[i] = '\0';
return ret;
}
char *replace7(char *orig, char *rep, char *with)
{
//33-34-35
char *result; // the return string
char *ins; // the next insert point
char *tmp; // varies
int len_rep; // length of rep
int len_with; // length of with
int len_front; // distance between rep and end of last rep
int count; // number of replacements
if (!orig)
{
return NULL;
}
if (!rep)
{
rep = "";
}
len_rep = strlen(rep);
if (!with)
{
with = "";
}
len_with = strlen(with);
ins = orig;
for (count = 0; tmp = strstr(ins, rep); ++count)
{
ins = tmp + len_rep;
}
// first time through the loop, all the variable are set correctly
// from here on,
// tmp points to the end of the result string
// ins points to the next occurrence of rep in orig
// orig points to the remainder of orig after "end of rep"
tmp = result = malloc(strlen(orig) + (len_with - len_rep) * count + 1);
if (!result)
{
return NULL;
}
while (count--)
{
ins = strstr(orig, rep);
len_front = ins - orig;
tmp = strncpy(tmp, orig, len_front) + len_front;
tmp = strcpy(tmp, with) + len_with;
orig += len_front + len_rep; // move to next "end of rep"
}
strcpy(tmp, orig);
return result;
}
char *replace6(char *st, char *orig, char *repl)
{
//17-18
static char buffer[4000];
char *ch;
if (!(ch = strstr(st, orig)))
return st;
strncpy(buffer, st, ch-st);
buffer[ch-st] = 0;
sprintf(buffer+(ch-st), "%s%s", repl, ch+strlen(orig));
return buffer;
}
char* replace3(char* s, char* term, char* new_term)
{
//error
char *nw = NULL, *pos;
char *cur = s;
while(pos = strstr(cur, term))
{
nw = (char*)realloc(nw, pos - cur + strlen(new_term));
strncat(nw, cur, pos-cur);
strcat(nw, new_term);
cur = pos + strlen(term);
}
strcat(nw, cur);
free(s);
return nw;
}
char *replace2(char *original,char *pattern,char *replacement)
{
//34-37
size_t replen = strlen(replacement);
size_t patlen = strlen(pattern);
size_t orilen = strlen(original);
size_t patcnt = 0;
char * oriptr;
char * patloc;
// find how many times the pattern occurs in the original string
for (oriptr = original; patloc = strstr(oriptr, pattern); oriptr = patloc + patlen)
{
patcnt++;
}
{
// allocate memory for the new string
size_t retlen = orilen + patcnt * (replen - patlen);
char * const returned = (char *) malloc( sizeof(char) * (retlen + 1) );
if (returned != NULL)
{
// copy the original string,
// replacing all the instances of the pattern
char * retptr = returned;
for (oriptr = original; patloc = strstr(oriptr, pattern); oriptr = patloc + patlen)
{
size_t skplen = patloc - oriptr;
// copy the section until the occurence of the pattern
strncpy(retptr, oriptr, skplen);
retptr += skplen;
// copy the replacement
strncpy(retptr, replacement, replen);
retptr += replen;
}
// copy the rest of the string.
strcpy(retptr, oriptr);
}
return returned;
}
}
char *replace4(char *string, char *oldpiece, char *newpiece)
{
//20-21
int str_index, newstr_index, oldpiece_index, end,
new_len, old_len, cpy_len;
char *c;
static char newstring[10000];
if ((c = (char *) strstr(string, oldpiece)) == NULL)
return string;
new_len = strlen(newpiece);
old_len = strlen(oldpiece);
//str = strlen(string);
end = strlen(string) - old_len;
//int count;
//for (count = 0; (strstr(oldpiece, newpiece)); ++count){}
//newstring = malloc(str + (old_len - new_len) * count + 1);
oldpiece_index = c - string;
newstr_index = 0;
str_index = 0;
while(str_index <= end && c != NULL)
{
/* Copy characters from the left of matched pattern occurence */
cpy_len = oldpiece_index-str_index;
strncpy(newstring+newstr_index, string+str_index, cpy_len);
newstr_index += cpy_len;
str_index += cpy_len;
/* Copy replacement characters instead of matched pattern */
///*newstring=realloc(newstring,sizeof(newstring)+new_len+old_len+end+newstr_index);
strcpy(newstring+newstr_index, newpiece);
newstr_index += new_len;
str_index += old_len;
/* Check for another pattern match */
if((c = (char *) strstr(string+str_index, oldpiece)) != NULL)
oldpiece_index = c - string;
}
/* Copy remaining characters from the right of last matched pattern */
strcpy(newstring+newstr_index,
string+str_index);
return newstring;
}
char *replace5(char *orig, char *rep, char *with)
{
//32-33-35
char *result;
char *ins;
char *tmp;
int len_rep;
int len_with;
int len_front;
int count;
if (!orig)
return NULL;
if (!rep)
rep = "";
len_rep = strlen(rep);
if (!with)
with = "";
len_with = strlen(with);
ins = orig;
for (count = 0; (tmp = strstr(ins, rep)); ++count) {
ins = tmp + len_rep;
}
tmp = result = malloc(strlen(orig) + (len_with - len_rep) * count + 1);
if (!result)
return NULL;
while (count--) {
ins = strstr(orig, rep);
len_front = ins - orig;
tmp = strncpy(tmp, orig, len_front) + len_front;
tmp = strcpy(tmp, with) + len_with;
orig += len_front + len_rep;
}
strcpy(tmp, orig);
return result;
}
replace4()
和replace6()
来自其他,但不是malloc,realloc。
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <inttypes.h>
#include <assert.h>
#include <stdint.h>
#include <sys/stat.h>
#include <stdarg.h>
char *temp;
int main()
{
for(int current=1;current<=80000;current++)
{
temp=/*replace6*//*replace3*/replace4("1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890","0","black");
//printf("%s",temp);
}
return 0;
}
replace()
功能?replace4()
或replace6()
吗?答案 0 :(得分:2)
非常像您提供的解决方案都不是您可以编写的最快的平衡性能比较。
首先,关于功能4和6有几点:
函数3很可能比其他函数执行得更差,因为它会多次分配内存,可能的例外情况是,如果缓冲区已经足够大,结果可能无效。
对于其余的功能,我注意到它们遵循这种结构模式:
在这一点上分离和征服并独立解决这些问题可能更容易,因为内存分配可能会占到呼叫成本的很大一部分。因此,目前还不清楚,如果你可以获得任何东西,例如迭代字符串的一部分,在输入的缓存大小的块上进行替换,并在第一个块之后使用启发式估计总大小。然而,使用启发式进行分配可能没问题,但您必须平衡昂贵的重新分配/副本以浪费内存。
关于1.我会说,如果你真的想知道你需要的确切内存量,并且根据个人经验和SO我会说strstr
你无法避免全长扫描通常非常快。我希望在这里优化得到低回报。
第3部分在这方面是类似的,因为使用c std-lib复制函数可能会导致编译器使用一些手工制作的程序集来破坏你可以编写的所有内容。
然而,我认为第二步可以很好地优化:
这意味着如果你提供一个允许调用者传入缓冲区的调用,你可能会更快。
因此,你可以实现1.作为一个函数,它计算字符串中模式的出现次数(很可能是非常有用的),2。可以由用户完成,3。可以是一个函数假设它收到足够大的输出缓冲区。如果您希望方便地进行一次调用,您可以在第4个帮助器内部使用这些函数,尽管您可能希望至少检查输入的大小并在适当的情况下就地工作。< / p>
关于您的测试,您目前只进行一次检查,其中涵盖了非常简单的案例。如果您想以有意义的方式测试呼叫的性能,至少应考虑以下因素:
查看影响算法性能的维度,例如:
在预热时间之前进行几次迭代(分支预测等)
最终,如果你真的知道你做了什么,要知道你可以看看装配并尝试改进它。此外,如果您可以排除某些情况,因为您知道您在一般问题域的特殊子空间中工作,那么通常可以通过针对您的案例执行特殊解决方案来获得最大收益。