【问题标题】:CamelCase to snake_case in C without tolowerC中的CamelCase到snake_case,没有tolower
【发布时间】:2021-11-06 22:04:21
【问题描述】:

我想写一个不使用tolower的函数将CamelCase转换为snake_case。

示例:helloWorld -> hello_world

这是我目前所拥有的,但是输出是错误的,因为我在这里覆盖了字符串中的一个字符:string[i-1] = '_';。 我得到hell_world。我不知道如何让它工作。

void snake_case(char *string)
{
    int i = strlen(string);
    while (i != 0)
    {
        if (string[i] >= 65 && string[i] <= 90)
        {
            string[i] = string[i] + 32;
            string[i-1] = '_';
        }
        i--;
    }
}

【问题讨论】:

  • 假设底层数组有足够的空间,您需要将字母向前移动以便为'_' 腾出空间。使用memmove(),因为memcpy()strcpy() 在使用同一数组中的地址调用时都会调用UB。 否则你需要malloc()(和/或realloc()
  • [realloc()]... 并更改函数签名。
  • 我可能会分两次执行此操作:一次用于计算要插入的大写字母 == 下划线的数量,然后将字符处理/复制到使用分配的新缓冲区第一步计算的大小。

标签: c string c-strings text-manipulation


【解决方案1】:

这种转换意味着,除了将字符从大写转换为小写外,还将一个字符插入到字符串中。这是一种方法:

  • 从左到右迭代,
  • 如果找到大写字符,则使用memmove将所有字符从该位置移动到字符串的末尾右移一位,然后为当前字符分配要插入的值,
  • 在到达空终止符 (\0) 时停止,指示字符串的结尾。

从右到左的迭代也是可以的,但由于选择是任意的,从左到右更习惯。

基本实现可能如下所示:

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

void snake_case(char *string)
{
    for ( ; *string != '\0'; ++string)
    {
        if (*string >= 65 && *string <= 90)
        {
            *string += 32;
            memmove(string + 1U, string, strlen(string) + 1U);
            *string = '_';
        }
    }
}

int main(void)
{
    char string[64] = "helloWorldAbcDEFgHIj";
    snake_case(string);
    printf("%s\n", string);
}

输出:hello_world_abc_d_e_fg_h_ij

注意:

  • 要移动的字符串的大小是字符串的长度加一,同时移动空终止符 (\0)。
  • 我假设函数 isupper 也是禁止使用的。
  • 数组需要足够大以容纳新字符串,否则memmove 将执行无效写入!

后者是一个需要认真实施的问题。 “编写未知长度的结果”的一般问题有几种解决方案。对于这种情况,它们可能如下所示:

  1. 首先确定结果字符串的长度,重新分配数组,然后才修改字符串。需要两次通过。
  2. 每次找到大写字符时,将字符串重新分配为其当前大小 + 1。只需要通过一次,但需要频繁地重新分配。
  3. 与 2 相同,但只要数组太小,就将数组重新分配 两倍 其当前大小。需要一次通过,并且重新分配频率较低(但较大)。最后将数组重新分配到它实际包含的字符串的长度。

在这种情况下,我认为选项 1 是最好的。如果字符串长度已知,则可以选择执行两次,算法可以分为两个不同的部分:找到新长度,然后修改字符串。我可以根据要求将其添加到答案中。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-11-08
    • 2017-11-28
    • 1970-01-01
    • 2023-03-30
    • 2011-08-23
    • 1970-01-01
    相关资源
    最近更新 更多