繁体   English   中英

用于将小写转换为大写的递归函数

[英]Recursive function for converting lower case to upper case

我的任务是在 C 中编写一个递归函数,将任何字符的字符串更改为全部大写(不使用toupper()或任何其他函数)。

这是以前的代码并尝试解决问题:

#include <stdio.h>
#include <string.h>
#include <stdlib.h>

char* allCapStringRec(char str[])
{
    if (str[0] == '\0' )
        return 0; 

    if (str[0] >= 'a' && str[0] <= 'z')
        str[0] = str[0] - 32;

    return allCapStringRec(str+1);
}

代码需要通过“测试”成功编译以检查代码 - 该函数自行工作但未完成该测试。

测试:

void Test3(char str[], char expected[], int dec)
{
    char *result = allCapStringRec(str);

    if (strcmp(result, expected) != 0)
        printf("allCapStringRec => Your Output is %s, Expected: %s\n", result, expected);
}

int main()
{
    Test3("123321", "123321", 4);
    Test3("abBba", "ABBBA", 4);
    Test3("ab$cd", "AB$CD", 4);

    printf("done");
    return 0;
}

我的输出:

dupCapStringRec => Your Output is , Expected: 123321

抱歉所有的编辑,这是我的第一个问题。 我需要帮助知道我做错了什么:)

这是递归的可怕用途! 这不碍事,所以我们如何修复这段代码:

到目前为止,其他答案假设您可以更改Test3() ,我假设您不能 - 这是其他人将测试例程应用于您的代码。 如果是这样,我看到两种方法来处理它的调用:

char *result = allCapStringRec(str);

首先,假设我们可以用可写字符串编译这段代码——也就是说,我们可以修改任何传入的字符串。在这种情况下,让allCapStringRec()返回一个值只是一种方便,而不是一个不可或缺的特性它的递归:

char *allCapStringRec(char str[])
{
    // assumes compiled with -fwritable-strings

    if (str[0] == '\0') {
        return str;
    }

    if (str[0] >= 'a' && str[0] <= 'z') {
        str[0] -= ' ';
    }

    allCapStringRec(str + 1);

    return str;  // convenience return, not strictly necessary
}

如果我们不能假设可写字符串,事情会变得更加复杂,因为我们必须创建一个字符串并返回它。 这里字符串结果的返回成为递归的一部分:

char *allCapStringRec(char str[])
{
    char *upper = calloc(strlen(str) + 1, sizeof(char));  // calloc initializes to '\0'

    if (str[0] == '\0') {
        return upper;
    } else if (str[0] >= 'a' && str[0] <= 'z') {
        upper[0] = str[0] - ' ';
    } else {
        upper[0] = str[0];
    }

    char *tail = allCapStringRec(str + 1);

    (void) strcpy(upper + 1, tail);

    free(tail);

    return upper;
}

如果这是假设的,那么Test3()是有缺陷的,应该将free(result)作为它为避免内存泄漏所做的最后一件事。 但是使用calloc()free()违反了“不使用 toupper() 或任何其他函数”的要求,因此对于不可写的字符串无法解决。

您的代码是错误的,但这并不是完全失败。

这需要改变:

  • 不要让allCapStringRec返回一个无意义的指针,而是让它成为一个void函数。
  • 不要尝试修改字符串文字(它们无法修改),而是将字符串文字复制到临时缓冲区并在该缓冲区上进行转换。 有关字符串文字的此问题的更多信息。

评论中的更多解释:

void allCapStringRec(char str[])  // make the function void
{
  if (str[0] == '\0')
    return;                       // don't return anything

  if (str[0] >= 'a' && str[0] <= 'z')
    str[0] = str[0] - 32;

  allCapStringRec(str + 1);       // don't return anything
}


void Test3(char str[], char expected[], int dec)
{
  char testbuffer[100];           // temporary buffer that can be modified
  strcpy(testbuffer, str);        // copy source to temp buffer
  allCapStringRec(testbuffer);    // convert string in temp buffer

  if (strcmp(testbuffer, expected) != 0)   // compare converted testbuffer with expected
    printf("allCapStringRec => Your Output is %s, Expected: %s\n", testbuffer, expected);
}

问题 1:您尝试修改只读字符串文字。 为什么写入用字符串文字初始化的“char *s”而不是“char s[]”时会出现分段错误? 相反,您必须将可写字符串传递给函数,因为您打算就地更改字符串。

问题2: if (str[0] >= 'a' && str[0] <= 'z') str[0] = str[0] - 32; 不是真正的可移植代码。

问题 3:为了递归而递归(现在我们有 3 个问题)。


您可以更高效、更便携地实现此功能:

(这也可以很容易地修改以涵盖语言环境:法语、西班牙语、德语等)

void str_toupper (char* str)
{
  static const char LUT[127] =
  {
    ['a'] = 'A',
    ['b'] = 'B',
    ['c'] = 'C',
    ['d'] = 'D',
    ['e'] = 'E',
    /* you get the idea */
  };

  for(size_t i=0; str[i] != '\0'; i++)
  {
    char converted = LUT[ str[i] ];
    if(converted)
      str[i] = converted;
  }
}

用法:

char str[] = "Hello World!";
str_toupper(str);

这里的技巧是查找表将所有未使用的项目设置为零,并且在大写转换期间将忽略这些项目。


如果您只想为了它而使用递归,那么这将是:

#ifdef MUST_USE_RECURSION_FOR_REASONS_UNKNOWN

void str_toupper (char* str)
{
  static const char LUT[127] =
  {
    ['a'] = 'A',
    ['b'] = 'B',
    ['c'] = 'C',
    ['d'] = 'D',
    ['e'] = 'E',
    /* you get the idea */
  };

  if(*str == '\0')
    return;

  char converted = LUT[*str];
  if(converted)
    *str = converted;  
  str_toupper(str+1); // tail call
}

#endif

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM