如何递归地将字符串中所有单词的首字母大写?

How can i make first letter of all words in a string uppercase recursively?

我想知道我该怎么做。我不想要任何迭代或 isalpha() 和 toupper() 函数。我们想使用我们自己的代码来读取输入。我们假设用户输入的所有字符都是小写的。这是我到目前为止尝试过的:

define MAX_LENGTH 100

int read_line(char str[],int);
void capitalize(char[]);

int main (void){
    char A[MAX_LENGTH];
printf("Enter a text \n");
read_line(A, MAX_LENGTH);

capitalize(A);
puts(A);


}

int read_line(char str[],int n){
    int ch,i=0;

    while ((ch = getchar()) != '\n'){
        if(i<MAX_LENGTH)
            str[i++] = ch;
    }
    str[i] = '[=10=]';
    return i;
}

void capitalize(char str[]){
 int x = strlen(str);
 static int i = 0;
    if(str[i]=='[=10=]')
    return;
    if(str[i-1]==' '|| i == 0)
      str[i] -= 32;
      i++;
      return capitalize(&str[i]);
 }

输出是这样的:

Enter a text:

asdf sdf df

Asdf sdf df

我的代码有什么问题?

主要问题是你同时使用索引和递归,简单的递归解决方案是:

void capitalize(char* str, bool start){
    if (!*str) return; // end as soon as [=10=] is met
    if (start) 
        if (*str >= 'a' && *str <= 'z') *str = (*str - 'a') + 'A'; // capitalize latin letters
    capitalize(str + 1, *str == ' '); // work with next symbol
}

应该被称为capitalize(str, true)

应该做的工作:

void capitalize(char *s)
{
    while(1) {
        while (*s==' ') s++;                // skip spaces
        if (!*s) return;                    // check for end
        if ('a'<=*s && *s<='z') *s -= 32;   // capitalize if needed
        while (*s && *s!=' ') s++;          // advance
    }                                       // loop
}

(我称之为"Stupid Character Processing")

您的代码无效。例如甚至函数 read_line

int read_line(char str[],int n){
    int ch,i=0;

    while ((ch = getchar()) != '\n'){
        if(i<MAX_LENGTH)
            str[i++] = ch;
    }
    str[i] = '[=10=]';
    return i;
}

是不正确的,至少因为当 i 等于 MAX_LENGTH -1 时,存在超出字符数组的访问内存

str[i] = '[=11=]';

那是循环的条件一开始写错了

至于递归函数可以看下面的例子

#include <stdio.h>

int is_blank( char c )
{
    return c == ' ' || c == '\t';
}

char * capitalize( char *s )
{
    if ( *s )
    {
        int blank = is_blank( *s );

        if ( !blank )
        {
            *s &= ~' ';
        }

        capitalize( s + 1 );

        if ( !blank && !is_blank( *( s + 1 ) ) && *( s + 1 ) )
        {
            *( s + 1 ) |= ' ';
        }
    }

    return s;
}

int main(void) 
{
    char s[] = "hello everybody. how do you do?";

    puts( s );
    puts( capitalize( s ) );

    return 0;
}

程序输出为

hello everybody. how do you do?
Hello Everybody. How Do You Do?

这是一个类似的演示程序,但具有您的固定功能 read_line

#include <stdio.h>

#define MAX_LENGTH  100

int is_blank( char c )
{
    return c == ' ' || c == '\t';
}

char * capitalize( char *s )
{
    if ( *s )
    {
        int blank = is_blank( *s );

        if ( !blank )
        {
            *s &= ~' ';
        }

        capitalize( s + 1 );

        if ( !blank && !is_blank( *( s + 1 ) ) && *( s + 1 ) )
        {
            *( s + 1 ) |= ' ';
        }
    }

    return s;
}

size_t read_line( char *s, size_t n )
{
    int ch;
    size_t i = 0;

    while ( i + 1 < n && ( ch = getchar() ) != EOF && ch != '\n' )
    {
        s[i++] = ch;
    }

    s[i] = '[=14=]';

    return i;
}

int main(void) 
{
    char s[MAX_LENGTH];

    read_line( s, MAX_LENGTH );

    puts( s );

    puts( capitalize( s ) );

    return 0;
}

如果要输入字符串

hello everybody. how do you do?

然后程序输出将与上面显示的相同。

hello everybody. how do you do?
Hello Everybody. How Do You Do?

如果您不清楚按位运算,则可以用此语句代替

对于此声明

*s &= ~' ';

对于此声明

*s -= 'a' - 'A';

和这个声明

*( s + 1 ) |= ' ';

对于此声明

*( s + 1 ) += 'a' - 'A';

如果使用您的方法来实现带有静态变量的递归函数,那么您会很感兴趣,为什么您的函数不起作用?

让我们考虑忽略调用 strlen 的第一条语句。

void capitalize(char str[]){
 int x = strlen(str);
 static int i = 0;
    if(str[i]=='[=21=]')
    return;
    if(str[i-1]==' '|| i == 0)
      str[i] -= 32;
      i++;
      return capitalize(&str[i]);
 }

首先,在第一次为一个字符串调用该函数后,您不能为另一个字符串再次调用它,因为静态变量 i 不会已经等于 0。

if语句的条件至少要写成这样

    if ( i == 0 || str[i-1]==' ' )

也就是说子表达式的顺序应该改变。

return 语句不应包含表达式

      return capitalize(&str[i]);

你可以写

      capitalize(&str[i]);

尽管如此,指针的初始值 str 已更改。但是在函数中,您使用的索引 i 相对于函数第一次调用的初始值 str

我相信您对如何正确重写函数很感兴趣,不是吗?

函数如下面的演示程序所示。

#include <stdio.h>

#define MAX_LENGTH  100

int is_blank( char c )
{
    return c == ' ' || c == '\t';
}

char * capitalize( char *s )
{
    static size_t i = 0;

    if ( *( s + i ) )
    {
        if ( !is_blank( s[i] ) && ( i == 0  || is_blank( s[i-1] ) ) )
        {
            s[i] -= 'a' - 'A';
        }

        ++i;

        capitalize( s );

        --i;
    }

    return s;
}

size_t read_line( char *s, size_t n )
{
    int ch;
    size_t i = 0;

    while ( i + 1 < n && ( ch = getchar() ) != EOF && ch != '\n' )
    {
        s[i++] = ch;
    }

    s[i] = '[=25=]';

    return i;
}

int main(void) 
{
    char s[MAX_LENGTH];

    read_line( s, MAX_LENGTH );

    puts( s );

    puts( capitalize( s ) );

    return 0;
}

我会写下:

void capitalize(char* str) {
    if (! *str) return;      // job done
    *str = toupper(*str);    // capitalize "correctly"
    capitalize(++str);
}