2015-05-17 3 views
1

Я пытаюсь написать программу, которая читает текстовый файл, сортирует его по символу и отслеживает, сколько раз каждый символ появляется в документе. Это то, что у меня есть до сих пор.Подсчет/сортировка символов в текстовом файле

class Program 
{ 
    static void Main(string[] args) 
    { 
     CharFrequency[] Charfreq = new CharFrequency[128]; 

     try 
     {    
     string line; 
     System.IO.StreamReader file = new System.IO.StreamReader(@"C:\Users\User\Documents\Visual Studio 2013\Projects\Array_Project\wap.txt"); 
     while ((line = file.ReadLine()) != null) 
     { 
      int ch = file.Read(); 

      if (Charfreq.Contains(ch)) 
      { 

      }  
     } 

     file.Close(); 

     Console.ReadLine(); 
     } 
     catch (Exception e) 
     { 
      Console.WriteLine("The process failed: {0}", e.ToString()); 
     } 
    } 
} 

Мой вопрос: что следует делать в инструкции if здесь?

У меня также есть класс Charfrequency, который я буду включать здесь, если это полезно/необходимо, чтобы я включил его (и да, необходимо, чтобы я использовал массив против списка или arraylist).

public class CharFrequency 
{ 
    private char m_character; 
    private long m_count; 

    public CharFrequency(char ch) 
    { 
     Character = ch; 
     Count = 0; 
    } 

    public CharFrequency(char ch, long charCount) 
    { 
     Character = ch; 
     Count = charCount; 
    } 

    public char Character 
    { 
     set 
     { 
      m_character = value; 
     } 

     get 
     { 
      return m_character; 
     } 
    } 

    public long Count 
    { 
     get 
     { 
      return m_count; 
     } 
     set 
     { 
      if (value < 0) 
       value = 0; 

      m_count = value; 
     } 
    } 

    public void Increment() 
    { 
     m_count++; 

    } 

    public override bool Equals(object obj) 
    { 
     bool equal = false; 
     CharFrequency cf = new CharFrequency('\0', 0); 

     cf = (CharFrequency)obj; 

     if (this.Character == cf.Character) 
      equal = true; 

     return equal; 
    } 

    public override int GetHashCode() 
    { 
     return m_character.GetHashCode(); 
    } 

    public override string ToString() 
    { 
     String s = String.Format("'{0}' ({1})  = {2}", m_character, (byte)m_character, m_count); 

     return s; 
    } 

} 
+0

Вы читаете символ char? И так, почему, если у вас есть вызов ReadLine()? –

+0

Литература не должна быть там, она является прежней формой кода раньше. – Cheeseop

+0

Почему вы просто не делаете «strbob = .ReadToEnd()», а затем просто перебираете набор символов с помощью strbob.length - strbob.replace (strloopchar) .length() и помещаете в массив? –

ответ

1

Вы не должны использовать Contains

сначала нужно инициализировать массив Charfreq:

CharFrequency[] Charfreq = new CharFrequency[128]; 

for (int i = 0; i < Charferq.Length; i++) 
{ 
    Charfreq[i] = new CharFrequency((char)i); 
} 

try 

, то вы можете

int ch; 

// -1 means that there are no more characters to read, 
// otherwise ch is the char read 
while ((ch = file.Read()) != -1) 
{ 
    CharFrequency cf = new CharFrequency((char)ch); 

    // This works because CharFrequency overloads the 
    // Equals method, and the Equals method checks only 
    // for the Character property of CharFrequency 
    int ix = Array.IndexOf(Charfreq, cf); 

    // if there is the "right" charfrequency 
    if (ix != -1) 
    { 
     Charfreq[ix].Increment(); 
    }  
} 

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

Как заметка на полях, эта программа будет считать "частоту" из ASCII символов (символы с кодом < = 127)

CharFrequency cf = new CharFrequency('\0', 0); 

cf = (CharFrequency)obj; 

И это бесполезно инициализации:

CharFrequency cf = (CharFrequency)obj; 

достаточно , в противном случае вы создаете CharFrequency, чтобы отбросить его ниже.

1

Словарь хорошо подходит для такой задачи. Вы не сказали, какой набор символов и кодировать файл. Итак, поскольку Unicode настолько распространен, допустим набор символов Unicode и кодировку UTF-8. (В конце концов, это значение по умолчанию для .NET, Java, JavaScript, HTML, XML, ...). Если это не так, прочитайте файл, используя подходящую кодировку, и исправьте свой код, потому что в настоящее время вы используете UTF-8 в своем StreamReader.

Далее идет итерация по «символам». А затем увеличивая счетчик для «символа» в словаре, как это видно в тексте.

Юникод имеет несколько сложных функций. Один из них объединяет символы, где базовый символ может быть наложен диакритикой и т. Д. Пользователи рассматривают такие комбинации как один «символ», или, как их называют Unicode, графемы. К счастью, .NET дает класс StringInfo, который итерации над ними как «текстовый элемент».

Итак, если вы думаете об этом, использование массива будет довольно сложным. Вам нужно будет создать собственный словарь поверх своего массива.

В приведенном ниже примере используется словарь и выполняется с использованием LINQPadscript.После создания словаря он заказывает и сбрасывает его с хорошим отображением.

var path = Path.GetTempFileName(); 
// Get some text we know is encoded in UTF-8 to simplify the code below 
// and contains combining codepoints as a matter of example. 
using (var web = new WebClient()) 
{ 
    web.DownloadFile("http://superuser.com/questions/52671/which-unicode-characters-do-smilies-like-%D9%A9-%CC%AE%CC%AE%CC%83-%CC%83%DB%B6-consist-of", path); 
} 
// since the question asks to analyze a file 
var content = File.ReadAllText(path, Encoding.UTF8); 
var frequency = new Dictionary<String, int>(); 
var itor = System.Globalization.StringInfo.GetTextElementEnumerator(content); 
while (itor.MoveNext()) 
{ 
    var element = (String)itor.Current; 
    if (!frequency.ContainsKey(element)) 
    { 
     frequency.Add(element, 0); 
    } 
    frequency[element]++; 
} 
var histogram = frequency 
    .OrderByDescending(f => f.Value) 
    // jazz it up with the list of codepoints in each text element 
    .Select(pair => 
     { 
      var bytes = Encoding.UTF32.GetBytes(pair.Key); 
      var codepoints = new UInt32[bytes.Length/4]; 
      Buffer.BlockCopy(bytes, 0, codepoints, 0, bytes.Length); 
      return new { 
       Count = pair.Value, 
       textElement = pair.Key, 
       codepoints = codepoints.Select(cp => String.Format("U+{0:X4}", cp)) }; 
     }); 
histogram.Dump(); // For use in LINQPad 
+0

Ничего себе! Я не заметил, что чрезмерная обработка суррогатных пар и составных персонажей! Я всегда люблю правильную обработку Unicode! :-) – xanatos

Смежные вопросы