函数只返回字符串的字母

时间:2014-04-22 14:51:15

标签: c string function pointers

我编写了一个程序,该程序应该接受一个字符串,然后返回一个只包含原始字母的字符串,但它不起作用,无法弄清楚原因。有人能帮助我吗?

#include<stdio.h>

char *only_letters(char *s1ptr, char *s2ptr)
{
    while(*s1ptr)
    {
        if((*s1ptr >= 'a' && *s1ptr <= 'z') || (*s1ptr >= 'A' && *s1ptr <= 'Z'))
        {
            *s2ptr = *s1ptr;
            s2ptr++;
        }
        s1ptr++;
    }
    *s2ptr = '\0';
    return s2ptr;
}

int main()
{
    char *s1ptr, *s2ptr;
    printf("\n Write a string:\n");
    scanf("%s", s1ptr);
    printf("\n%s\n", *only_letters(s1ptr, s2ptr));
    return 0;
}

5 个答案:

答案 0 :(得分:4)

你有3个问题。

  1. s1ptrs2ptr是两个未分配的数组,会导致未定义的行为。

  2. 您正在将s2ptr增加到值为\0的点。返回后,您将拥有一个只有\0的字符串。

  3. 要显示字符串,您必须在没有*的情况下传递它(不要取消引用它)。

  4. 试试这个

    char *only_letters(char *s1ptr, char *s2ptr_)
    {
        char *s2ptr = s2ptr_;
        while(*s1ptr)
        {
            if((*s1ptr >= 'a' && *s1ptr <= 'z') || (*s1ptr >= 'A' && *s1ptr <= 'Z'))
            {
                *s2ptr = *s1ptr;
                s2ptr++;
            }
            s1ptr++;
        }
        *s2ptr = '\0';
    
        return s2ptr_;
    }
    
    int main()
    {
        char s1ptr[256]; // Long enough
        char s2ptr[256]; // Long enough
        printf("\n Write a string:\n");
        scanf("%s", s1ptr);
        printf("\n%s\n", only_letters(s1ptr, s2ptr));
    }
    

答案 1 :(得分:3)

您遇到了未定义的行为,因为s1ptr没有指向有效位置,因此scanf失败。

尝试将变量声明为

char s1ptr[64], s2ptr[64]; //or whatever length suits you

另外,请注意

printf("\n%s\n", *only_letters(s1ptr, s2ptr));

将尝试取消引用only_letters返回的内容(char*,取消引用为char),但您尝试将其作为字符串读取(通过%s)。删除解引用运算符。

答案 2 :(得分:1)

这是非常难看的C风格代码,容易出错。虽然代码中的错误已由早期的鸟类修复,但这是C ++的方法:

std::string only_letters (std::string input) {
    auto it = std::remove_if(input.begin(),input.end(),
        [](const char x) {return !std::isalpha(static_cast<unsigned char>(x));});
    input.erase(it,input.end());
    return input;
}

int main () {
    std::string input;
    std::cout << "Write a string:\n";
    std::cin >> input;
    std::cout << only_letters(input);
}

答案 3 :(得分:0)

除了您使用无效指针这一事实外,您还使用了错误的格式说明符:

printf("\n%s\n", *only_letters(s1ptr, s2ptr));

由于only_letter返回char*,因此取消引用其结果会产生char
您的格式表示期望指向零终止字符序列(“%s”)的指针,因此printf将解释您作为指针传递给它的char。 在您的情况下,您将返回指向最终'\0'字符的指针,并且零恰好被解释为空指针,打印为“(null)”。
在开始之前,您需要保存结果指针的初始值。

可能完整且未经测试的修复:

char *only_letters(char *s1ptr, char *s2ptr)
{
    char* result = s2ptr;
    while(*s1ptr)
    {
        if((*s1ptr >= 'a' && *s1ptr <= 'z') || (*s1ptr >= 'A' && *s1ptr <= 'Z'))
        {
            *s2ptr = *s1ptr;
            s2ptr++;
        }
        s1ptr++;
    }
    *s2ptr = '\0';
    return result;
}

int main()
{
    char s1ptr[1024], s2ptr[1024];
    printf("\n Write a string:\n");
    scanf("%s", s1ptr);
    printf("\n%s\n", only_letters(s1ptr, s2ptr));
    return 0;
}

答案 4 :(得分:0)

您的代码至少有三个缺陷。第一个是函数定义

char *only_letters(char *s1ptr, char *s2ptr)
{
    while(*s1ptr)
    {
        if((*s1ptr >= 'a' && *s1ptr <= 'z') || (*s1ptr >= 'A' && *s1ptr <= 'Z'))
        {
            *s2ptr = *s1ptr;
            s2ptr++;
        }
        s1ptr++;
    }
    *s2ptr = '\0';
    return s2ptr;
}

该函数返回指向终止零的指针

*s2ptr = '\0';
return s2ptr;

有效代码可以采用以下方式

char * only_letters( const char *s1ptr, char *s2ptr )
{
    char *p = s2ptr;

    while ( *s1ptr )
    {
        if ( ( *s1ptr >= 'a' && *s1ptr <= 'z' ) || ( *s1ptr >= 'A' && *s1ptr <= 'Z' ) )
        {
            *p++ = *s1ptr;
        }
        s1ptr++;
    }

    *p = '\0';

    return s2ptr;
}

至于我,那我就把这个函数写成

char * only_letters( const char *s1ptr, char *s2ptr )
{
    char *p = s2ptr;

    while ( *s1ptr )
    {
        if ( isalpha( *s1ptr ) )
        {
            *p++ = *s1ptr;
        }
        s1ptr++;
    }

    *p = '\0';

    return s2ptr;
}

第二个缺陷是你没有在你要写数据的地方分配内存。

int main()
{
    char *s1ptr, *s2ptr;
    //...

有效代码可能看起来像

int main()
{
    const size_t N = 20;
    char s1ptr[N], s2ptr[N];

考虑到而不是

printf("\n%s\n", *only_letters(s1ptr, s2ptr));

必须有

printf("\n%s\n", only_letters(s1ptr, s2ptr));

第三个缺陷是使用函数scanf来读取字符串。此函数可以覆盖不属于该数组的内存。

scanf("%s", s1ptr);

最好使用函数fgets

例如

fgets( s1ptr, N, stdin );

最后,如果程序是用C语言编写的,则main应定义为

int main( void )

如果是偶然的:)它是一个C ++程序,那么你应该使用标准的C ++流而不是C流和相应的C ++函数而不是C函数。

此外,您可以使用标准算法std::copy_if来仅在目标字符串中复制字母字符。