• strspn()

    From Michael Sanders@porkchop@invalid.foo to comp.lang.c on Fri Nov 21 18:41:01 2025
    From Newsgroup: comp.lang.c

    So strspn, perfect for what I need!

    before:

    int ok = 1;

    if (strlen(colorSpec) == 4) {
    for (int i = 0; i < 4; i++) {
    char c = colorSpec[i];
    if (c < '1' || c > '8') { ok = 0; break; }
    }
    } else ok = 0;

    after:

    strspn() returns the length of the leading substring
    consisting ONLY of characters in the allowed set...

    if (strlen(colorSpec) != 4 && strspn(colorSpec, "12345678") = 4) FAIL;
    --
    :wq
    Mike Sanders
    --- Synchronet 3.21a-Linux NewsLink 1.2
  • From Michael Sanders@porkchop@invalid.foo to comp.lang.c on Fri Nov 21 18:42:16 2025
    From Newsgroup: comp.lang.c

    On Fri, 21 Nov 2025 18:41:01 -0000 (UTC), Michael Sanders wrote:

    if (strlen(colorSpec) != 4 && strspn(colorSpec, "12345678") = 4) FAIL;

    Should instead be:

    if (strlen(colorSpec) != 4 && strspn(colorSpec, "12345678") != 4) FAIL;
    --
    :wq
    Mike Sanders
    --- Synchronet 3.21a-Linux NewsLink 1.2
  • From Michael Sanders@porkchop@invalid.foo to comp.lang.c on Fri Nov 21 19:06:18 2025
    From Newsgroup: comp.lang.c

    On Fri, 21 Nov 2025 18:41:01 -0000 (UTC), Michael Sanders wrote:

    So strspn, perfect for what I need!

    before:

    int ok = 1;

    if (strlen(colorSpec) == 4) {
    for (int i = 0; i < 4; i++) {
    char c = colorSpec[i];
    if (c < '1' || c > '8') { ok = 0; break; }
    }
    } else ok = 0;

    after:

    strspn() returns the length of the leading substring
    consisting ONLY of characters in the allowed set...

    if (strlen(colorSpec) != 4 && strspn(colorSpec, "12345678") = 4) FAIL;

    Actually is should be:

    if (strlen(colorSpec) != 4 || strspn(colorSpec, "12345678") != 4) FAIL;

    Excuse the extra posts, got excited.
    --
    :wq
    Mike Sanders
    --- Synchronet 3.21a-Linux NewsLink 1.2
  • From bart@bc@freeuk.com to comp.lang.c on Sat Nov 22 00:04:24 2025
    From Newsgroup: comp.lang.c

    On 21/11/2025 18:41, Michael Sanders wrote:
    So strspn, perfect for what I need!

    before:

    int ok = 1;

    if (strlen(colorSpec) == 4) {
    for (int i = 0; i < 4; i++) {
    char c = colorSpec[i];
    if (c < '1' || c > '8') { ok = 0; break; }
    }
    } else ok = 0;

    after:

    strspn() returns the length of the leading substring
    consisting ONLY of characters in the allowed set...

    if (strlen(colorSpec) != 4 && strspn(colorSpec, "12345678") = 4) FAIL;


    Performance probably isn't critical in your use-case, but the solution
    using 'strspn' was three times as slow as doing the explicit code.

    (Test string was a fixed "8725" and tested 100M times.)

    This is not surprising since strspn doesn't know that the substring is
    ordered so doesn't need to test every character of the input string
    against every every character of the substring, at least while there is
    a match.
    --- Synchronet 3.21a-Linux NewsLink 1.2
  • From Michael Sanders@porkchop@invalid.foo to comp.lang.c on Sat Nov 22 00:56:06 2025
    From Newsgroup: comp.lang.c

    On Sat, 22 Nov 2025 00:04:24 +0000, bart wrote:

    Performance probably isn't critical in your use-case, but the solution
    using 'strspn' was three times as slow as doing the explicit code.

    (Test string was a fixed "8725" and tested 100M times.)

    This is not surprising since strspn doesn't know that the substring is ordered so doesn't need to test every character of the input string
    against every every character of the substring, at least while there is
    a match.

    I don't doubt it bart. Where as my loop was custom built for that particular condition, strspn() has to be alot more generic & thus slower. But still its
    a nifty function in concept no?
    --
    :wq
    Mike Sanders
    --- Synchronet 3.21a-Linux NewsLink 1.2
  • From Ben Bacarisse@ben@bsb.me.uk to comp.lang.c on Sat Nov 22 02:41:11 2025
    From Newsgroup: comp.lang.c

    Michael Sanders <porkchop@invalid.foo> writes:

    So strspn, perfect for what I need!

    before:

    int ok = 1;

    if (strlen(colorSpec) == 4) {
    for (int i = 0; i < 4; i++) {
    char c = colorSpec[i];
    if (c < '1' || c > '8') { ok = 0; break; }
    }
    } else ok = 0;

    There's no need for the strlen test:

    int i = 0;
    while (i < 4 && colorSpec[i] >= '1' && colorSpec[i] <= '8') i++;
    int ok = i == 4 && colorSpec[i] == 0;

    after:

    strspn() returns the length of the leading substring
    consisting ONLY of characters in the allowed set...

    if (strlen(colorSpec) != 4 && strspn(colorSpec, "12345678") = 4) FAIL;

    Hmm... don't you mean

    if (strlen(colorSpec) != 4 || strspn(colorSpec, "12345678") != 4) FAIL;

    You could also write the positive test explicitly like this, again
    without strlen:

    static bool in_range(char c) { return c >= '1' && c <= '8'; }
    ...
    in_range(colorSpec[0]) && in_range(colorSpec[1]) &&
    in_range(colorSpec[2]) && in_range(colorSpec[3]) &&
    colorSpec[4] == 0
    --
    Ben.
    --- Synchronet 3.21a-Linux NewsLink 1.2
  • From Ben Bacarisse@ben@bsb.me.uk to comp.lang.c on Sat Nov 22 02:42:43 2025
    From Newsgroup: comp.lang.c

    Michael Sanders <porkchop@invalid.foo> writes:

    On Fri, 21 Nov 2025 18:41:01 -0000 (UTC), Michael Sanders wrote:

    So strspn, perfect for what I need!

    before:

    int ok = 1;

    if (strlen(colorSpec) == 4) {
    for (int i = 0; i < 4; i++) {
    char c = colorSpec[i];
    if (c < '1' || c > '8') { ok = 0; break; }
    }
    } else ok = 0;

    after:

    strspn() returns the length of the leading substring
    consisting ONLY of characters in the allowed set...

    if (strlen(colorSpec) != 4 && strspn(colorSpec, "12345678") = 4) FAIL;

    Actually is should be:

    if (strlen(colorSpec) != 4 || strspn(colorSpec, "12345678") != 4) FAIL;

    Excuse the extra posts, got excited.

    Sorry, I read threads in order so commented on this in my earlier reply.
    --
    Ben.
    --- Synchronet 3.21a-Linux NewsLink 1.2
  • From Michael Sanders@porkchop@invalid.foo to comp.lang.c on Sat Nov 22 22:02:17 2025
    From Newsgroup: comp.lang.c

    On Sat, 22 Nov 2025 02:42:43 +0000, Ben Bacarisse wrote:

    Sorry, I read threads in order so commented on this in my earlier reply.

    No worries. Its all good.
    --
    :wq
    Mike Sanders
    --- Synchronet 3.21a-Linux NewsLink 1.2
  • From Michael Sanders@porkchop@invalid.foo to comp.lang.c on Sat Nov 22 22:03:59 2025
    From Newsgroup: comp.lang.c

    On Sat, 22 Nov 2025 02:41:11 +0000, Ben Bacarisse wrote:

    int i = 0;
    while (i < 4 && colorSpec[i] >= '1' && colorSpec[i] <= '8') i++;
    int ok = i == 4 && colorSpec[i] == 0;

    Nice/clean/succinct.
    --
    :wq
    Mike Sanders
    --- Synchronet 3.21a-Linux NewsLink 1.2
  • From Bonita Montero@Bonita.Montero@gmail.com to comp.lang.c on Tue Dec 2 13:44:59 2025
    From Newsgroup: comp.lang.c

    Am 22.11.2025 um 01:04 schrieb bart:
    On 21/11/2025 18:41, Michael Sanders wrote:
    So strspn, perfect for what I need!

    before:

    int ok = 1;

    if (strlen(colorSpec) == 4) {
         for (int i = 0; i < 4; i++) {
             char c = colorSpec[i];
             if (c < '1' || c > '8') { ok = 0; break; }
         }
    } else ok = 0;

    after:

    strspn() returns the length of the leading substring
    consisting ONLY of characters in the allowed set...

    if (strlen(colorSpec) != 4 && strspn(colorSpec, "12345678") = 4) FAIL;


    Performance probably isn't critical in your use-case, but the solution
    using 'strspn' was three times as slow as doing the explicit code.
    (Test string was a fixed "8725" and tested 100M times.)
    Try that with AVX. Make a 256 bit vector with 0's and a vector with '9's.
    Have two compares resulting in a 32 * 8 bit 0 / 0xFF mask. Convert that
    mask to a bitmask (with AVX-512 the comparison directly results in a
    bitmask, i.e. no conversion is necessary).
    --- Synchronet 3.21a-Linux NewsLink 1.2