这是对C的好SUBSTR? [英] Is this a good substr for C?

查看:134
本文介绍了这是对C的好SUBSTR?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

又见<一个href=\"http://stackoverflow.com/questions/874161/c-tokenizer-and-it-returns-empty-too-when-fields-are-missing-yay\">C标记生成器


下面是一个快速SUBSTR()对于C,我写的(是的,变量初始化需要移动启动功能等,但你的想法)

我见过SUBSTR许多聪明的实现()是简单的班轮调用函数strncpy()!

他们都错了(函数strncpy不保证空终止,因此调用可能不会产生一个正确子!)

下面的东西也许更好?

带出的错误!

 的char * SUBSTR(为const char *文本,诠释nStartingPos,诠释nRun)
{
    字符* emptyString =的strdup(); / *来吧!这不能不* /    如果(文字== NULL)回报emptyString;    INT在textlen = strlen的(文本);    --nStartingPos;    如果((nStartingPos℃,)||(nRun&下; = 0)||(在textlen == 0)||(在textlen&下; nStartingPos))返回emptyString;    字符* returnString =(字符*)释放calloc((1 + nRun)的sizeof(字符));    如果(returnString == NULL)回报emptyString;    strncat函数(returnString,(nStartingPos +文字),nRun);    / *我们不需要从这时开始了emptyString * /    免费(emptyString);
    emptyString = NULL;    返回returnString;
}
诠释的main()
{
    为const char *文字=-2--4--6-7-8-9-10-11-;    字符* p值= SUBSTR(文本,-1,2);
    的printf([*]'%s'的(\\)\\ n,((P == NULL)?&LT;&NULL GT;:P));
    自由(对);    p值= SUBSTR(文字,1,2);
    的printf([*]'%s'的(-2)\\ n,((P == NULL)&LT;&NULL GT;?:P));
    自由(对);    p值= SUBSTR(文字,3,2);
    的printf([*]'%s'的( - )\\ n,((P == NULL)&LT;&NULL GT;?:P));
    自由(对);    p值= SUBSTR(文字,16,2);
    的printf([*]'%s'的(10)\\ n,((P == NULL)&LT;&NULL GT;?:P));
    自由(对);    p值= SUBSTR(文字,16,20);
    的printf([*]'%s'的(10-11 - )\\ n,((P == NULL)&LT;&NULL GT,:P));
    自由(对);    p值= SUBSTR(文字,100,2);
    的printf([*]'%s'的(\\)\\ n,((P == NULL)?&LT;&NULL GT;:P));
    自由(对);    p值= SUBSTR(文字,1,0);
    的printf([*]'%s'的(\\)\\ n,((P == NULL)?&LT;&NULL GT;:P));
    自由(对);    返回0;
}


  

输出:


  [*]''()
[*]' - 2'(-2)
[*]' - '( - )
[*]'10'(10)
[*]'10-11-'(10-11-)
[*]''()
[*]''()


解决方案

我想说的回报 NULL 如果输入不超过的malloc() ED空字符串。这样,你可以测试函数是否失败或不符合如果(P),而不是如果(* P == 0)

另外,我想是因为 emptyString 免费()在一个条件Ð你的函数泄漏内存。您应该确保您免费()无条件的,即权返回之前

至于您的评论函数strncpy()不是NUL终止字符串(这是真的),如果你使用释放calloc()来分配字符串,而不是的malloc(),如果分配比你复制,一个字节多以来<$ C $,这将不会是一个问题C>释放calloc()自动设定所有值(包括,在这种情况下,端),以0

我会给你更多的音符,但我讨厌读书驼峰code。不是说有什么错。

编辑:至于你的更新:

请注意,C标准定义的sizeof(char)的为1,无论你的系统。如果您使用的是一个字节使用9位(但愿)的计算机,的sizeof(char)的仍然会是1不是说有什么不妥说的sizeof(char)的 - 这清楚地表明你的意图,并提供了电话对称释放calloc()的malloc()对于其他类型。但的sizeof(INT)实际上是有用的( INT S能在16位和32位和新奇的这些大小不同64位计算机)。你知道的越多。

我还想重申,与其他大多数C code,它的一致性返回 NULL 上的错误,而不是 。我知道许多功能(如的strcmp())如果你通过他们NULL可能会做坏事 - 这是可以预期的。但C标准库(和许多其他的C API)来取的办法这是调用者的责任,以检查 NULL ,而不是函数有责任将孩子他/她,如果( S)他没有。如果你想这样做的其他方式,这很酷,但它违背的C接口设计,更强的发展趋势之一。

另外,我会使用函数strncpy()(或的memcpy()),而不是 strncat函数()。使用 strncat函数()(和的strcat())掩盖了你的意图 - 它使一个人看你的code想你想添加到字符串的结尾(你这样做,是因为在释放calloc(),到底是开头),当你想要做的是设置串。 strncat函数()使得它看起来就像是增加一个字符串,而的strcpy()(或另一个副本日常)将使它看起来更像你的意图是什么。以下三条线都做在这种情况下同样的事情 - 挑哪一个你认为最好看:

  strncat函数(returnString,文字+ nStartingPos,nRun);函数strncpy(returnString,文字+ nStartingPos,nRun);的memcpy(returnString,文字+ nStartingPos,nRun);

另外,函数strncpy()的memcpy()将可能是(凌晨一点)位更快/更比 strncat函数高效()

文本+ nStartingPos 相同 nStartingPos +文字 - 我会把字符* 第一,因为我认为这是更清晰,但你想要把它们是由你任意顺序。此外,他们周围的括号是多余的(但很好),因为 + 具有较高的precedence比

编辑2:三线code都不做同样的事情,但在这种情况下,他们都会产生相同的结果。感谢赶上我这句话。

See also C Tokenizer


Here is a quick substr() for C that I wrote (yes, the variable initializations needs to be moved to start of the function etc, but you get the idea)

I have seen many "smart" implementations of substr() that are simple one liner calls strncpy()!

They are all wrong (strncpy does not guarantee null termination and thus the call might NOT produce a correct substring!)

Here is something maybe better?

Bring out the bugs!

char* substr(const char* text, int nStartingPos, int nRun)
{
    char* emptyString = strdup(""); /* C'mon! This cannot fail */

    if(text == NULL) return emptyString;

    int textLen = strlen(text);

    --nStartingPos;

    if((nStartingPos < 0) || (nRun <= 0) || (textLen == 0) || (textLen < nStartingPos)) return emptyString;

    char* returnString = (char *)calloc((1 + nRun), sizeof(char));

    if(returnString == NULL) return emptyString;

    strncat(returnString, (nStartingPos + text), nRun);

    /* We do not need emptyString anymore from this point onwards */

    free(emptyString);
    emptyString = NULL;

    return returnString;
}


int main()
{
    const char *text = "-2--4--6-7-8-9-10-11-";

    char *p = substr(text, -1, 2);
    printf("[*]'%s' (\")\n",  ((p == NULL) ? "<NULL>" : p));
    free(p);

    p = substr(text, 1, 2);
    printf("[*]'%s' (-2)\n", ((p == NULL) ? "<NULL>" : p));
    free(p);

    p = substr(text, 3, 2);
    printf("[*]'%s' (--)\n", ((p == NULL) ? "<NULL>" : p));
    free(p);

    p = substr(text, 16, 2);
    printf("[*]'%s' (10)\n", ((p == NULL) ? "<NULL>" : p));
    free(p);

    p = substr(text, 16, 20);
    printf("[*]'%s' (10-11-)\n", ((p == NULL) ? "<NULL>" : p));
    free(p);

    p = substr(text, 100, 2);
    printf("[*]'%s' (\")\n", ((p == NULL) ? "<NULL>" : p));
    free(p);

    p = substr(text, 1, 0);
    printf("[*]'%s' (\")\n", ((p == NULL) ? "<NULL>" : p));
    free(p);

    return 0;
}

Output :

[*]'' (")
[*]'-2' (-2)
[*]'--' (--)
[*]'10' (10)
[*]'10-11-' (10-11-)
[*]'' (")
[*]'' (")

解决方案

I would say return NULL if the input isn't valid rather than a malloc()ed empty string. That way you can test whether or not the function failed or not with if(p) rather than if(*p == 0).

Also, I think your function leaks memory because emptyString is only free()d in one conditional. You should make sure you free() it unconditionally, i.e. right before the return.

As to your comment on strncpy() not NUL-terminating the string (which is true), if you use calloc() to allocate the string rather than malloc(), this won't be a problem if you allocate one byte more than you copy, since calloc() automatically sets all values (including, in this case, the end) to 0.

I would give you more notes but I hate reading camelCase code. Not that there's anything wrong with it.

EDIT: With regards to your updates:

Be aware that the C standard defines sizeof(char) to be 1 regardless of your system. If you're using a computer that uses 9 bits in a byte (god forbid), sizeof(char) is still going to be 1. Not that there's anything wrong with saying sizeof(char) - it clearly shows your intention and provides symmetry with calls to calloc() or malloc() for other types. But sizeof(int) is actually useful (ints can be different sizes on 16- and 32- and these newfangled 64-bit computers). The more you know.

I'd also like to reiterate that consistency with most other C code is to return NULL on an error rather than "". I know many functions (like strcmp()) will probably do bad things if you pass them NULL - this is to be expected. But the C standard library (and many other C APIs) take the approach of "It's the caller's responsibility to check for NULL, not the function's responsibility to baby him/her if (s)he doesn't." If you want to do it the other way, that's cool, but it's going against one of the stronger trends in C interface design.

Also, I would use strncpy() (or memcpy()) rather than strncat(). Using strncat() (and strcat()) obscures your intent - it makes someone looking at your code think you want to add to the end of the string (which you do, because after calloc(), the end is the beginning), when what you want to do is set the string. strncat() makes it look like you're adding to a string, while strcpy() (or another copy routine) would make it look more like what your intent is. The following three lines all do the same thing in this context - pick whichever one you think looks nicest:

strncat(returnString, text + nStartingPos, nRun);

strncpy(returnString, text + nStartingPos, nRun);

memcpy(returnString, text + nStartingPos, nRun);

Plus, strncpy() and memcpy() will probably be a (wee little) bit faster/more efficient than strncat().

text + nStartingPos is the same as nStartingPos + text - I would put the char * first, as I think that's clearer, but whatever order you want to put them in is up to you. Also, the parenthesis around them are unnecessary (but nice), since + has higher precedence than ,.

EDIT 2: The three lines of code don't do the same thing, but in this context they will all produce the same result. Thanks for catching me on that.

这篇关于这是对C的好SUBSTR?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆