我写了一个函数,它接受一个字符串,并将每个单词的最后一个字符大写,其余的 lowercase.What 错了吗?
I wrote a function that takes one string and, capitalize the last character of each word in uppercase and the rest in lowercase.What's wrong with it?
我有一个函数接受一个字符串,并将最后一个字符大写
每个单词大写,其余小写。
如果一个单词只有一个字母,则必须大写。
我的代码:
#include <string.h>
char* rcapitalize(char* p)
{
char space = 32,tab = 9;
int len = strlen(p);
for (int i = 0;i<len;i++)
{
if (p[i]>='a' && p[i]<='z' && (p[i+1])==space ||p[i]>='a' && p[i]<='z' && (p[i+1])=='[=11=]' ||p[i]>='a' && p[i]<='z' && (p[i+1])==tab)
{
p[i]=p[i]-32;
}
else if (p[i]>='A' && p[i]<='Z' && (p[i+1])!=tab ||p[i]>='A' && p[i]<='Z' && (p[i+1])!=space || p[i]>='A' && p[i]<='Z' && (p[i+1])!='[=11=]')
{
p[i] = p[i]+32;
}
}
return p;
}
Input: "a FiRSt LiTTlE TESt"
Return Value: "A firsT littlE tesT"
My return value: "A firsT little tesT"
为什么要将 'E'
小写成一个单词 "littlE"
?
它可以通过使用函数来做一些常见的事情来简化(仅限 ASCII):
int myisspace(int c)
{
if(c == ' ' || c == '\t') return 1;
return 0;
}
int myisupperletter(int c)
{
if((c >= 'A' && c <= 'Z')) return 1;
return 0;
}
int myislowerletter(int c)
{
if((c >= 'a' && c <= 'z')) return 1;
return 0;
}
int mytolower(int c)
{
if(myisupperletter(c)) c += 'a' - 'A';
return c;
}
int mytoupper(int c)
{
if(myislowerletter(c)) c -= 'a' - 'A';
return c;
}
char* rcapitalize(char* p)
{
for(char *wrk = p; *wrk; wrk++)
{
if(myisspace(wrk[1]) || !wrk[1]) *wrk = mytoupper(*wrk);
else *wrk = mytolower(*wrk);
}
return p;
}
int main()
{
char r[] = " aa ----- FiRSt LiTTlE TESt ";
printf("%s\n", rcapitalize(r));
}
或者您可以使用标准库中的函数
char* rcapitalize(char* p)
{
for(char *wrk = p; *wrk; wrk++)
{
if(isspace(wrk[1]) || !wrk[1]) *wrk = toupper(*wrk);
else *wrk = tolower(*wrk);
}
return p;
}
用法
int main()
{
char r[] = " aa FiRSt LiTTlE TESt ";
printf("%s\n", rcapitalize(r));
}
在这里你可以自己测试和玩:https://godbolt.org/z/a4xr4G
这个函数有一些错误
但这是直接导致错误的条件 lowercase-ing 即 'E'.
这应该匹配不在单词末尾的大写字母吧?但是它匹配所有大写字母。
else if (p[i]>='A' && p[i]<='Z' && (p[i+1])!=tab ||p[i]>='A' && p[i]<='Z' && (p[i+1])!=space || p[i]>='A' && p[i]<='Z' && (p[i+1])!='[=10=]'
当执行到条件失败时 p[i] == 'E'
,则 (p[i+1])!='[=12=]'
为真(即使 (p[i+1])!=space
为假)
如评论所述:
- 你的 if 条件过于复杂,你应该尝试分解它们
- 对于您的测试,您应该使用 C 标准函数,例如 isspace()
- 对于您的处理,您应该使用 C 标准函数,例如 toupper()
通过简化您的 if 条件,您会发现 (p[i+1]) != tab || (p[i+1]) != space
始终为真。
根据所有这些,这是您的函数的简化版本:
char* rcapitalize(char* p) {
size_t len = strlen(p);
for (size_t i = 0; i < len; i++) {
if (p[i + 1] == '[=10=]' || isspace(p[i + 1])) {
p[i] = toupper(p[i]);
} else {
p[i] = tolower(p[i]);
}
}
return p;
}
您的 if 条件不符合您的要求。
您对字符的检查是“有效的”,因为它是 ASCII,但完整的版本将包括使用函数 is_lower、is_upper、toupper、tolower、pointers,如另一个答案所示
但我认为这是初学者的学习练习,所以使用 ASCII 没问题
char* rcapitalize(char *p) {
char space = 32, tab = 9;
int len = strlen(p);
for (int i = 0; i < len; i++) {
if (i + 1 <= len && (p[i + 1] == space || p[i + 1] == tab || p[i + 1] == '[=10=]')) {
if (p[i] >= 'A' && p[i] <= 'Z')
p[i] += 32;
if (p[i] >= 'a' && p[i] <= 'z')
p[i] -= 32;
}
}
return p;
}
单词 "LiTTlE"
是字符串中最后一个字母大写的唯一单词。
else if 语句的第一个sub-expression
p[i]>='A' && p[i]<='Z' && (p[i+1])!=tab
将始终计算为真,因为字符 p[i+1]
确实不等于 tab
。所以完整的表达式也将始终计算为真。
您必须在此 else if 语句的完整表达式中使用逻辑 AND 运算符,而不是逻辑 OR 运算符。
例如它可能看起来像
else if ( p[i] >= 'A' && p[i] <= 'Z' && p[i+1] != tab && p[i+1] != space && p[i+1] != '[=11=]' )
不过这个程序看起来很糟糕。例如,如果将使用 EBCDIC 字符 table.
而不是 ASDII 字符 table,它将无法正常工作
首先不要使用像 32
这样的幻数。
使用的逻辑表达式过于复杂。
strlen
的调用是多余的。
这是一个演示程序,展示了如何编写函数。
#include <stdio.h>
#include <ctype.h>
char * rcapitalize( char *s )
{
for ( char *p = s; *p; ++p )
{
unsigned char c1 = p[0], c2 = p[1];
if ( isalpha( c1 ) )
{
if ( isspace( c2 ) || c2 == '[=12=]' )
{
*p = toupper( c1 );
}
else if ( isupper( c1 ) )
{
*p = tolower( c1 );
}
}
}
return s;
}
int main(void)
{
char s[] = "a FiRSt LiTTlE TESt";
puts( rcapitalize( s ) );
return 0;
}
程序输出为
A firsT littlE tesT
我有一个函数接受一个字符串,并将最后一个字符大写 每个单词大写,其余小写。 如果一个单词只有一个字母,则必须大写。
我的代码:
#include <string.h>
char* rcapitalize(char* p)
{
char space = 32,tab = 9;
int len = strlen(p);
for (int i = 0;i<len;i++)
{
if (p[i]>='a' && p[i]<='z' && (p[i+1])==space ||p[i]>='a' && p[i]<='z' && (p[i+1])=='[=11=]' ||p[i]>='a' && p[i]<='z' && (p[i+1])==tab)
{
p[i]=p[i]-32;
}
else if (p[i]>='A' && p[i]<='Z' && (p[i+1])!=tab ||p[i]>='A' && p[i]<='Z' && (p[i+1])!=space || p[i]>='A' && p[i]<='Z' && (p[i+1])!='[=11=]')
{
p[i] = p[i]+32;
}
}
return p;
}
Input: "a FiRSt LiTTlE TESt" Return Value: "A firsT littlE tesT" My return value: "A firsT little tesT"
为什么要将 'E'
小写成一个单词 "littlE"
?
它可以通过使用函数来做一些常见的事情来简化(仅限 ASCII):
int myisspace(int c)
{
if(c == ' ' || c == '\t') return 1;
return 0;
}
int myisupperletter(int c)
{
if((c >= 'A' && c <= 'Z')) return 1;
return 0;
}
int myislowerletter(int c)
{
if((c >= 'a' && c <= 'z')) return 1;
return 0;
}
int mytolower(int c)
{
if(myisupperletter(c)) c += 'a' - 'A';
return c;
}
int mytoupper(int c)
{
if(myislowerletter(c)) c -= 'a' - 'A';
return c;
}
char* rcapitalize(char* p)
{
for(char *wrk = p; *wrk; wrk++)
{
if(myisspace(wrk[1]) || !wrk[1]) *wrk = mytoupper(*wrk);
else *wrk = mytolower(*wrk);
}
return p;
}
int main()
{
char r[] = " aa ----- FiRSt LiTTlE TESt ";
printf("%s\n", rcapitalize(r));
}
或者您可以使用标准库中的函数
char* rcapitalize(char* p)
{
for(char *wrk = p; *wrk; wrk++)
{
if(isspace(wrk[1]) || !wrk[1]) *wrk = toupper(*wrk);
else *wrk = tolower(*wrk);
}
return p;
}
用法
int main()
{
char r[] = " aa FiRSt LiTTlE TESt ";
printf("%s\n", rcapitalize(r));
}
在这里你可以自己测试和玩:https://godbolt.org/z/a4xr4G
这个函数有一些错误
但这是直接导致错误的条件 lowercase-ing 即 'E'.
这应该匹配不在单词末尾的大写字母吧?但是它匹配所有大写字母。
else if (p[i]>='A' && p[i]<='Z' && (p[i+1])!=tab ||p[i]>='A' && p[i]<='Z' && (p[i+1])!=space || p[i]>='A' && p[i]<='Z' && (p[i+1])!='[=10=]'
当执行到条件失败时 p[i] == 'E'
,则 (p[i+1])!='[=12=]'
为真(即使 (p[i+1])!=space
为假)
如评论所述:
- 你的 if 条件过于复杂,你应该尝试分解它们
- 对于您的测试,您应该使用 C 标准函数,例如 isspace()
- 对于您的处理,您应该使用 C 标准函数,例如 toupper()
通过简化您的 if 条件,您会发现 (p[i+1]) != tab || (p[i+1]) != space
始终为真。
根据所有这些,这是您的函数的简化版本:
char* rcapitalize(char* p) {
size_t len = strlen(p);
for (size_t i = 0; i < len; i++) {
if (p[i + 1] == '[=10=]' || isspace(p[i + 1])) {
p[i] = toupper(p[i]);
} else {
p[i] = tolower(p[i]);
}
}
return p;
}
您的 if 条件不符合您的要求。
您对字符的检查是“有效的”,因为它是 ASCII,但完整的版本将包括使用函数 is_lower、is_upper、toupper、tolower、pointers,如另一个答案所示
但我认为这是初学者的学习练习,所以使用 ASCII 没问题
char* rcapitalize(char *p) {
char space = 32, tab = 9;
int len = strlen(p);
for (int i = 0; i < len; i++) {
if (i + 1 <= len && (p[i + 1] == space || p[i + 1] == tab || p[i + 1] == '[=10=]')) {
if (p[i] >= 'A' && p[i] <= 'Z')
p[i] += 32;
if (p[i] >= 'a' && p[i] <= 'z')
p[i] -= 32;
}
}
return p;
}
单词 "LiTTlE"
是字符串中最后一个字母大写的唯一单词。
else if 语句的第一个sub-expression
p[i]>='A' && p[i]<='Z' && (p[i+1])!=tab
将始终计算为真,因为字符 p[i+1]
确实不等于 tab
。所以完整的表达式也将始终计算为真。
您必须在此 else if 语句的完整表达式中使用逻辑 AND 运算符,而不是逻辑 OR 运算符。
例如它可能看起来像
else if ( p[i] >= 'A' && p[i] <= 'Z' && p[i+1] != tab && p[i+1] != space && p[i+1] != '[=11=]' )
不过这个程序看起来很糟糕。例如,如果将使用 EBCDIC 字符 table.
而不是 ASDII 字符 table,它将无法正常工作首先不要使用像 32
这样的幻数。
使用的逻辑表达式过于复杂。
strlen
的调用是多余的。
这是一个演示程序,展示了如何编写函数。
#include <stdio.h>
#include <ctype.h>
char * rcapitalize( char *s )
{
for ( char *p = s; *p; ++p )
{
unsigned char c1 = p[0], c2 = p[1];
if ( isalpha( c1 ) )
{
if ( isspace( c2 ) || c2 == '[=12=]' )
{
*p = toupper( c1 );
}
else if ( isupper( c1 ) )
{
*p = tolower( c1 );
}
}
}
return s;
}
int main(void)
{
char s[] = "a FiRSt LiTTlE TESt";
puts( rcapitalize( s ) );
return 0;
}
程序输出为
A firsT littlE tesT