簡體   English   中英

在字符串開頭找到字母,后跟空格

[英]find letter at the beginning of the string followed by space

我想寫一個方法來計算字母“ a”或“ A”。 “ a”可以在字符串的開頭,后跟空格,或者在字符串中被空格包圍的任何位置。 結果應該是2,但是我的代碼得到5,如何修改代碼,以便它檢測a之前和之后的空間?

using System;

namespace Hi
{
    class Program
    {
        static void Main(string[] args)
        {
            string t1 = "A book was lost. There is a book on the table. Is that the book?";

            Console.WriteLine(t1);
            Console.WriteLine(" - Found {0} articles, should be 2.", CountArticles(t1));
            Console.ReadKey();
        }

        static int CountArticles(string text)
        {
            int count = 0;

            {
                for (int i = 0; i < text.Length; ++i)
                {
                    if (text[i] == 'a' || text[i] == 'A')
                    {
                        ++count;
                    }
                }            
                return count;
        }
    }
}
}

我建議使用正則表達式來計算所有匹配項。 像這樣的東西:

  using System.Text.RegularExpressions;

  ... 

  string t1 = "A book was lost. There is a book on the table. Is that the book?";

  int count = Regex.Matches(t1, @"\bA\b", RegexOptions.IgnoreCase).Count;

如果您堅持使用for循環,則必須檢查空格

  static int CountArticles(string text)
  {
      int count = 0;

      for (int i = 0; i < text.Length; ++i)
      {
          if (text[i] == 'a' || text[i] == 'A')
          {
             // So we have a or A, now we have to check for spaces:
             if (((i == 0) || char.IsWhiteSpace(text[i - 1])) &&
                 ((i == text.Length - 1) || char.IsWhiteSpace(text[i + 1])))
                ++count;
           }
       }            

       return count;
  } 

就個人而言,我非常喜歡簡單的DFA狀態機。 感覺很奇怪,所以我將解釋原因...歸結為以下幾個原因:

  1. DFA的速度非常快; 如果您像我一樣進行解析,則很有可能在此代碼中拋出大量數據。 性能很重要。
  2. DFA非常容易進行單元測試; 您唯一需要做的就是確保測試所有狀態和轉換。
  3. DFA的代碼覆蓋率報告非常有用。 它不能保證您的設計是正確的,但是如果是正確的,那么它將起作用。 您肯定會從中獲得比Regex涵蓋的更多信息。

主要缺點是:

  1. 他們需要更多的工作來構建。 (*)
  2. 您應該使用一張紙來思考它們(並像其他人那樣記錄下來)。

一旦您有了主意,就可以輕松構建DFA。 拿一張紙,考慮一下程序的可能狀態(畫圓圈),並在它們之間進行轉換(圓圈之間的箭頭)。 最后,考慮一下什么時候會發生。

轉換為代碼幾乎是1:1。 使用開關只是一種實現方式-還有其他方式可以做到這一點。 無論如何,這里沒有進一步的干擾:

enum State
{
    SpaceEncountered,
    ArticleEncountered,
    Default
};

static int CountArticles(string text)
{
    int count = 0;
    State state = State.SpaceEncountered; // start of line behaves the same

    for (int i = 0; i < text.Length; ++i)
    {
        switch (state)
        {
            case State.SpaceEncountered:
                if (text[i] == 'a' || text[i] == 'A')
                {
                    state = State.ArticleEncountered;
                }
                else if (!char.IsWhiteSpace(text[i]))
                {
                    state = State.Default;
                }
                break;

            case State.ArticleEncountered:
                if (char.IsWhiteSpace(text[i]))
                {
                    ++count;
                    state = State.SpaceEncountered;
                }
                else
                {
                    state = State.Default;
                }
                break;
            case State.Default: // state 2 = 
                if (char.IsWhiteSpace(text[i]))
                {
                    state = State.SpaceEncountered;
                }
                break;
        }
    }

    // if we're in state ArticleEncountered, the next is EOF and we should count one extra
    if (state == State.ArticleEncountered)
    {
        ++count;
    }
    return count;
}

static void Main(string[] args)
{
    Console.WriteLine(CountArticles("A book was lost. There is a book on the table. Is that the book?"));
    Console.ReadLine();
}

(*)現在,我看到人們在思考,好吧,這么一個簡單的問題的代碼很多。 是的,這是真的,這就是為什么存在生成DFA的方法的原因。 最常用的方法是構造一個詞法分析器或正則表達式。 這個玩具問題有點多,但也許您真正的問題要大一些...

像這樣使用String.Split

int count = text.Split(' ').Count(c => c == "a" || c == "A");

您還可以使用TextInfo類將字符串作為“ 標題大小寫”,以便字符串的開頭或后跟空格

一本書丟了。 桌上有一本書。 那是書嗎?

現在您可以使用CountArticles函數來計算角色

  namespace Hi
{
    class Program
    {
        static void Main(string[] args)
        {


    string t1 = "A book was lost. There is a book on the table. Is that the book?";

            Console.WriteLine(t1);
            Console.WriteLine(" - Found {0} articles, should be 2.", CountArticles(t1));
            Console.ReadKey();
        }

        static int CountArticles(string text)
        {
            int count = 0;

            // Here you may also try TextInfo
            //Make string as a Title Case
            //the beginning of the string OR followed by space would be now  'A'
            TextInfo textInfo = new CultureInfo("en-US", false).TextInfo;
            text = textInfo.ToTitleCase(text); 


            {
                for (int i = 0; i < text.Length; ++i)
                {
                    if (text[i] == 'A')
                    {
                        ++count;
                    }
                }
                return count;
            }
        }
    }
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM