Generate combination using string array in c# [duplicate] - c#

This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
Different combinations of an array (C#)
string[] array = {"01", "02", "03", "04", "05", "06", "07", "08", "09", "10"};
How to generate to 2 / 3 / 4 / 5 strings per combination like for example 2 strings per combination, with no repeats/duplicates, disregard of position as well, using combination formula nCr = 10!/2!(10-2)! = 45 combinations.
I need the output to be like this:
"01", "02"
"01", "03"
"01", "04"
...
"02", "03" // eliminate the "02","01" 'cause it is same as "01","02" combination
"02", "04"
...
Then to generate combinations of 3 strings, would have 120 combinations (according to nCr).
I need the output to be like this:
"01","02","03"
"01","02","04"
...
And combinations of 4 strings, would have 210 combinations, the least, combinations of 5 strings per combination, would have 252 combinations.
How can I write that? I've used up many loops and it looks really a mess.

You could use a simple recursion:
private static IEnumerable<string> Combinations(int start, int level)
{
for ( int i = start; i < array.Length; i++ )
if ( level == 1 )
yield return array[i];
else
foreach ( string combination in Combinations(i + 1, level - 1) )
yield return String.Format("{0} {1}", array[i], combination);
}
The call it like this:
var combinations = Combinations(0, 2);
foreach ( var item in combinations )
Console.WriteLine(item);

You can use this efficient project: Permutations, Combinations, and Variations using C# Generics.
string[] array = { "01", "02", "03", "04", "05", "06", "07", "08", "09", "10" };
int lowerIndex = 2;
var combinations = new Facet.Combinatorics.Combinations<String>(
array,
lowerIndex,
Facet.Combinatorics.GenerateOption.WithoutRepetition
);
foreach (IList<String> combis in combinations)
{
String combi = String.Join(" ", combis);
Console.WriteLine(combi);
}
Since it's open source you can look how it's implemented. But the link above is also very informative.
output (lowerIndex=2):
01 02
01 03
01 04
01 05
01 06
01 07
01 08
01 09
01 10
02 03 <-- no 02 01 since it would be a repitition
02 04
02 05
// ... (45 combinations w/o repetitions)
09 10
output (lowerIndex=5):
01 02 03 04 05
01 02 03 04 06
01 02 03 04 07
01 02 03 04 08
01 02 03 04 09
01 02 03 04 10
01 02 03 05 06
01 02 03 05 07
01 02 03 05 08
01 02 03 05 09
01 02 03 05 10
01 02 03 06 07
// ........... (252 combinations w/o repetitions)
05 07 08 09 10
06 07 08 09 10

Here is the function to perform combinations for two numbers using nCr,Tweak it for multiple numbers
/// <summary>
/// Performs a nCr Combination of the two numbers
/// </summary>
/// <param name="n">The Number</param>
/// <param name="r">The Range</param>
/// <returns></returns>
public static double Combination(double n, double r)
{
/*
* Formula for Combination: n! / (r! * (n - r)!)
*/
// n and r should be integral values
double rfloor = Math.Floor(r);
double nfloor = Math.Floor(n);
// Check for all invalid values of n and r.
if ((n < 1) || (r < 0) || (r > n) || (r != rfloor) || (n != nfloor))
{
throw new Exception("Invalid Input to Combination Function: Number must be greater than Range");
}
return Factorial(n) / (Factorial(r) * Factorial(n - r));
}
And
public static double Factorial(double n)
{
if (n < 0) { throw new Exception("Cannot take the factorial of a negative number"); }
double factorial = 1;
// 0! and 1! = 1
for (double i = 2; i < n + 1; i++)
{
factorial *= i;
}
return factorial;
}

Related

CRC-CCITT 16 bit Calculation in C#

I am trying to write one program for serial port communication, where i need to send data packet with CRC, I am writing this code in C# language.
Below is sample packet which receiver is expecting with CRC.
10 02 B1 F0 3F 32 08 00 00 10 03 B4 5C
Second Data Packet : 10 02 B1 F0 3F 32 07 00 00 10 03 4D EE
10 - DLE Code
02 - STX
B1 F0 3F 32 08 00 00 are Data
10 - DLE
03 -ETX
B4 - CRC Lower Bye
5C - CRC -Upper Bye
CCIT : (Fx) = x16 + x12 + x5 + 1
Operational Initial Value: FFFFH
I tried some online CRC calculators but so far no luck, can anybody guide how to calculate CRC for above data(B1 F0 3F 32 08 00 00)? may be can suggest online calculator which can give me above output(B4 5C).
Thanks for your advise!
I found something that works, but it seems a bit strange.
First I xor'ed the two samples
10 02 B1 F0 3F 32 08 00 00 10 03 B4 5C
10 02 B1 F0 3F 32 07 00 00 10 03 4D EE
--------------------------------------
00 00 00 00 00 00 0F 00 00 00 00 F9 B2
This eliminates the initial CRC and final xor values, and led to using a bit reflected 0x11021 CRC. It appears that the CRC is using 8 bytes of data, including the trailing 0x10.
Using the CRC calculator linked to below, pick any CRC16, then click on custom and set parameters to: input reflected checked, output reflected checked, poly = 0x1021. There's not enough information to determine the initial value and final xor value without a different sized message. Using 8 bytes of data, some example options are: initial value = 0x5B08, final xor value = 0x0000, or initial value = 0xffff, final xor value = 0xdde5, or initial value = 0x0000, final xor value = 0xa169.
When using reflected parameters, the calculator bit reverses the init value (0x5B08 is 0x17DA bit reversed). For code, the 3 combos are {0x17da,0x0000}, (0xffff,0xdde5}, {0x0000,0xa169}. Poly = 0x8408 and is right shifting.
Using xx's to indicate ingored data, I got
xx xx B1 F0 3F 32 08 00 00 10 xx B4 5C
xx xx B1 F0 3F 32 07 00 00 10 xx 4D EE
Since the first two bytes are {10 02}, fixed values, they could be included, by changing the initial value. However, I wasn't able to include the ETX 03 value.
http://www.sunshine2k.de/coding/javascript/crc/crc_js.html
Second hit I've found on the web but I copied it's contents here for reference:
using System;
public enum InitialCrcValue { Zeros, NonZero1 = 0xffff, NonZero2 = 0x1D0F }
public class Crc16Ccitt {
const ushort poly = 4129;
ushort[] table = new ushort[256];
ushort initialValue = 0;
public ushort ComputeChecksum(byte[] bytes) {
ushort crc = this.initialValue;
for(int i = 0; i < bytes.Length; ++i) {
crc = (ushort)((crc << 8) ^ table[((crc >> 8) ^ (0xff & bytes[i]))]);
}
return crc;
}
public byte[] ComputeChecksumBytes(byte[] bytes) {
ushort crc = ComputeChecksum(bytes);
return BitConverter.GetBytes(crc);
}
public Crc16Ccitt(InitialCrcValue initialValue) {
this.initialValue = (ushort)initialValue;
ushort temp, a;
for(int i = 0; i < table.Length; ++i) {
temp = 0;
a = (ushort)(i << 8);
for(int j = 0; j < 8; ++j) {
if(((temp ^ a) & 0x8000) != 0) {
temp = (ushort)((temp << 1) ^ poly);
} else {
temp <<= 1;
}
a <<= 1;
}
table[i] = temp;
}
}
}
The original link: http://sanity-free.org/133/crc_16_ccitt_in_csharp.html

BinaryReader EndOfStreamException when BaseStream.Position < BaseStream.Length

While using a BinaryReader, how is it possible that I get an EndOfStreamException on ReadUInt16() when BaseStream.Position is equal to 20 and BaseStream.Length is equal to 174? I can't find anything in the docs to indicate how this can occur.
EndOfStreamException: Failed to read past end of stream.
System.IO.BinaryReader.FillBuffer (Int32 numBytes) (at /Users/builduser/buildslave/mono/build/mcs/class/corlib/System.IO/BinaryReader.cs:119)
System.IO.BinaryReader.ReadUInt16 () (at /Users/builduser/buildslave/mono/build/mcs/class/corlib/System.IO/BinaryReader.cs:513)
Chunk.SaveChunk () (at Assets/Scripts/Chunk.cs:293)
Here is the exact data I believe to be in the stream. This data was retrieved from the program Hex Editor Neo while Visual Studio was halted at a breakpoint on the line of the exception.
01 00 00 00 00 00 00 00 01 00 a0 00 00 00 00 00
ff ff 00 00 13 00 00 00 00 10 0c 10 02 00 00 0c
00 0b 01 03 01 00 00 0c 03 04 02 0d 02 00 00 0e
03 01 01 0d 01 00 01 0e 03 03 01 09 01 00 01 0e
0c 0f 02 04 02 00 04 0c 03 06 01 01 01 00 04 0c
04 0c 02 0c 02 00 04 0e 04 0a 01 05 01 00 04 0e
09 07 02 03 02 00 0a 0c 03 06 02 01 02 00 0a 0e
03 06 01 01 01 00 0b 0c 00 05 02 03 02 00 0b 0e
00 05 01 03 01 00 0b 0e 09 01 01 01 01 00 0b 0e
0a 05 02 02 02 00 0c 0e 09 04 02 01 02 00 0e 0e
04 02 01 04 01 00 0e 0e 08 02 02 01 02 00
Edit: Code from opening the stream up until the exception.
public void SaveChunk()
{
lock (chunkDataLock)
{
FileStream readStream = File.Open("GameData/chunkdata.bin", FileMode.Open, FileAccess.Read, FileShare.Write);
FileStream writeStream = File.Open("GameData/chunkdata.bin", FileMode.Open, FileAccess.Write, FileShare.Read);
using (BinaryReader reader = new BinaryReader(readStream))
using (BinaryWriter writer = new BinaryWriter(writeStream))
{
//reader.BaseStream.Length == 174 here
if (reader.BaseStream.Length == 0)
{
writer.Write((ushort)0);
writer.Flush();
writer.BaseStream.Position = 0;
reader.BaseStream.Position = 0;
}
// 0, 0, 0
int[] regionPos = GetRegionFromChunkPosition(chunkPosX, chunkPosY, chunkPosZ);
// numRegions = 1
ushort numRegions = reader.ReadUInt16();
writer.BaseStream.Position += 2;
for (int i = 0; i < numRegions; i++)
{
// 0, 0, 0
short regXPos = reader.ReadInt16(), regYPos = reader.ReadInt16(), regZPos = reader.ReadInt16();
// numChunksPosition = 8
long numChunksPosition = reader.BaseStream.Position;
// numChunks = 1
ushort numChunks = reader.ReadUInt16();
// regionLengthPosition = 10
long regionLengthPosition = reader.BaseStream.Position;
// regionLength = 160
uint regionLength = reader.ReadUInt32();
uint newRegionLength = 0;
writer.BaseStream.Position += 12;
// At this point reader and writer both have BaseStream.Position of 14
// True
if (regXPos == regionPos[0] && regYPos == regionPos[1] && regZPos == regionPos[2])
{
bool chunkFound = false;
for (ushort j = 0; j < numChunks; j++)
{
// 0, -1, 0
short xPos = reader.ReadInt16(), yPos = reader.ReadInt16(), zPos = reader.ReadInt16();
writer.BaseStream.Position += 6;
// Exception occurs on this line.
// at this point, reader.BaseStream.Position = 20
// and reader.BaseStream.Length = 174
ushort numVoxelGroups = reader.ReadUInt16();
...
}
...
}
...
}
...
}
}
}

Calculating the PPP Frame Check Sequence

I'm attempting to generate a valid PPP Frame Check Sequence (FCS) using C#. The code I have implemented is based off of this answer.
public static class Crc16
{
const ushort polynomial = 0x8408;
static readonly ushort[] fcstab = new ushort[256];
// This is the fcstab from RFC1662
// https://www.rfc-editor.org/rfc/rfc1662#ref-7
//static readonly ushort[] fcstab = new ushort[] {
// 0x0000, 0x1189, 0x2312, 0x329b, 0x4624, 0x57ad, 0x6536, 0x74bf,
// 0x8c48, 0x9dc1, 0xaf5a, 0xbed3, 0xca6c, 0xdbe5, 0xe97e, 0xf8f7,
// 0x1081, 0x0108, 0x3393, 0x221a, 0x56a5, 0x472c, 0x75b7, 0x643e,
// 0x9cc9, 0x8d40, 0xbfdb, 0xae52, 0xdaed, 0xcb64, 0xf9ff, 0xe876,
// 0x2102, 0x308b, 0x0210, 0x1399, 0x6726, 0x76af, 0x4434, 0x55bd,
// 0xad4a, 0xbcc3, 0x8e58, 0x9fd1, 0xeb6e, 0xfae7, 0xc87c, 0xd9f5,
// 0x3183, 0x200a, 0x1291, 0x0318, 0x77a7, 0x662e, 0x54b5, 0x453c,
// 0xbdcb, 0xac42, 0x9ed9, 0x8f50, 0xfbef, 0xea66, 0xd8fd, 0xc974,
// 0x4204, 0x538d, 0x6116, 0x709f, 0x0420, 0x15a9, 0x2732, 0x36bb,
// 0xce4c, 0xdfc5, 0xed5e, 0xfcd7, 0x8868, 0x99e1, 0xab7a, 0xbaf3,
// 0x5285, 0x430c, 0x7197, 0x601e, 0x14a1, 0x0528, 0x37b3, 0x263a,
// 0xdecd, 0xcf44, 0xfddf, 0xec56, 0x98e9, 0x8960, 0xbbfb, 0xaa72,
// 0x6306, 0x728f, 0x4014, 0x519d, 0x2522, 0x34ab, 0x0630, 0x17b9,
// 0xef4e, 0xfec7, 0xcc5c, 0xddd5, 0xa96a, 0xb8e3, 0x8a78, 0x9bf1,
// 0x7387, 0x620e, 0x5095, 0x411c, 0x35a3, 0x242a, 0x16b1, 0x0738,
// 0xffcf, 0xee46, 0xdcdd, 0xcd54, 0xb9eb, 0xa862, 0x9af9, 0x8b70,
// 0x8408, 0x9581, 0xa71a, 0xb693, 0xc22c, 0xd3a5, 0xe13e, 0xf0b7,
// 0x0840, 0x19c9, 0x2b52, 0x3adb, 0x4e64, 0x5fed, 0x6d76, 0x7cff,
// 0x9489, 0x8500, 0xb79b, 0xa612, 0xd2ad, 0xc324, 0xf1bf, 0xe036,
// 0x18c1, 0x0948, 0x3bd3, 0x2a5a, 0x5ee5, 0x4f6c, 0x7df7, 0x6c7e,
// 0xa50a, 0xb483, 0x8618, 0x9791, 0xe32e, 0xf2a7, 0xc03c, 0xd1b5,
// 0x2942, 0x38cb, 0x0a50, 0x1bd9, 0x6f66, 0x7eef, 0x4c74, 0x5dfd,
// 0xb58b, 0xa402, 0x9699, 0x8710, 0xf3af, 0xe226, 0xd0bd, 0xc134,
// 0x39c3, 0x284a, 0x1ad1, 0x0b58, 0x7fe7, 0x6e6e, 0x5cf5, 0x4d7c,
// 0xc60c, 0xd785, 0xe51e, 0xf497, 0x8028, 0x91a1, 0xa33a, 0xb2b3,
// 0x4a44, 0x5bcd, 0x6956, 0x78df, 0x0c60, 0x1de9, 0x2f72, 0x3efb,
// 0xd68d, 0xc704, 0xf59f, 0xe416, 0x90a9, 0x8120, 0xb3bb, 0xa232,
// 0x5ac5, 0x4b4c, 0x79d7, 0x685e, 0x1ce1, 0x0d68, 0x3ff3, 0x2e7a,
// 0xe70e, 0xf687, 0xc41c, 0xd595, 0xa12a, 0xb0a3, 0x8238, 0x93b1,
// 0x6b46, 0x7acf, 0x4854, 0x59dd, 0x2d62, 0x3ceb, 0x0e70, 0x1ff9,
// 0xf78f, 0xe606, 0xd49d, 0xc514, 0xb1ab, 0xa022, 0x92b9, 0x8330,
// 0x7bc7, 0x6a4e, 0x58d5, 0x495c, 0x3de3, 0x2c6a, 0x1ef1, 0x0f78
// };
static Crc16()
{
ushort value;
ushort temp;
for (ushort i = 0; i < fcstab.Length; ++i)
{
value = 0;
temp = i;
for (byte j = 0; j < 8; ++j)
{
if (((value ^ temp) & 0x0001) != 0)
{
value = (ushort)((value >> 1) ^ polynomial);
}
else
{
value >>= 1;
}
temp >>= 1;
}
fcstab[i] = value;
}
}
/// <summary>Method that computes the checksum.</summary>
/// <param name="buff">The input <see cref="byte[]"/> to calculate the checksum off of.</param>
/// <example>
/// byte[] fcs = Crc16.ComputeChecksumBytes(buff)
/// </example>
/// <returns></returns>
public static byte[] ComputeChecksumBytes(byte[] buff)
{
ushort fcs = 0xFFFF;
for (int i = 0; i < buff.Length; i++)
{
byte index = (byte)((fcs ^ buff[i]) & 0xff);
fcs = (ushort)((fcs >> 8) ^ fcstab[index]);
}
fcs ^= 0xFFFF;
var lsb = (fcs >> 8) & 0xff;
var msb = fcs & 0xff;
return new byte[] { (byte)msb, (byte)lsb };
}
}
The good part is that the FCS table (fcstab[]) that gets generated is the same table seen in RFC 1662 thus confirming that the code in the constructor is correct.
The problem seems to be with the ComputeChecksumBytes() method.
I have an input PPP Packet of 7E FF 03 C0 21 01 00 00 0E 02 06 00 00 00 00 07 02 08 02 DD 31 7E.
I know from this link that the "FCS is calculated over the entire PPP packet, not including the start and stop flags (7E)." This leaves me with FF 03 C0 21 01 00 00 0E 02 06 00 00 00 00 07 02 08 02 DD 31.
I also know from that link that the FCS octets (DD 31) are to be "made equal to zero". This leaves me with FF 03 C0 21 01 00 00 0E 02 06 00 00 00 00 07 02 08 02 00 00.
When I call Crc16.ComputeChecksumBytes with that input byte array, my actual calculated FCS ends up being C0 0E.
Everything I'm doing seems to be correct but I still cannot figure out why I'm not getting the DD 31 that was calculated in the original packet.
Any help would be greatly appreciated!
Just do it without the two 0's at the end.

Read string of numbers into a grid/matrix [closed]

Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 8 years ago.
Improve this question
Can anyone tell me how can I read this grid into arrays like a[i][j] ? I searched on google but I can't seem to find anything useful.Thank you very much for helping!
static void Main(string[] args)
{
String grid = "08 02 22 97 38 15 00 40 00 75 04 05 07 78 52 12 50 77 91 08" +
"49 49 99 40 17 81 18 57 60 87 17 40 98 43 69 48 04 56 62 00" +
"81 49 31 73 55 79 14 29 93 71 40 67 53 88 30 03 49 13 36 65" +
"52 70 95 23 04 60 11 42 69 24 68 56 01 32 56 71 37 02 36 91" +
"22 31 16 71 51 67 63 89 41 92 36 54 22 40 40 28 66 33 13 80" +
"24 47 32 60 99 03 45 02 44 75 33 53 78 36 84 20 35 17 12 50" +
"32 98 81 28 64 23 67 10 26 38 40 67 59 54 70 66 18 38 64 70" +
"67 26 20 68 02 62 12 20 95 63 94 39 63 08 40 91 66 49 94 21" +
"24 55 58 05 66 73 99 26 97 17 78 78 96 83 14 88 34 89 63 72" +
"21 36 23 09 75 00 76 44 20 45 35 14 00 61 33 97 34 31 33 95" +
"78 17 53 28 22 75 31 67 15 94 03 80 04 62 16 14 09 53 56 92" +
"16 39 05 42 96 35 31 47 55 58 88 24 00 17 54 24 36 29 85 57" +
"86 56 00 48 35 71 89 07 05 44 44 37 44 60 21 58 51 54 17 58" +
"19 80 81 68 05 94 47 69 28 73 92 13 86 52 17 77 04 89 55 40" +
"04 52 08 83 97 35 99 16 07 97 57 32 16 26 26 79 33 27 98 66" +
"88 36 68 87 57 62 20 72 03 46 33 67 46 55 12 32 63 93 53 69" +
"04 42 16 73 38 25 39 11 24 94 72 18 08 46 29 32 40 62 76 36" +
"20 69 36 41 72 30 23 88 34 62 99 69 82 67 59 85 74 04 36 16" +
"20 73 35 29 78 31 90 01 74 31 49 71 48 86 81 16 23 57 05 54" +
"01 70 54 71 83 51 54 69 16 92 33 48 61 43 52 01 89 19 67 48";
int[] a = new int[20];
for(int i=0;i<20;i++)
for (int j = 1; j < 20; j++)
{
}
}
As suggested in the comments you can simply separate your numbers and use split string. for example:
private static void Main(string[] args)
{
String grid = "08,02,22,97,38,15,00,40,00,75,04,05,07,78,52,12,50,77,91,08," +
"49,49,99,40,17,81,18,57,60,87,17,40,98,43,69,48,04,56,62,00," +
"81,49,31,73,55,79,14,29,93,71,40,67,53,88,30,03,49,13,36,65," +
"52,70,95,23,04,60,11,42,69,24,68,56,01,32,56,71,37,02,36,91," +
"22,31,16,71,51,67,63,89,41,92,36,54,22,40,40,28,66,33,13,80," +
"24,47,32,60,99,03,45,02,44,75,33,53,78,36,84,20,35,17,12,50," +
"32,98,81,28,64,23,67,10,26,38,40,67,59,54,70,66,18,38,64,70," +
"67,26,20,68,02,62,12,20,95,63,94,39,63,08,40,91,66,49,94,21," +
"24,55,58,05,66,73,99,26,97,17,78,78,96,83,14,88,34,89,63,72," +
"21,36,23,09,75,00,76,44,20,45,35,14,00,61,33,97,34,31,33,95," +
"78,17,53,28,22,75,31,67,15,94,03,80,04,62,16,14,09,53,56,92," +
"16,39,05,42,96,35,31,47,55,58,88,24,00,17,54,24,36,29,85,57," +
"86,56,00,48,35,71,89,07,05,44,44,37,44,60,21,58,51,54,17,58," +
"19,80,81,68,05,94,47,69,28,73,92,13,86,52,17,77,04,89,55,40," +
"04,52,08,83,97,35,99,16,07,97,57,32,16,26,26,79,33,27,98,66," +
"88,36,68,87,57,62,20,72,03,46,33,67,46,55,12,32,63,93,53,69," +
"04,42,16,73,38,25,39,11,24,94,72,18,08,46,29,32,40,62,76,36," +
"20,69,36,41,72,30,23,88,34,62,99,69,82,67,59,85,74,04,36,16," +
"20,73,35,29,78,31,90,01,74,31,49,71,48,86,81,16,23,57,05,54," +
"01,70,54,71,83,51,54,69,16,92,33,48,61,43,52,01,89,19,67,48";
var splitstring = grid.Split(',');
var a = new int[20,20];
const int rowCount = 19; //counts 0 as 1
var rowIndex = 0;
var colIndex = 0;
foreach (var s in splitstring)
{
if (rowIndex > rowCount)
{
rowIndex = 0;
colIndex++;
}
a[colIndex, rowIndex] = Int32.Parse(s);
rowIndex++;
}
}
Note the Int32.Parse(s) will throw an exception if the parse fails. You can instead use an Int32.TryParse and use the out value for your result. Depends on what you want to do.
Consider add a space to the end of each "line" such as the following:
String grid = "08 02 .. 91 08 " +
"01 70 .. 67 48 ";
// ^-- add space here
This will allow the string to be converted trivially into a 1D array of strings with string.Split.
string grid = "08 02 .. 91 08"; // every number is space-separated now
string[] gridArray = grid.Split(" "); // -> ["08", "02", .. "91", "08"]
(Even without ensuring the extra spaces, a 1D array can be achieved using a Regular Expression split: var gridArray = Regex.Split(grid, "(?:\s|(?<=\d{2})(?=\d{2}))"), but I recommend "normalizing" the input string literals if possible.)
And each index in the resulting 1D array can be accessed as so, where columns represents the number of columns of the super-imposed matrix, or the "width" of each row.
int columns = 20;
int gridIndex = j * columns + i; // where j is a *row* and i is a *column*
// for a column-major matrix
string numStr = gridArray[gridIndex]; // and value at the [column,row]
Then it's just a matter of converting numStr to an integer and assigning it to the appropriate array index.
If every number is separated by a space such that ever number NN is in form "NN " it also takes up 3 characters. In this case the intermediate Split can be skipped, using the same idea of indexing into the source as a 1D sequence.
int gridNumOffset = (j * columns + i) * 3;
string numStr = grid.Substring(gridNumOffset, 2);
(Finding the substring offset even when there is no space at the end-of-line can be done using a little bit more math, which is a good exercise and the formula just becomes (j * columns + i) * 3 + f(i), where f(i) applies the appropriate offset.)
Another more mundane approach, assuming that the original string cannot be modified to include an end-of-line space/character, is to read in each line as N characters, deal with it, and move on. The concepts from above can be applied:
int rowWidth = (columns * 3) - 1; // -1 assuming no line-end space
for(int j = 0; j < rows; j++) { // j is *rows*, for column-major matrix
string rowStr = str.Substring(j * rowWidth, rowWidth);
string[] row = rowStr.Split(" "); // 1D array just for this row
for (int i = 0; i < columns; i++) {
string numStr = row[i];
// Convert and put value into the correct matrix position
}
}

How to convert byte[] to that text format?

I can say I don't know what I'm asking for help,because I don't know the format,but I've got a picture.
I have a byte[] array ,how do I convert it to that format below(in right)?
alt text http://img512.imageshack.us/img512/3548/48667724.jpg
Its not plain ascii.
It sounds like you'd like to take an array of bytes, and convert it to text (replacing characters outside of a certain range with "."s)
static public string ConvertFromBytes(byte[] input)
{
StringBuilder output = new StringBuilder(input.Length);
foreach (byte b in input)
{
// Printable chars are from 0x20 (space) to 0x7E (~)
if (b >= 0x20 && b <= 0x7E)
{
output.Append((char)b);
}
else
{
// This isn't a text char, so use a placehold char instead
output.Append(".");
}
}
return output.ToString();
}
or as a LINQy extension method (inside a static extension class):
static public string ToPrintableString(this byte[] bytes)
{
return Encoding.ASCII.GetString
(
bytes.Select(x => x < 0x20 || x > 0x7E ? (byte)'.' : x)
.ToArray()
);
}
(You could call that like string printable = byteArray.ToPrintableString();)
Use b.ToString("x2") to format a byte value into a two character hexadecimal string.
For the ASCII display, check if the value corresponds to a regular printable character and convert it if it is:
if (b >= 32 && b <= 127) {
c = (char)b;
} else {
c = '.';
}
Or shorter:
c = b >= 32 && b <= 127 ? (char)b : '.';
To do it on an array:
StringBuilder builder = new StringBuilder();
foreach (b in theArray) {
builder.Append(b >= 32 && b <= 127 ? (char)b : '.');
}
string result = builder.ToString();
This could be any number of encodings... try this test test script to see which of them print out:
Bl8s
Here is the script:
byte[] b = new byte[] {0x42, 0x6C, 0x38, 0x73 };
foreach (EncodingInfo ei in Encoding.GetEncodings())
{
Console.WriteLine("{0} - {1}", ei.GetEncoding().GetString(b), ei.Name);
}
[edit 2018:] Re-wrote the function from scratch to make the code much more efficient and fix some other problems. You can now also optionally specify a starting offset and number of bytes (starting from there) to display.
If you want the whole memory display, including the offset number, and left and right displays, you can do it like this: (32-byte width)
/// <summary> Returns a String where the specified bytes are formatted in a
/// 3-section debugger-style aligned memory display, 32-bytes per line </summary>
public static unsafe String MemoryDisplay(byte[] mem, int i_start = 0, int c = -1)
{
if (mem == null)
throw new ArgumentNullException();
if (i_start < 0)
throw new IndexOutOfRangeException();
if (c == -1)
c = mem.Length - i_start;
else if (c < 0)
throw new ArgumentException();
if (c == 0)
return String.Empty;
char* pch = stackalloc Char[32]; // for building right side at the same time
var sb = new StringBuilder((c / 32 + 1) * 140); // exact pre-allocation
c += i_start;
for (int i = i_start & ~0x1F; i < c;)
{
sb.Append(i.ToString("x8"));
sb.Append(' ');
do
{
if (i < i_start || i >= c) // non-requested area, or past the end
{
sb.Append(" ");
pch[i & 0x1F] = ' ';
}
else
{
var b = mem[i];
sb.Append(b.ToString("x2") + " ");
pch[i & 0x1F] = non_monospace(b) ? '.' : (Char)b;
}
}
while ((++i & 0x1F) != 0);
sb.Append(' ');
sb.AppendLine(new String(pch, 0, 32));
}
return sb.ToString();
}
The code uses the following helpers to determine which characters should be shown as 'dots' in right-hand part.
static readonly ulong[] _nmb =
{
0x00000000ffffe7ffUL,
0x8000000000000000UL,
0x00002000ffffffffUL,
0x0000000000000000UL,
};
static bool non_monospace(byte b) => (_nmb[b >> 6] & 1UL << b) != 0;
Output of the above function looks like this (character width is 138 columns, scroll to the right to see the "human-readable" part):
00000000 47 49 46 38 39 61 0f 00 0f 00 91 ff 00 00 00 00 c0 c0 c0 ff ff 00 00 00 00 21 f9 04 01 00 00 01 GIF89a...................!......
00000020 00 2c 00 00 00 00 0f 00 0f 00 00 02 2c 8c 0d 99 c7 91 02 e1 62 20 5a 79 ea bd 00 6d 89 69 8a f8 .,..........,.......b Zy...m.i..
00000040 08 e5 a7 99 e9 17 9d ac 24 a2 21 68 89 1e ac b4 d9 db 51 ab da c8 8c 1a 05 00 3b ........$.!h......Q.......;
Try: Encoding.Default.GetBytes
If that doesn't work, there are different types that you can specify (UTF-8, ASCII...)

Categories