【问题标题】:How to write function that return dynamic allocated string?如何编写返回动态分配字符串的函数?
【发布时间】:2021-05-08 02:37:29
【问题描述】:

我已指定使用函数char *slova(const char *s) 返回动态分配的字符串,该字符串仅由大小写字母组成。禁止使用string.h库。

char *slova(const char *s)
{
    char *new;
    int br = 0;
    new = (char *)malloc(sizeof(s));
    for (int i = 0; i != '\0'; i++)
        if(s[i] >= 'A' && s[i] <= 'z')
        {
            new[br] = s[i];
            br++;
        }
    return new;
}

我知道在 ASCII 码中 A 和 z 之间除了大小字母之外还有一些其他字符,所以不用担心。由于某种原因,这段代码不起作用,我不知道为什么。

【问题讨论】:

  • 是的,我忘了说,不允许使用string,h lib。
  • 不要忘记在new字符串的末尾添加'\0'(否则不能称为字符串)
  • sizeof(s) 将是指针的大小。没有strlen(),您可以轻松获得字符串长度。或者您可以使用realloc 来分配内存。
  • 是否允许使用ctype.h
  • ASCII character set'A''z' 之间有几个明显不需要的字符('[',']',...)

标签: c function dynamic-memory-allocation


【解决方案1】:
  • sizeof(s) 将返回的不是缓冲区大小,而是指针 s 的大小。
  • i != '\0' 是错误的。这意味着i != 0 并防止它进入循环,因为i 的初始值为0
  • 您忘记通过添加终止空字符来终止结果字符串。
  • 在 C 中转换 malloc() 的结果是 discouraged

固定代码:

char *slova(const char *s){
    char *new;
    int br = 0;

    // calculate the length
    for (int i = 0; s[i] != '\0'; i++)
        if(s[i] >= 'A' && s[i] <= 'z'){
            br++;
        }

    // allocate buffer
    new = malloc(br + 1);
    if (new == NULL) return NULL;

    // actually create the string
    br = 0;
    for (int i = 0; s[i] != '\0'; i++)
        if(s[i] >= 'A' && s[i] <= 'z'){
            new[br] = s[i];
            br++;
        }

    new[br] = '\0';
    return new;
}

【讨论】:

  • if(s[i] &gt;= 'A' &amp;&amp; s[i] &lt;= 'z') 可能返回的不仅仅是“大小字母”(无需进入克林贡字符集...)
【解决方案2】:

仔细查看你的函数声明

char *slova(const char *s){
            ^^^^^^^^^^^^^

它的参数是指针类型const char *。因此在此声明中

new = (char *)malloc(sizeof(s));

表达式sizeof(s) 产生的指针大小通常等于84 字节,具体取决于所使用的系统。也就是这个表达式不提供传递字符串的长度。

也是这个循环的主体

for (int i = 0; i != '\0'; i++)

永远无法获得控制权,因为条件 i != '\0' 立即计算为 false,因为变量 i 被初始化为零。

该函数可以如下所示,如下面的演示程序所示。它不使用标题 &lt;string.h&gt; 中的函数。

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

char * slova( const char *s )
{
    size_t n = 0;
    
    for ( const char *t = s; *t != '\0'; ++t )
    {
        if ( isalpha( ( unsigned char )*t ) ) ++n;
    }
    
    char * result = malloc( ( n + 1 ) *sizeof( char ) );
    
    if ( result != NULL )
    {
        char *p = result;
        for ( ; *s; ++s)
        {
            if ( isalpha( ( unsigned char )*s ) )
            {
                *p++ = *s;
            }
        }
        
        *p = '\0';
    }
    
    return result;
}   

int main(void) 
{
    const char *s = "H#e#l#l#o W#o#r#l#d";
    
    char *p = slova( s );
    
    if ( p ) puts( p );
    
    free( p );
    
    return 0;
}

程序输出是

HelloWorld

如果您也不允许使用标题 &lt;ctype.h&gt; 中的函数,则该函数可以如下面的演示程序所示。

#include <stdio.h>
#include <stdlib.h>

char * slova( const char *s )
{
    const char *upper_case = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
    const char *lower_case = "abcdefghijklmnopqrstuvwxyz";
    
    size_t n = 0;
    
    for ( const char *t = s; *t != '\0'; ++t )
    {
        const char *letter = lower_case;
        
        if ( *t < lower_case[0] )
        {
            letter = upper_case;
        }
        
        while ( *letter && *letter < *t ) ++letter;
        
        if ( *letter == *t ) ++n;
    }
    
    char * result = malloc( ( n + 1 ) *sizeof( char ) );
    
    if ( result != NULL )
    {
        char *p = result;
        
        for ( ; *s; ++s)
        {
            const char *letter = lower_case;
            
            if ( *s < lower_case[0] )
            {
                letter = upper_case;
            }
            
            while ( *letter && *letter < *s ) ++letter;
            
            if ( *letter == *s )
            {
                *p++ = *s;
            }
        }
        
        *p = '\0';
    }
    
    return result;
}   

int main(void) 
{
    const char *s = "H#e#l#l#o W#o#r#l#d";
    
    char *p = slova( s );
    
    if ( p ) puts( p );
    
    free( p );
    
    return 0;
}

程序输出又是

HelloWorld

【讨论】:

  • 建议:在传递空指针时为s参数添加保护(可能是空指针取消引用)。
  • @GrzegorzSzpetkowski 字符串函数从不检查是否传递了空指针。传递非空指针是函数用户的责任。
猜你喜欢
  • 1970-01-01
  • 2023-01-08
  • 1970-01-01
  • 1970-01-01
  • 2016-06-26
  • 2011-06-24
  • 2013-05-23
  • 1970-01-01
  • 2023-02-02
相关资源
最近更新 更多