我写了一个函数,它接受一个字符串,并将每个单词的最后一个字符大写,其余的 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));
}

https://godbolt.org/z/ssnMPY

或者您可以使用标准库中的函数

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