Arrays “快速提取方法”;“有效”;c中的子串

Arrays “快速提取方法”;“有效”;c中的子串,arrays,c,string,memory,c-strings,Arrays,C,String,Memory,C Strings,我编写了两个函数从字符串中提取“有效”子字符串,这意味着子字符串只能包含字母和数字。但是,如果要检查的字符串太长,即使性能差距不太明显,它们也会开始失去性能,我对此并不感到太激动。有没有更快的方法来“验证”字符串?这是我的密码: #include <stdlib.h> #include <stdio.h> #include <ctype.h> #include <wchar.h> wchar_t* validstr(wchar_t* src, w

我编写了两个函数从字符串中提取“有效”子字符串,这意味着子字符串只能包含字母和数字。但是,如果要检查的字符串太长,即使性能差距不太明显,它们也会开始失去性能,我对此并不感到太激动。有没有更快的方法来“验证”字符串?这是我的密码:

#include <stdlib.h>
#include <stdio.h>
#include <ctype.h>
#include <wchar.h>

wchar_t* validstr(wchar_t* src, wchar_t* cc, unsigned int* index) {
    wchar_t* valid = calloc(1, sizeof(wchar_t));
    while (isalpha(*cc) || isdigit(*cc)) {
        valid = realloc(valid, (wcslen(valid) + 2) * sizeof(wchar_t));
        wcscat(valid, (wchar_t[]) { *cc, 0 });
        ++* index;
        *cc = src[*index];
    }
    return valid;
}

wchar_t* validstr2(wchar_t* src) {
    wchar_t* valid = calloc(1, sizeof(wchar_t));
    while (isalpha(*src) || isdigit(*src)) {
        valid = realloc(valid, (wcslen(valid) + 2) * sizeof(wchar_t));
        wcscat(valid, (wchar_t[]) { *src, 0 });
        src++;
    }
    return valid;
}

int main() {
    wchar_t* str = L"valid10+(notvalidanymore";

    // usage for validstr()
    wchar_t current = str[0];
    unsigned int index = 0;
    printf("%ls\n", validstr(str, &current, &index));

    // usage for validstr2()
    printf("%ls\n", validstr2(str));
}
#包括
#包括
#包括
#包括
wchar_t*validstr(wchar_t*src、wchar_t*cc、无符号整数*索引){
wchar_t*valid=calloc(1,sizeof(wchar_t));
while(isalpha(*cc)| isdigit(*cc)){
valid=realloc(valid,(wcslen(valid)+2)*sizeof(wchar_t));
wcscat(有效,(wchar_t[]){*cc,0});
++*指数;
*cc=src[*指数];
}
返回有效;
}
wchar_t*有效性TR2(wchar_t*src){
wchar_t*valid=calloc(1,sizeof(wchar_t));
while(isalpha(*src)| isdigit(*src)){
valid=realloc(valid,(wcslen(valid)+2)*sizeof(wchar_t));
wcscat(有效,(wchar_t[]){*src,0});
src++;
}
返回有效;
}
int main(){
wchar_t*str=L“有效10+(notvalidanymore);
//validstr()的用法
wchar_t current=str[0];
无符号整数索引=0;
printf(“%ls\n”,validstr(str、current和index));
//validstr2()的用法
printf(“%ls\n”,validstr2(str));
}

您应该尽可能避免重新分配

因此,您可以首先计算与您相关的字符:

size_t length = 0
for(wchar_t* tmp = cc; *tmp && iswalnum(*tmp); ++tmp)
{
    ++length
}
请注意,
isalnum
函数包含字母和数字,但在任何情况下都应使用宽字符函数(
isw[…]
,请注意附加的
w

计算完毕后,只需复制感兴趣的值:

wchar_t* valid = malloc((length + 1) * sizeof(wchar_t));
//                                ^ terminating null character!

memcpy(valid, cc, length*sizeof(wchar_t));
valid[length] = 0;

// for validstr:
memcpy(cc, src, length*sizeof(wchar_t));
*index = length;
我更喜欢这里的
malloc
而不是
calloc
,因为不需要对数组进行零初始化,它无论如何都会被覆盖

请注意,
validstr
的上述版本与您的实现略有不同:您首先递增,然后复制字符,这将跳过
str
的第一个字符。我的版本从第一个字符开始复制。如果确实要跳过第一个字符,则从第一个字符开始复制,然后您将你又好了:

memcpy(cc, src + 1, length);

请注意此版本(
validstr(wchar\u t*、wchar\u t*、unsigned int*)
)无论如何,对我来说并不十分安全,您可能很容易读取超出src界限的内容,这将导致未定义的行为–除非您总是以任何方式保证
src
至少与复制的子字符串一样长。

realloc在循环中会非常慢。为什么不使用一个循环,然后分配空间并在循环后复制数据?是否有理由需要在循环内重新定位?我只保留字符串,然后将所有应保留的字符移到前面,跳过那些不相关的字符。如果您绝对希望将分配的内存减到最小,则首先计算剩余的字符@Aconcagua他的代码没有保留所有有效字符-它只保留初始子字符串,但不包括第一个无效字符。因此,他可以对字符串进行strdup,然后用字符串终止符替换第一个无效字符。这似乎是一个很好的方法-如果有一个宽字符版本的strdup。这就是我的想法nking:它仍然需要循环,但它只在循环内部增加,所以性能不是真正的问题,因为时间完全被calloc掩盖了。实际上,calloc似乎是一种浪费-如果你要立即对其进行写入,你不需要初始化内存。那么@JerryJeremiah我的错呢,没有注意到。OnPOSIX,有并且似乎windows也支持它。承认,不能保证一般的可移植性。。。