突破递归方法

时间:2019-04-05 18:38:30

标签: c#

我有以下可行的递归方法,但似乎无法打破它:

public static void smsMessage(string message, int maxLength)
{ 
  int strPos = 0;

  var spaces = message.ToCharArray()
    .Select((v, x) => new { value = v, index = x })
    .Where(element => !char.IsLetterOrDigit(element.value))
    .Select(element => element.index)
    .ToList();

  for (int i = 0; i < spaces.Count; ++i)
  {
    strPos += spaces[i];

    if (strPos >= maxLength || i == spaces.Count - 1 )
    {
      if (i == spaces.Count-1)
      {
        strPos -= spaces[i];

        returnMessage.Add(message.Substring(0).Trim());

        return;
      }

      strPos -= spaces[i];

      returnMessage.Add(message.Substring(0, spaces[i - 1]).Trim());

      message = message.Remove(0, spaces[i - 1] + 1);

      if (message.Length > 0) // keep processing until done
      {
        smsMessage(message, maxLength);
      }
    }
  }
}

我击中if statment (i == space.Count-1)并处理了最后一条消息,然后击中了return,但此后它又跳到了smsMessage(message, maxLength)行并抛出了错误。我现在想完成处理。如何退出此方法?

谢谢。

1 个答案:

答案 0 :(得分:8)

您的方法很难理解,因此很难正确使用。

我对编写递归方法的新手的建议是始终遵循相同的模式,直到您掌握它为止。首先获得正确的签名:

  • 递归方法永远不要改变全局状态,因此不应无效。它应该返回结果。您的方法会改变全局状态。 更改全局状态的递归方法很难推理
  • 如果难以表达您的逻辑而不进行突变,请变异传入的累加器,而不是全局状态,然后返回void。然后编写一个创建累加器的助手方法。

现在我们来看一下方法的主体。

  • 我们在基本情况下吗?如果是,则返回结果。
  • 我们不在基本情况下。
  • 将问题划分为n个较小问题。 每个子问题的难度必须小于您要解决的问题的难度。如果不满足此条件,则递归不会终止。
  • 递归解决每个较小的问题,产生n个解决方案。
  • 组合解决方案以解决更大的问题。
  • 返回解决方案。

也就是说,递归方法正确地只有两点可以返回:基本情况之后和递归情况之后。

我的建议是,您编写程序时应清楚遵循此模式,并确认您实际上正在解决一个较小的问题。

因此,从头开始:方法的签名是什么?让我们使用累积技术并说:

public static List<string> SMSMessage(string message, int maxLength)
{
  var accumulator = new List<string>();
  SMSMessage(accumulator, message, maxlength);
  return accumulator;
}

private static void SMSMessage(
  List<string> accumulator, 
  string message, 
  int maxLength)
{ 
  // IF (BASE CASE) { DO BASE CASE, RETURN }
  // DO RECURSIVE CASE, RETURN
}

好的,基本情况是什么?也就是说,我们什么时候不做任何递归操作?

  var trimmed = message.Trim();
  if (trimmed.Length <= maxLength)
  {
    if (trimmed.Length != 0)
      accumulator.Add(trimmed);
    return;
  }

超级。现在,递归情况是什么?您必须提出一个或多个可以递归解决的小问题。您可以从这里解决吗?