2012-01-09 14 views
9

Я пытаюсь подсчитать количество слов из богатого текстового поля в C#, код, который у меня ниже, работает только в том случае, если это одна строка. Как это сделать, не полагаясь на регулярное выражение или какие-либо другие специальные функции.Подсчет количества слов в C#

string whole_text = richTextBox1.Text; 
string trimmed_text = whole_text.Trim(); 
string[] split_text = trimmed_text.Split(' '); 
int space_count = 0; 
string new_text = ""; 

foreach(string av in split_text) 
{ 
    if (av == "") 
    { 
     space_count++; 
    } 
    else 
    { 
     new_text = new_text + av + ","; 
    } 
} 

new_text = new_text.TrimEnd(','); 
split_text = new_text.Split(','); 
MessageBox.Show(split_text.Length.ToString()); 
+5

Вот подсказка для домашней работы: посмотреть на [Lines] (http://msdn.microsoft.com/en-us/library/system.windows. forms.textboxbase.lines.aspx) свойства RichTextBox для извлечения содержимого RTB. –

ответ

15

Поскольку вы заинтересованы только в количество слов, и вы не заботитесь об отдельных словах, String.Split можно было бы избежать. String.Split удобен, но он излишне генерирует (потенциально) большое количество объектов String, что, в свою очередь, создает ненужную нагрузку на сборщик мусора. Для каждого слова в вашем тексте необходимо создать экземпляр нового объекта String, а затем скоро собраться, так как вы его не используете.

Для домашнего задания это может иметь значение, но если содержимое вашего текстового поля часто изменяется, и вы выполняете это вычисление внутри обработчика событий, может быть разумнее просто перебирать символы вручную. Если вы действительно хотите использовать String.Split, перейдите к более простой версии, например, Yonix.

В противном случае, используйте алгоритм, аналогичный следующему:

var text = richTextBox1.Text.Trim(); 
int wordCount = 0, index = 0; 

while (index < text.Length) 
{ 
    // check if current char is part of a word 
    while (index < text.Length && !char.IsWhiteSpace(text[index])) 
     index++; 

    wordCount++; 

    // skip whitespace until next word 
    while (index < text.Length && char.IsWhiteSpace(text[index])) 
     index++; 
} 

Этот код должен работать лучше тех случаях, когда у вас есть несколько пробелов между каждым словом.

0

Ваш подход находится на правильном пути. Я бы сделал что-то вроде передачи свойства text richTextBox1 в метод. Это, однако, не будет точным, если ваш богатый текстовое поле форматирования HTML, так что вам нужно вырезать любые HTML-теги перед запуском количество слов:

public static int CountWords(string s) 
    { 
    int c = 0; 
    for (int i = 1; i < s.Length; i++) 
    { 
     if (char.IsWhiteSpace(s[i - 1]) == true) 
     { 
     if (char.IsLetterOrDigit(s[i]) == true || 
      char.IsPunctuation(s[i])) 
     { 
      c++; 
     } 
     } 
    } 
    if (s.Length > 2) 
    { 
     c++; 
    } 
    return c; 
} 
1

Посмотрите на Lines имущества, указанного в @ Комментарий Джей Риггса, а также this overload of String.Split, чтобы сделать код намного проще. Тогда самым простым подходом было бы перебрать каждую строку в свойстве Lines, вызвать на нем String.Split и добавить длину массива, который он возвращает, к счету выполнения.

EDIT: Также есть причина, по которой вы используете RichTextBox вместо TextBox с Multiline, установленным на True?

4

Есть некоторые лучшие способы сделать это, но в соответствии с тем, что у вас есть, попробуйте следующее:

string whole_text = richTextBox1.Text; 
string trimmed_text = whole_text.Trim(); 

// new line split here 
string[] lines = trimmed_text.Split(Environment.NewLine.ToCharArray()); 

// don't need this here now...    
//string[] split_text = trimmed_text.Split(' '); 

int space_count = 0; 
string new_text = ""; 

Теперь сделайте два Foreach петли. Один для каждой строки и один для подсчета слов в строках.

foreach (string line in lines) 
{ 
    // Modify the inner foreach to do the split on ' ' here 
    // instead of split_text 
    foreach (string av in line.Split(' ')) 
    { 
     if (av == "") 
     { 
      space_count++; 
     } 
     else 
     { 
      new_text = new_text + av + ","; 
     } 
    } 
} 

new_text = new_text.TrimEnd(','); 

// use lines here instead of split_text 
lines = new_text.Split(','); 
MessageBox.Show(lines.Length.ToString()); 
} 
24
char[] delimiters = new char[] {' ', '\r', '\n' }; 
whole_text.Split(delimiters,StringSplitOptions.RemoveEmptyEntries).Length; 
+2

Это было бы «Есть лучшие способы сделать это», о котором я упомянул в своем ответе;) +1. –

+0

+1 для 'RemoveEmptyEntries'. Это имеет значение, если в строке есть несколько пробельных символов. – Groo

2

Это был вопрос интервью телефон скрининга, что я просто взял (большой компании, расположенной в Центральной Азии, который продает все виды устройств, которые начинаются с буквы «я»), и я думаю, что я franked ... после того, как я вышел в оффлайн, я написал это. Мне жаль, что я не смог это сделать во время интервью.

static void Main(string[] args) 
{ 
    Debug.Assert(CountWords("Hello world") == 2); 
    Debug.Assert(CountWords(" Hello world") == 2); 
    Debug.Assert(CountWords("Hello world ") == 2); 
    Debug.Assert(CountWords("Hello  world") == 2); 
} 

public static int CountWords(string test) 
{ 
    int count = 0; 
    bool wasInWord = false; 
    bool inWord = false; 

    for (int i = 0; i < test.Length; i++) 
    { 
     if (inWord) 
     { 
      wasInWord = true; 
     } 

     if (Char.IsWhiteSpace(test[i])) 
     { 
      if (wasInWord) 
      { 
       count++; 
       wasInWord = false; 
      } 
      inWord = false; 
     } 
     else 
     { 
      inWord = true; 
     } 
    } 

    // Check to see if we got out with seeing a word 
    if (wasInWord) 
    { 
     count++; 
    } 

    return count; 
} 
0

Мы использовали адаптированную форму ответа Йоши, где мы исправили ошибку, когда он не будет рассчитывать последнее слово в строке, если не было белого пространства после него:

public static int CountWords(string test) 
{ 
    int count = 0; 
    bool inWord = false; 

    foreach (char t in test) 
    { 
    if (char.IsWhiteSpace(t)) 
    { 
     inWord = false; 
    } 
    else 
    { 
     if (!inWord) count++; 
     inWord = true; 
    } 
    } 
    return count; 
} 
0
public static int WordCount(string str) 
{   
    int num=0; 
    bool wasInaWord=true;; 

    if (string.IsNullOrEmpty(str)) 
    { 
     return num; 
    } 

    for (int i=0;i< str.Length;i++) 
    { 
     if (i!=0) 
     { 
      if (str[i]==' ' && str[i-1]!=' ') 
      { 
       num++; 
       wasInaWord=false; 
      } 
     } 
      if (str[i]!=' ') 
      { 
       wasInaWord=true;     
      } 
    } 
    if (wasInaWord) 
    { 
     num++; 
    } 
    return num; 
} 
+0

Просьба привести некоторое объяснение кода в вашем ответе. –

-1

Вы также можете сделать это таким образом! Добавьте этот метод к вашим методам расширения.

public static int WordsCount(this string str) 
    { 
     return Regex.Matches(str, @"((\w+(\s?)))").Count; 
    } 

И назовите это так.

string someString = "Let me show how I do it!"; 
    int wc = someString.WordsCount(); 
+0

Это дает неправильный ответ, если у нас есть несколько пробелов или «\ r \ n» разрыв строк между словами. – Artemious

0

Это должно работать

input.Split(' ').ToList().Count; 
Смежные вопросы