如何正确构建字符串的 toLower

How to build toLower for string correctly

我正在尝试对全名字符串执行不区分大小写的 strcmp。 我有一个函数可以将 C 风格的字符串转换为小写。

    char* toLowerCase(char* string){
    
        char *s = string;
        unsigned long int s_len = strlen(s);
        char sToLower[s_len];
    
        for (int i = 0; i < s_len; i++)
            sToLower[i] = tolower(s[i]);
        sToLower[s_len] = 0;
    
        s = sToLower;
        return s;
    }

但是 strcpy 和 strcat 不起作用。如何解决?

        char fullName[1024] = "";
        strcpy(fullName, toLowerCase(p->data.firstName));
        strcat(fullName, toLowerCase(p->data.lastName));

toLowerCase 函数不正确,因为它 returns 一个指向局部数组的指针,该数组在退出该函数后将不存在。所以使用这个指针访问内存会调用未定义的行为。

char* toLowerCase(char* string){
//...
char sToLower[s_len];
//...
s = sToLower;
return s;
}

而且本地数组的大小指定不正确

char sToLower[s_len];

你至少需要像

一样声明
char sToLower[s_len + 1];

为终止零字符保留内存'[=15=]'

您需要就地更改源字符串(但在这种情况下,该函数不能与字符串文字一起使用),或者您需要在函数内动态创建一个新数组并将转换为的源字符串存储在那里小写。

例如

char* toLowerCase( const char* s )
{
    char *sToLower = malloc( strlen( s ) + 1 );

    if ( sToLower != NULL )
    {
        char *p = sToLower;
        while ( ( *p++ = tolower( ( unsigned char )*s++ ) ) != '[=13=]' );
    }

    return sToLower;
}

当不再需要字符串时,您需要释放函数中为返回的字符串分配的内存。

或者可以使用两个指定源数组和目标数组的参数声明函数,如

char* toLowerCase( char *dsn, const char* src );

也就是说,函数的用户必须提供目标数组,该数组将存储转换为小写的源字符串。

正如已经指出的那样,函数内部的局部变量会占用函数范围之外的存在。您可以为 target-string 动态分配内存(稍后释放)或在调用期间提供内存。

由于 fullName 已经可用,您可以按如下方式修改 toLowerCase() 函数:

#include <inttypes.h>

size_t toLowerCopy (char* dst, size_t dsize, const char* src) {
    if (!src || dsize < 2 || !dst) return 0L;

    const char* tmp = src;
    while (*tmp && --dsize)
        *dst++ = tolower (*tmp++);
    *dst = '[=10=]';
    return (tmp - src);
}

它还注意目的地 buffer-size,计算终端 [=14=] 字符。 您可以将其称为 fullName 为:


char fullName[1024];

size_t copied = toLowerCopy (fullName, sizeof(fullName), p->data.firstName);
// handle if (copied == 0)
size_t first_len = copied;
if (copied) fullName [copied++] = ' ';  // first name was not empty (separator)
copied = toLowerCopy (fullName + copied, sizeof(fullName) - copied, p->data.lastName);
// handle if (copied == 0)
if (!copied) fullName[first_len] = '[=11=]'; // second name was emtpy

感谢来自莫斯科的 Vlad 。这是我的解决方案:

void toLowerCase(char* target, const char* source){
while ((*target++ = tolower((unsigned char)*source++)) != '[=10=]');}

        toLowerCase(fullname, p->data.firstName);
        toLowerCase(lastName, p->data.lastName);
        strcat(fullname, lastName);
        printf("%s", fullname);