C#练习题答案: ASCII85编解码【难度:3级】--景越C#经典编程题库,1000道C#基础练习题等你来挑战

ASCII85编解码【难度:3级】:

答案1:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text.RegularExpressions;

public class Ascii85
{
     
    public static string toAscii85(byte[] data)
    {
   
        // Throw out invalid data
        if (data == null || data.Length == 0) return "<~~>";

        // Right-pad the array with 0's as necessary, then convert to a list of 4-byte integers
        var extra = data.Length % 4 == 0 ? 0 : 4 - data.Length % 4;
        var bytes = data.Concat(Enumerable.Repeat((byte)0, extra)).Reverse().ToArray();
        var nums = Enumerable.Range(0, bytes.Length / 4).Select(i => BitConverter.ToUInt32(bytes, 4 * i));

        // Encode each 4-byte integer (split into 5 even parts) as ASCii characters
        var chars = new List<char>();
        foreach (var num in nums)
        {
   
            for (uint x = num, i = 0; i < 5; x /= 85, i++)
            {
   
                chars.Insert(0, (char)(x % 85 + 33));
            }
        }

        // Trim the extra characters off, compress, and bound the encoded string with the special values
        var trimmed = string.Concat(chars.Take(chars.Count() - extra));
        var compressed = string.Concat(Enumerable.Range(0, (trimmed.Length) / 5).Select(i => trimmed.Substring(5 * i, 5)).Select(s => s == "!!!!!" ? "z" : s));
        if (trimmed.Length % 5 > 0) compressed += trimmed.Substring(trimmed.Length / 5 * 5);
        return "<~" + compressed + "~>";
    }

    public static byte[] fromAscii85(string data)
    {
   
        // Throw out invalid data
        if (string.IsNullOrEmpty(data)) return new byte[0];

        // Strip off the special values, decompress, replace appropriate z's with !!!!!'s, and right-pad the string with u's
        var zIndex = 0;
        var rawData = data.Substring(2, data.Length - 4).Replace(" ", "");
        while (zIndex < rawData.Length)
        {
   
            zIndex = rawData.IndexOf('z', zIndex);
            if (zIndex == -1) break;
            if (zIndex % 5 == 0)
                rawData = rawData.Remove(zIndex, 1).Insert(zIndex, "!!!!!");
            else
                zIndex++;
        }
        var extra = rawData.Length % 5 == 0 ? 0 : 5 - rawData.Length % 5;
        var chars = rawData.Select(c => c).Concat(Enumerable.Repeat('u', extra)).ToArray();

        // Decode each group of 5 ASCii characters into a 4-byte integer
        var nums = new List<uint>();
        var i = 4;
        var x = 0U;
        foreach (var ch in chars)
        {
   
            x += (uint)((ch - 33) * Math.Pow(85, i));
            if (--i < 0)
            {
   
                nums.Add(x);
                i = 4;
                x = 0U;
            }
        }

        // Convert the list of 4-byte integers into single bytes
        var bytes = nums.SelectMany(u => Enumerable.Range(1, 4).Select(j => (byte)(u >> ((4 - j) * 8))));
        return bytes.Reverse().Skip(extra).Reverse().ToArray();

    }
}

答案2:

using System;
using System.IO;
using System.Linq;
using System.Text;


public class Ascii85
    {
   
        private const string prefix = "<~";
        private const string suffix = "~>";
        private const char ascii33 = '!';

        static void EncodeBlock(int padLength, uint value, StringBuilder sb)
        {
   
            if (value == 0)
            {
   
                sb.Append('z');
            }
            else
            {
   
                char[] encoded = new char[5];

                for (int index = 4; index >= 0; index--)
                {
   
                    encoded[index] = (char) ((value % 85) + ascii33);
                    value /= 85;
                }

                if (padLength != 0)
                    Array.Resize(ref encoded, 5 - padLength);

                sb.Append(encoded);
            }
        }

        public static string toAscii85(byte[] data)
        {
   
            StringBuilder sb = new StringBuilder();

            int count = 0;
            uint value = 0;

            sb.Append(prefix);
            if(data.Length == 0) {
   
              sb.Append(suffix);
              return sb.ToString();
            }

            if (data.All(d => d == '\0') &amp;&amp; data.Length < 4)
            {
   
                sb.Append(new string('!', data.Length + 1));
                sb.Append(suffix);
                return sb.ToString();
            }

            foreach (byte b in data)
            {
   
                value |= ((uint) b) << (24 - (count * 8));

                if (++count == 4)
                {
   
                    EncodeBlock(0, value, sb);

                    count = 0;
                    value = 0;
                }
            }

            if (count > 0)
                EncodeBlock(4 - count, value, sb);

            sb.Append(suffix);
            return sb.ToString();
        }

        public static byte[] fromAscii85(string data)
        {
   
            data = data.Substring(2, data.Length - 4);

            var calculatedPow85 = new uint[] {
   85u * 85u * 85u * 85u, 85u * 85u * 85u, 85u * 85u, 85u, 1};

            using (MemoryStream stream = new MemoryStream(data.Length * 4 / 5))
            {
   
                int count = 0;
                uint value = 0;

                foreach (char ch in data.Where(b => !char.IsWhiteSpace(b)))
                {
   
                    if (ch == 'z' &amp;&amp; count == 0)
                    {
   
                        DecodeBlock(stream, value, 0);
                    }
                    else
                    {
   
                        value += (uint) (calculatedPow85[count] * (ch - ascii33));

                        count++;
                        if (count == 5)
                        {
   
                            DecodeBlock(stream, value, 0);

                            count = 0;
                            value = 0;
                        }
                    }
                }

                if (count > 1)
                {
   
                    for (int padding = count; padding < 5; padding++)
                    {
   
                        value += 84 * calculatedPow85[padding];
                    }

                    DecodeBlock(stream, value, 5 - count);
                }

                return stream.ToArray();
            }
        }

        static void DecodeBlock(Stream stream, uint value, int padLength)
        {
   
            for 

你可能感兴趣的:(C#编程训练习题答案,csharp面试题库和答案,csharp编程练习,算法,二进制,ASCII)