#trim space - code review

26 messages · Page 1 of 1 (latest)

late flower
#

I'm learning C after 12 years of web dev and I want to learn something new without web involving and more low level.

My goal is to read id3v1 tag (for now) from mp3 file and I need to trim space and I would like to have some reviews about my code and the best approach to use ltrim and rtrim, it's better to call ltrim and rtrim in trim_all or having a trim function whitout calling ltrim and rtrim but with it's own implementation like trim function?

#include <stdio.h>
#include <ctype.h>
#include <string.h>

void trim(char *str) {
    if (str == NULL || str[0] == '\0') return;

    int start = 0;
    size_t end = strlen(str) - 1;

    while (isspace(str[start])) start++;
    while (end > start && isspace(str[end])) end--;

    size_t new_length = end - start + 1;
    memmove(str, str + start, new_length);
    str[new_length] = '\0';
}

void ltrim(char *str) {
    if (str == NULL || str[0] == '\0') return;

    int start = 0;
    const size_t end = strlen(str);

    while (isspace(str[start])) start++;

    size_t new_length = end - start + 1;
    memmove(str, str + start, new_length);
}

void rtrim(char *str) {
    if (str == NULL || str[0] == '\0') return;

    size_t end = strlen(str) - 1;
    while (isspace(str[end])) end--;

    size_t new_length = end + 1;
    str[new_length] = '\0';
}

void trim_all(char *str) {
    ltrim(str);
    rtrim(str);
}

int main(void) {
    char str[] = "   Hello, World!   ";
    trim(str);
    printf("%s\n", str);

    char str2[] = "   Hello, World!   ";
    ltrim(str2);
    printf("%s\n", str2);

    char str3[] = "   Hello, World!   ";
    rtrim(str3);
    printf("%s\n", str3);

    char str4[] = "   Hello, World!   ";
    trim_all(str4);
    printf("%s\n", str4);

    return 0;
}
versed ridgeBOT
#

When your question is answered use !solved to mark the question as resolved.

Remember to ask specific questions, provide necessary details, and reduce your question to its simplest form. For tips on how to ask a good question use !howto ask.

hybrid axle
#

yeah so ideally you don't do it like this

#

in my experience the best way to do these sorts of things is with views

#

e.g. you don't need to modify the original string, you can just change your view of it to not have any whitespace at the start or front

#

although that gets complicated with some c apis that expect c strings

#

or having a trim function whitout calling ltrim and rtrim but with it's own implementation like trim function
would it would be more efficient

#

but it depends how much you care about maintainability vs efficiency

#

also I know that c-strings seem fun but most of the time you do actually know the size of a string so calling strlen all the time is just a waste
e.g. if ltrim had a size parameter you could pass strlen if you wanted, or you could pass known sizes as well

#
size_t end = strlen(str) - 1;
while (isspace(str[end])) end--;
```also this has a bug
#

if your string has only spaces end wraps around

#

you have to be careful when iterating in reverse. You also can't just end >= 0 && isspace(str[end]) because end is always >= 0 by virtue of being unsigned

late flower
#

So you tell me to use a second parm to pass the string size instead of calculted in trim function.
Ok then it's better for performance two have different implementation instead of calling ltrim and rtrim inside trim.
Thx for the bug. I'll try to use a lib for unit test ^^

hybrid axle
#

its not better because there are 2 functions

#

its better because ltrim + rtrim have redundant code, that you only need to do once instead of in both

late flower
#

👍

late flower
#

I've fixed my code

void trim(char *str, const size_t len) {
    if (str == NULL || str[0] == '\0') return;

    int start = 0;
    size_t end = len;

    if (end == 0) return;

    end--;

    while (start < end && isspace(str[start])) start++;
    while (end > start && isspace(str[end])) end--;

    if (start >= end) {
        str[0] = '\0';
        return;
    }

    const size_t new_length = end - start + 1;
    memmove(str, str + start, new_length);

    str[new_length] = '\0';
}

I'm afraid about UTF8 encoding. In C it scares me. In C++ there is no issue with utf8? Everything is utf8? 😆

hybrid axle
#

they use the same underlying string representations

#

but ascii is often utf8 compatible (except for string size vs data length) so a lot of apis that were ascii were updated to utf8 without needing to re-write code

#

last I checked there also isn't a good way to use utf8 with standard output streams

#

(since the standard streams are only implemented for char and wchar_t)

late flower
#

C seems more simpler than rust but so harder to understand 🤯
But I want to try C with raylib and GTK then switch to c++ with raylib too and Qt. A very long path 😬

versed ridgeBOT
#

This question is being automatically marked as stale.
If your question has been answered, type !solved.
If your question is not answered feel free to bump the post or re-ask.
Take a look at !howto ask for tips on improving your question.

late flower
#

!solved