使用ReadByte()读取泛型类型

时间:2014-03-20 20:17:08

标签: c# algorithm generics data-structures generic-programming

我是一名c#初学者,试图读取二进制文件中的符号。我在c#中使用ReadByte()以单一参数读取这个二进制文件。这样做

using(var stream = new BinaryReader(System.IO.File.OpenRead(args[0])))

之后我做了

 while (stream.BaseStream.Position < stream.BaseStream.Length) 
 {
   int symbol = stream.ReadByte(); 
   //And then i do my stuff
 }   

直到这里,每件事都很好。

但我的下一步是制作通用类型"<T>"的符号。 所以我的算法是:

namespace Final 
{
    public Class A <T> where T: IComparable <T> 
    {
        public Class Node
        {
            public T symbol; //This symbol has to be generic type because symbol may be int/long/uint etc. on 32/64 bit archtecture.
            public Node next;
            public int freq;
        }
        public Node Front;

        public A(string[] args) //it's a constructor
        {
            Front = null;
            using(var stream = new BinaryReader(System.IO.File.OpenRead(args[0]))) 
            {                    
                while (stream.BaseStream.Position < stream.BaseStream.Length) 
                {  
                    Func < byte, T > converter = b = > new T(b);
                    byte byteValue = stream.ReadByte();
                    T processingValue = converter(byteValue); //here is the problem
                    Node pt, temp;
                    pt = Front;
                    while (pt != null)
                    {
                        if (pt.symbol == processingValue) //here is the problem
                        {
                            pt.freq++;
                            break;
                        }
                        temp = pt;
                        pt = pt.next;
                    }
                }
            }
            stream.Close();
        }
    }
    public class MyClass
    {
        public static void Main(string[] args)
        {
            A <T> ObjSym = new A <T> (args); //object creation        
        }
    }
}

请注意three class Class AClass Node(包含符号)和Class MyClass(包含main()函数,我创建object)和在课堂A中,我有constructor

现在我想要实现的目标是,我正在尝试制作&#34;符号&#34;作为通用数据类型,我的意思是在32/64位架构上符号可能是int / uint / long等。另请注意我正在阅读{{1 } {strong>在Binary File ,二进制符号的格式为(11010101等)。

我真的很感激,如果有人可以通过编辑来纠正我的算法,从而实现我的目标,即将符号设置为sole argument()类型,因为我昨天被卡住了。非常感谢你。

编辑:完整代码:

"generic"

错误是:(对于调试我尝试在构造函数中打印check1和check2,但它只打印&#34; check1&#34; not&#34; check2&#34;)。请直到输出结束:

using System;
using System.IO;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Runtime.InteropServices;


namespace shekhar_final_version_Csharp
 {
  //  public class Huffman<K> where K :  IComparable<K>
    public class Huffman < T > where T: struct, IComparable < T > , IEquatable < T > 
    {
        public int data_size, length, i, is_there;
         public class Node
        {
            public Node next, left, right;
            public T symbol;
            public int freq;
            public int is_processed;
        }
        public Node front, rear;
        ///////////////////////////////////////////////
      //  public Huffman(string[] args) 
        public Huffman(string[] args, Func < byte[], int, T > converter) 
        {
            front = null;
            rear = null;
            int size = Marshal.SizeOf(typeof (T));
            // Console.WriteLine("Size: {0}  ", size);
            using(var stream = new BinaryReader(System.IO.File.OpenRead(args[0]))) 
            {
                while (stream.BaseStream.Position < stream.BaseStream.Length) 
                {
                   byte[] bytes = stream.ReadBytes(size);   
                    T processingValue = converter(bytes, 0); 
                    {
                        Node pt, temp;
                        bool is_there = false;
                        pt = front;
                        while (pt != null) 
                        { 
                             if (pt.symbol.Equals(processingValue))
                            {
                                pt.freq++;
                                is_there = true;

                                break;
                            }
                            temp = pt;
                            pt = pt.next;
                        }
                        if (is_there == false) 
                        {  
                            temp = new Node();
                            temp.symbol = processingValue;
                            temp.freq = 1;
                            temp.left = null;
                            temp.right = null;
                            temp.next = null;
                            temp.is_processed = 0;
                            if (front == null) 
                            {
                                front = temp;
                            } 
                            else 
                            {
                            //    Console.WriteLine("Symbol : {0}  frequency is : {1}", pt.symbol, pt.freq);
                                temp.next = front;
                                front = temp;
                            }
                        }
                    }
                    Console.WriteLine("check1");
                }
                Console.WriteLine("check2");                
                stream.Close();

                //////////////////////////////
            }
        }
        public void Print_tree( Node treee) 
        {
            Node pt = treee;
            while (pt != null) 
            {
                Console.WriteLine("Symbol : {0}  frequency is : {1}", pt.symbol, pt.freq);
                pt = pt.next;
            }
        }

        /////////////////////////////
        public Node find_two_smallest(ref  Node pmin1, ref  Node pmin2) 
        {
            Node temp = front;
            Node temp6 = front;
            Node address = null;
            Node min1;
            min1 = new Node();
            min1.freq = int.MaxValue;
            Node min2;
            min2 = new Node();
            min2.freq = int.MaxValue;
            while (temp != null)
            {
                if (temp.is_processed == 0) 
                {
                    if (temp.freq < min2.freq) 
                    {
                        min1 = min2;
                        min2 = temp;
                    } 
                    else if (temp.freq < min1.freq && temp.freq != min2.freq) 
                    {
                        min1 = temp;
                    }
                    temp = temp.next;
                } 
                else if (temp.is_processed == 1) 
                {
                    temp = temp.next;
                }
            }
            pmin1 = min1;
            pmin2 = min2;
            //  Below is the code to find the address of first minimum arriving on traversal of List which will be "front" for next execution.
            while (temp6 != null) 
            {
                if (temp6.freq == min1.freq || temp6.freq == min2.freq) 
                {
                    address = temp6;
                    break;
                }
                temp6 = temp6.next;

            }
            return address;
        }
        ///////////////////////////////////////////////////////////////////
        public int count_remaining() 
        {
            int remaining = 0;
            Node pt = front;
            while (pt != null) 
            {
                if (pt.is_processed == 0) 
                {
                    remaining += 1;
                }
                pt = pt.next;
            }
            return remaining;
        }
        ////////////////////////////////////////////////////////////////////////////
        public void huffman_node_processing() 
        {
            Node temp, temp2;
            temp2 = front;
            while (temp2 != null) 
            {
                if (temp2.next == null) 
                {
                    rear = temp2;
                    break;
                }
                temp2 = temp2.next;
            }
            int remaining;
            int counter = 0;
            remaining = count_remaining();

// You can un-comment these console.writeline(..); which are commented below if you want to see how the addition of nodes taking place(which nodes are added), 
//I have commented it inorder to give direct and clear output.
            while (front != rear) 
            {
                if (counter == 0) 
                {
                    temp = new Node();
                    Console.WriteLine("first element1 {0} ", front.freq);
                    Console.WriteLine("second element1 {0} ", front.next.freq);
                    temp.freq = front.freq + front.next.freq;
                    front.is_processed = 1;
                    front.next.is_processed = 1;
                    temp.is_processed = 0;
                    temp.left = front;
                    temp.right = front.next;
                    temp.next = null;
                    rear.next = temp;
                    front = front.next.next;
                    Console.WriteLine("tempcheck1 {0} ", temp.freq);
                    rear = rear.next;
                    remaining = count_remaining();
                    if (remaining == 1) 
                    {
                        break;
                    }
                }
                if (rear.freq == front.freq) 
                {
                    //Console.WriteLine("first element2 {0} ", front.freq);
                    //Console.WriteLine("second element2{0} ", front.next.freq);
                    temp = new Node();
                    temp.freq = front.freq + rear.freq;
                    rear.is_processed = 1;
                    front.is_processed = 1;
                    temp.is_processed = 0;
                    temp.left = front;
                    temp.right = rear;
                    temp.next = null;
                    rear.next = temp;
                    front = front.next;
                    //Console.WriteLine("temp check2 {0} ", front.freq);
                    rear = rear.next;
                    remaining = count_remaining();
                    if (remaining == 1) 
                    {
                        break;
                    }
                }

                if (rear.freq > front.freq) 
                {
                    Node pmin1 = null;
                    Node pmin2 = null;
                    Node address = find_two_smallest(ref pmin1, ref pmin2);
                    temp = new Node();
                    Console.WriteLine("pmin1check3 {0} ", pmin1.freq);
                    Console.WriteLine("pmin2check3 {0} ", pmin2.freq);
                    temp.freq = pmin1.freq + pmin2.freq;
                    pmin1.is_processed = 1;
                    pmin2.is_processed = 1;
                    temp.is_processed = 0;
                    temp.left = pmin2;
                    temp.right = pmin1;
                    temp.next = null;
                    rear.next = temp;
                    front = address;
                    Console.WriteLine("tempcheck3 {0} ", temp.freq);
                    rear = rear.next;
                    remaining = count_remaining();
                    if (remaining == 1) 
                    {
                        break;
                    }
                }

                if (rear.freq < front.freq) 
                {
                    Node pmin1 = null;
                    Node pmin2 = null;
                    Node address = find_two_smallest(ref pmin1, ref pmin2);
                    temp = new Node();
                    //Console.WriteLine("pmin1check4 {0} ", pmin1.freq);
                    //Console.WriteLine("pmin2check4 {0} ", pmin2.freq);
                    temp.freq = pmin1.freq + pmin2.freq;
                    pmin1.is_processed = 1;
                    pmin2.is_processed = 1;
                    temp.is_processed = 0;
                    temp.left = pmin2;
                    temp.right = pmin1;
                    temp.next = null;
                    rear.next = temp;
                    front = address;
                    //Console.WriteLine("tempcheck4 {0} ", temp.freq);
                    rear = rear.next;
                    remaining = count_remaining();
                    if (remaining == 1) 
                    {
                        break;
                    }
                }
                counter++;
            }

        }
        ////////////////////////////////////////////
        public void GenerateCode( Node parentNode, string code) 
        {
            if (parentNode != null) 
            {
                GenerateCode(parentNode.left, code + "0");
                if (parentNode.left == null && parentNode.right == null)
                    Console.WriteLine("Symbol : " + parentNode.symbol + "  frequency is :  " + code);
                GenerateCode(parentNode.right, code + "1");
            }
        }

    }
    public class MyClass 
    {
        public static void Main(string[] args) 
        {
           // Huffman<K>  ObjSym = new Huffman<K>(args); //object creation
            Huffman < long > ObjSym = new Huffman < long > (args, BitConverter.ToInt64);
            Console.WriteLine("\nReading the Binary file......");
            ObjSym.Print_tree(ObjSym.front);
            ObjSym.huffman_node_processing();
            Console.WriteLine("\nThe encoding of symbols are :");
            ObjSym.GenerateCode(ObjSym.rear, "");

        }
    }
}

1 个答案:

答案 0 :(得分:2)

您必须将转换函数和数字类型的大小传递给A的构造函数:

public A(string[] args, int size, Func<byte[], int, T> converter) { ... }
 A<long> ObjSym = new A<long>(args, sizeof(long), BitConverter.ToInt64)

而不是直接传递大小,您可以使用Marshal.SizeOf

int size = Marshal.SizeOf(typeof(T));

然后,您可以从阅读器中读取所需的字节数并进行转换:

byte[] bytes = stream.ReadBytes(size);
T processingValue = converter(bytes, 0);

您可以使用Equals检查符号:

if (pt.symbol.Equals(processingValue))

如果进一步约束type参数以实现IEquatable<T>,则可以在等式检查期间避免装箱:

public class A<T> where T : struct, IComparable <T>, IEquatable<T>
{
    public class Node
    {
        public T symbol;
        public Node next;
        public int freq;
    }

    public Node Front;

    public A(string[] args, Func<byte[], int, T> converter)
    {
        int size = Marshal.SizeOf(typeof(T));
        Front = null;
        using(var stream = new BinaryReader(System.IO.File.OpenRead(args[0]))) 
        {                    
            while (stream.BaseStream.Position < stream.BaseStream.Length) 
            {
                byte[] bytes = stream.ReadBytes(size);
                T processingValue = converter(bytes, 0);

                Node pt, temp;
                pt = Front;
                while (pt != null)
                {
                    if (pt.symbol.Equals(processingValue))
                    {
                        pt.freq++;
                        break;
                    }
                    temp = pt;
                    pt = pt.next;
                }
            }
        }
    }
}