如何递归地将字符串中所有单词的首字母大写?
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);
}
我想知道我该怎么做。我不想要任何迭代或 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);
}