【问题标题】:Compare strings比较字符串
【发布时间】:2011-07-06 22:34:39
【问题描述】:

谢谢!现在完美运行。 Java让我变得愚蠢:(

我在比较 C 中的字符串时遇到了一些困难。当我不使用我的 isMorse 函数时,我得到了正确的输出,但是当我使用它时,输出变得不准确并显示随机字符。据我所知,变量“morse”实际上在调用 strcmp 时发生了变化。我认为这与“莫尔斯”不是一个常数有关,但我不确定如何补救。

谢谢!!

char *EnglishToMorse(char english)
{
   static char *morse;

   int i;
   for (i = 0; i < LOOKUP_SIZE; i++)
   {
      if (lookup[i].character == english)
      {
         morse = lookup[i].morse;
         return morse;
      }
   }

   morse = &english;  // Problem was here!!!
   return morse;
}

【问题讨论】:

  • 您说“输出变得不准确”,但您的示例代码没有任何输出语句。请发布一个简短、完整、可运行的示例来演示您所看到的行为(不要忘记提及您期望看到的内容)。
  • 你确定EnglishToMorse 正在返回一个以 NULL 结尾的字符串吗?
  • strcmp(const char*, const char*) 不应该改变你的莫尔斯变量
  • lookup 数组是什么?注意空格(空格、制表符、换行符):"---""---\n""--- " 不同。

标签: c string string-comparison


【解决方案1】:

morse 变量出现变化的原因是它指向堆栈上的一个区域。它指向堆栈上的一个区域的原因是因为您为其分配了参数english 的地址,该地址在您调用函数时被压入堆栈,然后在函数完成后从堆栈中弹出。

现在,您的 morse 变量将指向堆栈上相同位置的任何内存,这将在您的程序的整个生命周期中不断变化。

在我看来,解决此问题的最佳方法是从 EnglishToMorse 返回一个 NULL 指针,如果字符不是 A-Z...,然后检查 isMorse 函数中的 NULL 指针。毕竟,检查代码中的 NULL 指针是个好习惯。

char* EnglishToMorse(char english)
{
    int i;

    english = toupper(english);
    for (i = 0; i < LOOKUP_SIZE; i++)
    {
        if (lookup[i].character == english)
            return lookup[i].morse;
    }

    return NULL;
}

int isMorse(char* morse)
{
    int i;

    /* Check for NULL, so strcmp doesn't fail. */
    if (morse == NULL) return 0;

    for (i = 0; i < LOOKUP_SIZE; i++)
    {
        if(strcmp(morse, lookup[i].morse) == 0) 
            return 1;
    }

    return 0;
}

【讨论】:

    【解决方案2】:

    EnglishToMorse 中有一个静态变量,但它是错误的。 morse 没有必要是静态的——你只需返回它。但是你确实需要英语是静态的——而不是在堆栈上——因为你返回了它的地址。此外,它必须是一个以 NUL 结尾的字符串。做类似的事情

    char *EnglishToMorse(char english)
    {
       static char save_english[2]; /* initialized to 0's */ 
    
       int i;
       for (i = 0; i < LOOKUP_SIZE; i++)
          if (lookup[i].character == english)
             return lookup[i].morse;
    
       save_english[0] = english;
       return save_english;
    }
    

    但是请注意,EnglishToMorse 的调用者必须在再次调用 EnglishToMorse 之前使用或保存结果,因为第二次调用可能会覆盖 static_english。

    【讨论】:

    • @Cory 不要忘记接受答案。这里有几个不错的,不仅仅是我的。
    【解决方案3】:

    char *EnglishToMorse(char english)

    morse = &amp;english;
    是问题所在。

    永远不要返回指向局部变量或函数参数的指针。

    【讨论】:

      【解决方案4】:

      看起来问题可能出在这个函数中:

      char *EnglishToMorse(char english) {
          static char *morse;
          // ...
          morse = &english;
          return morse;
      }
      

      您正在返回传递给函数的参数的地址 (english)。该参数在函数返回后(在调用者有机会实际看到该值之前)不复存在。您似乎试图通过将 morse 变量声明为静态来解决此问题,但这只会使 morse 变量本身成为静态,而不是它指向的任何内容。

      此外,C 中的字符串必须以 NUL 字符结尾。通过返回一个指向单个字符的指针(如english),不能保证内存中的下一个字节是或不是NUL字符。因此,期望看到以 NUL 结尾的字符串的调用者可能会得到比他们讨价还价的更多。

      【讨论】:

        【解决方案5】:

        我有一点猜测。函数EnglishToMorse() 可能会从堆栈返回一个指向内存的指针。如果是这样,在EnglishToMorse() 之后运行另一个函数将改变该内存。这可能是由于EnglishToMorse() 中的一个错误——声明了一个char 的本地数组并返回了一个指向它的指针。

        没有看到EnglishToMorse() 的代码,这只是在黑暗中刺伤。您可以提供更多代码让我们查看并获胜。

        【讨论】:

        • +1 - 如果数据没有调用 isMorse() 就可以,这听起来很可能,因为它可能仍在堆栈上。调用另一个函数将导致新的内容被压入堆栈。
        • 我发布了我的 EnglishToMorse 函数。感谢您的回复。
        • 我应该将“morse”作为附加参数传递给 EnglishToMorse(),而不是将其声明为局部静态变量吗?
        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多