C# - Formatting .txt Document Problem - c#

Here is the text file that I am loading in:
ORIGINAL FILE
10 BARE PCB
20 T C40
B C5, C45, C48
30 B C25
40 B C17, C18
50 B C15
60 T C20, C23,
B C6, C7, C8, C9, C10, C11, C12,
C31, C32, C33, C34, C35, C36,
C37, C38, C39
70 T C16, C21, C22, C24, C41, C42
B C3, C19, C43, C44, C47
80 T C13, C14
B C1, C2
90 B C26, C27, C28, C29, C30
100 T R65
110 T R35
120 T R34
130 T R33
140 T R21, R22, R29, R30
150 B R28, R31, R32, R37
160 T R17, R19, R26, R47, R50, R51,
R53, R57, R58, R59
B R18, R25, R42, R48, R49, R52,
R54, R55, R56, R60
170 T R23
B R10, R43
180 T R8, R9
190 T R13, R14, R15, R61, R62, R63,
R64
200 T R27, R38, R39, R40, R41
B R2, R3, R11, R44, R45, R46
210 B R1
220 T C4
230 T D1
240 T U1
250 B U10
270 B U6
280 B U5
290 B U4
300 T U2
310 B U7
320 B U8
330 T U9
340 B L2, L3
350 B L8, L9
360 B L1, L4, L5, L6, L7, L10
370 B J1, J2
380 B J3
390 B X1
400 T X2
410 B J4
420 B J5
422 B U3
2000 T TRACKING LABEL
423 ADHESIVE
424 ACCELERATOR
425 ADHESIVE
And this is what I have the file being formatted to:
FORMATTED FILE
0010 BARE PCB
0020 C40
0020A C5, C45, C48
0030A C25
0040A C17, C18
0050A C15
0060 C20, C23,
0060A C6, C7, C8, C9, C10, C11, C12,C31, C32, C33, C34, C35, C36,C37, C38, C39
0070 C16, C21, C22, C24, C41, C42
0070A C3, C19, C43, C44, C47
0080 C13, C14
0080A C1, C2
0090A C26, C27, C28, C29, C30
0100 R65
0110 R35
0120 R34
0130 R33
0140 R21, R22, R29, R30
0150A R28, R31, R32, R37
0160 R17, R19, R26, R47, R50, R51,R53, R57, R58, R59
0160A R18, R25, R42, R48, R49, R52,R54, R55, R56, R60
0170 R23
0170A R10, R43
0180 R8, R9
0190 R13, R14, R15, R61, R62, R63,R64
0200 R27, R38, R39, R40, R41
0200A R2, R3, R11, R44, R45, R46
0210A R1
0220 C4
0230 D1
0240 U1
0250A U10
0270A U6
0280A U5
0290A U4
0300 U2
0310A U7
0320A U8
0330 U9
0340A L2, L3
0350A L8, L9
0360A L1, L4, L5, L6, L7, L10
0370A J1, J2
0380A J3
0390A X1
0400 X2
0410A J4
0420A J5
0422A U3
2000 TRACKING LABEL
0423 ADHESIVE
0424 ACCELERATOR
0425 ADHESIVE
HOWEVER
If you look closely in the formatted file there is a few spots where there is no space after one of the commas (C12,C31 & C36,C37 & R51,R53 & R52,R54 & R63,R64). I would like there to be a space in between there..
CODE
private void openRefsFormatHelper()
{
try
{
// Resets the formatted refs text.
formattedRefsTextRichTextBox.ResetText();
// Reads the lines in the file to format.
var reader = File.OpenText(openRefs.FileName);
// Creates a list for the lines to be stored in.
var list = new List<string>();
// Adds each line in the file to the list.
while (true)
{
var line = reader.ReadLine();
if (line == null)
break;
list.Add(line);
}
// Handles all of the requirements for the reference text.
list = fourDigitRequirement(list);
list = concatRequirement(list);
list = startsWithBRequirement(list);
list = elementIsBRequirement(list);
list = removeTRequirement(list);
// Prints the formatted refs to the richtextbox.
foreach (var line in list)
formattedRefsTextRichTextBox.AppendText(line + "\n");
}
// Catches an exception if the file could not be formatted.
catch (Exception)
{
MessageBox.Show("There was a problem formatting the 'Refs File'.", "Refs File Format Error",
MessageBoxButtons.OK, MessageBoxIcon.Warning);
}
}
static List<string> elementIsBRequirement(List<string> list)
{
// Creates a new list to return with new format.
var result = new List<string>();
// Checks each line in the list.
foreach (var line in list)
{
// Splits each line into 'parts'
var parts = line.Split(' ');
// Checks if the second 'part' array is "B"
if (parts[1].Equals("B"))
{
// If it is "B", replace with "A" and add to the new list "result"
parts[0] += "A";
parts[1] = string.Empty;
result.Add(string.Join(" ", parts));
}
// Otherwise keep the line how it is.
else
result.Add(line);
}
// Returns the new list so it can be formatted further.
return result;
}
static List<string> startsWithBRequirement(List<string> list)
{
// Creates a new list to return with new format.
var result = new List<string>();
var i = 0;
// Checks if the line begins with "B"
foreach (var line in list)
{
// Splits each line into 'parts'
var parts = line.Split(' ');
// Checks if the first 'part' array is "B"
if (parts[0].Equals("B"))
{
// If it is "B", copy the previous line down and add "A" where "B" was at
// and add to the new list "result".
parts[0] = string.Empty;
result.Add(list[i - 1].Split(' ')[0] + "A" + string.Join(" ", parts));
}
// Otherwise keep the line how it is.
else
result.Add(line);
i++;
}
// Returns the new list so it can be formatted further.
return result;
}
static List<string> concatRequirement(List<string> list)
{
// Creates a new list to return with new format.
var result = new List<string>();
// Checks each line in the list.
foreach (var line in list)
{
// Splits each line into 'parts'
var parts = line.Split(' ');
int test;
// Concats everything together
if (int.TryParse(parts[0], out test) || parts[0].Equals("B"))
result.Add(line);
// Otherwise result - 1
else
result[result.Count - 1] += line;
}
// Returns the new list so it can be formatted further.
return result;
}
static List<string> removeTRequirement(List<string> list)
{
// Creates a new list to return with new format.
var result = new List<string>();
// Checks each line in the list.
foreach (var line in list)
{
// Splits each line into 'parts'
var parts = line.Split(' ');
// Checks if the second 'part' array is "T", if it is, remove "T"
if (parts[1].Equals("T"))
parts[1] = string.Empty;
// Add the new string to the result.
result.Add(string.Join(" ", parts).Replace(" ", " "));
}
// Returns the new list so it can be formatted further.
return result;
}
static List<string> fourDigitRequirement(List<string> list)
{
// Creates a new list to return with new format.
var result = new List<string>();
// Checks each line in the list.
foreach (var line in list)
{
// Splits each line into 'parts'
var parts = line.Split(' ');
int test;
// Checks if the array[0] (digits) is the proper length.
if (int.TryParse(parts[0], out test))
{
// If it is not a length of 4 digits, add "O" to the front until it is.
parts[0] = parts[0].PadLeft(4, '0');
// Add the new string to the result list.
result.Add(string.Join(" ", parts));
}
// Otherwise keep the line how it is.
else
result.Add(line);
}
// Returns the new list so it can be formatted further.
return result;
}
QUESTION:
- How do I get that space in there?

In concatRequirement, you can change:
result[result.Count - 1] += line;
to
result[result.Count - 1] += " " + line;

Without desk-checking the whole thing, I notice that the problem entries are where the value is at the end of the line.
Try appending a space to the line before you split it. Maybe.

Related

c# Spacing alignment on textfile

based on the image on below, I would like to have proper and consistent alignment and spacing like the right side of image.
Below is my source code for the first output, please help thanks
string line = null;
string printout = null;
StringBuilder sb = new StringBuilder(line);
if (File.Exists(filePath))
{
StreamReader file = null;
file = new StreamReader(filePath);
try
{
while ((line = file.ReadLine()) != null)
{
if (line == string.Empty)
{
continue;
}
if (!line.StartsWith("-"))
{
if ((line.Length <= 82) || line.Contains("MY01"))
{
printout = String.Format(line.Remove(0, 5).ToUpper());
var result = Regex.Replace(printout, "[\t ][ ]{10}", " ");
Console.WriteLine(result);
}
}
}
}
catch (IOException e)
{
Console.WriteLine("not valid", e.Message);
}
finally
{
if (file != null)
file.Close();
}
}
}
}
It's hard to see exactly what your original file format looks like, but here's one way to do it using string.PadRight to pad each column item to the correct width for that column.
If we pretend we have an input file like the one on the left, this method will format it to something similar to the one on the right.
This probably isn't the most efficient way to do this, but what it does is:
Read all the lines of the file, and for each line, split it on whitespace characters into an array of "items".
Finds the maximum width of each column and saves it in a dictionary with the column index as a key and the column width as a value
Writes each line back to the file after first setting the width of each line item to the correct width for that column
public static void FormatTextColumns(string filePath)
{
// Minimum number of spaces between two columns
var minColSpace = 3;
// Dictionary holds the index and max width of each column
var columnWidths = new Dictionary<int, int>();
// Read each file line into an array of items by splitting the line on whitespace
var lineItems = File
.ReadAllLines(filePath)
.Select(line => line.Split(new char[0], StringSplitOptions.RemoveEmptyEntries))
.ToList();
// Get the max column count
var maxColumns = lineItems.Max(x => x.Length);
// Save the max width of each column
for (var i = 0; i < maxColumns; i++)
{
foreach (var line in lineItems)
{
if (line.Length > i)
{
int existingValue;
columnWidths.TryGetValue(i, out existingValue);
columnWidths[i] = Math.Max(line[i].Length, existingValue);
}
}
}
// Save each line back to the file after padding each column item to the correct length
File.WriteAllLines(filePath, lineItems.Select(line =>
string.Concat(line.Select((item, index) =>
item.PadRight(columnWidths[index] + minColSpace)))));
}
Sample file input:
CISCO ZPRPflubadub 08-0729-01-MARch 08-0729-01 1 EA
CISCO ZPRP 08-0729-01-MAR 08-0729-0134 1 EA
CISCO ZPRP 08-0729-01-MAR 08-0729-01 1 EA
CISCO ZPRP 08-0729-01-MAR 08-0729-01 10 EA 4
CISCOar ZPRP 08-0729-01-MAR 08-0729-01 1 EA
CISCO ZPRP 08-0729-01-MARffe 08-0729-01 1 EA
Sample file output:
CISCO ZPRPflubadub 08-0729-01-MARch 08-0729-01 1 EA
CISCO ZPRP 08-0729-01-MAR 08-0729-0134 1 EA
CISCO ZPRP 08-0729-01-MAR 08-0729-01 1 EA
CISCO ZPRP 08-0729-01-MAR 08-0729-01 10 EA 4
CISCOar ZPRP 08-0729-01-MAR 08-0729-01 1 EA
CISCO ZPRP 08-0729-01-MARffe 08-0729-01 1 EA

Continuously reading serial-port buffer and parsing data to array in C#

Hello I'm trying to find best solution for continuously reading serial-port buffer and parsing data to array, continuously string form serial-port looks like this :
"...G 130 g\r\nG 130 g\r\nG 124 g\r\nG 124 g\r\nG 124
g\r\nG... "
The main idea is read for exaple last 3 data from serial-port broadcasting string, parse to double array [124.0; 124.0; 124.0] and comapre if equals.
Now I'm using this simple code but it is not enough fast :
_serialPortMainForm.DataReceived += new SerialDataReceivedEventHandler(Port_DataReceived);
.....
void Port_DataReceived(object sender, SerialDataReceivedEventArgs e)
{
byte[] data = new byte[_serialPortMainForm.BytesToRead];
_serialPortMainForm.Read(data, 0, data.Length);
string str = Encoding.ASCII.GetString(data);
RawSerialPortData += str;
if (RawSerialPortData.Length > Properties.Settings.Default.BufferSize) {
ProcessSerialPortData(RawSerialPortData);
RawSerialPortData = "";
}
}
And parsing data like this :
public void ProcessSerialPortData( string DataToProcess) {
int count = 0;
string PostFix = "";
DataToProcess = DataToProcess.Substring(DataToProcess.IndexOf('G') + 1);
DataToProcess = DataToProcess.Replace(" ", "");
DataToProcess = DataToProcess.Replace(Environment.NewLine, "|");
foreach (char c in DataToProcess) if (c == '|') count++;
ProcessedData = new double[count-1];
DataToProcess = DataToProcess.Replace("G", "");
if (DataToProcess.Contains("kg")) { PostFix = "kg"; DataToProcess = DataToProcess.Replace("kg", ""); }
if (DataToProcess.Contains("g")) { PostFix = "g"; DataToProcess = DataToProcess.Replace("g", ""); }
UnitsController(PostFix);
DataToProcess = DataToProcess.Replace(".", ",");
string[] SplitData = DataToProcess.Split('|');
int j = 0;
while (j < count - 1) {
Double.TryParse(SplitData[j], out ProcessedData[j]);
j++;
}
}
Kg are irelevant for this situation because grams are enough for this situation
Have somenone any idea or simple and best solution how do this better and faster ??
Making certain assumptions about the string in the buffer, one could extract all values using Regex.
Declare a global variable outside the method and compile the Regex for faster results:
Regex _regex = new Regex(#"\d+\s+\w+", RegexOptions.Compiled);
Then in your method, use the following to extract all the values:
var matches = _regex.Matches(DataToProcess)
.Cast<Match>()
.Select(m =>
{
var parts = m.Value.Split(' ');
return new { Value = parts[0], Unit = parts[1] };
});
//This is just for you to see the results in the console.
foreach (var value in matches)
{
Console.WriteLine(value);
}
Assuming DataToProcess contains this:
var DataToProcess = #"G130 g\r\nG 130 g\r\nG 124 g\r\nG 124 g\r\nG 124 g\r\n";
This would yield the following in the console:
{ Value = 130, Unit = g }
{ Value = 130, Unit = g }
{ Value = 124, Unit = g }
{ Value = 124, Unit = g }
{ Value = 124, Unit = g }
You can then use this enumeration to test for units, values, etc.
If you need the values as an array of doubles, just use:
var ProcessedData = matches.Select(m => Convert.ToDouble(m.Value)).ToArray();
Lastly, camelCase is usually preferred in C# for variable names and your code doesn't seem very thread-safe. Something to think about.

How do I define that value crosses 0 in C#?

There is list of int variable
data = List<int>
It contains few ints above the 0, few int's under 0 and so on. Data looks like:
-2962
-5787
-1671
-5667
-498
-4463
1399
3608
2173
I need to find the first item, when this function crosses the 0 from + to - (or from - to +) to get only first items above 0 or first items under 0 (depends on the sign of first item if it + or -).
So my code is:
var itemSign = 0;
foreach (var item in data)
{
if (itemSign == Sign(item))
{
result.Add(item);
Console.WriteLine(item);
}
itemSign = Sign(item);
}
But output is:
-2962
-5787
-1671
-5667
-498
-4463
1399
3608
2173
It seems like it doesn't work at all because I need to get these ints in these case:
-2962
-5787
-1671
-5667
-498
-4463
How do I define that value crosses 0 in C#?
You can use break as soon as sign change appears :
var itemSign = Sign(data.FirstOrDefault());
var result = new List<int>();
foreach (var item in data)
{
if (itemSign == Sign(item))
{
result.Add(item);
Console.WriteLine(item);
}
else
break;
}
There are two versions I can think of. Both use the List<int>.FindIndex() method.
class Program
{
static void Main(string[] args)
{
var list = new List<int>() {
-2962 ,
-5787 ,
-1671 ,
-5667 ,
-498 ,
-4463 ,
1399 ,
3608 ,
2173 ,
};
int index = list.FindIndex((x) => x>0)-1;
// index = 5
index=list.Zip(list.Skip(1), (x, y) => Math.Sign(x*y)).ToList().FindIndex((s) => s==-1);
// index = 5
}
}
The first one returns the index of the first non-negative number.
The second one multiplies consecutive numbers and if their product has a negative sign it means the numbers just changed sign.
Usint System.Linq (just for fun)
var input = new List<int> { -2962, -5787, -1671, -5667, -498, -4463, 1399, 3608, 2173 };
var cross = input
.Zip(input.Skip(1), (a, b) => new []{a,b})
.TakeWhile(t => (t.First() ^ t.Last()) >> 31 == 0)
.SelectMany(_ => _)
.Distinct();
Console.WriteLine(string.Join(",", cross)); //-2962,-5787,-1671,-5667,-498,-4463
If you want just the last element in the row, or first, then Aggregate could work:
var cross = input.Aggregate((a,b) => (a ^ b) >> 31 == 0 ? a : b); //1399
var cross = input.Aggregate((a,b) => (a ^ b) >> 31 == 0 ? b : a); //-4463
for each element in list, if >0 add to positive list, if <0 add to negative list. this is simple if else stuff....

What would be the best way to parse this process output (Tshark putput)

my Tshark out put give me table of IP's and i want to show them in decending order, this is my code who get the process output:
_process = new ProcessStartInfo(_tsharkPath);
_process.Arguments = (string.Format("-r {1}{0}{1} -q -z ip_hosts,tree ", _filePath, "\""));
_process.WindowStyle = ProcessWindowStyle.Hidden;
_process.UseShellExecute = false;
_process.RedirectStandardOutput = true;
_process.RedirectStandardError = true;
_process.CreateNoWindow = true;
_process.UseShellExecute = false;
_process.ErrorDialog = false;
Process tsharkProcess = Process.Start(_process);
StreamReader reader = tsharkProcess.StandardOutput;
tsharkProcess.WaitForExit(10000);
List<string> list = new List<string>();
SortedDictionary<string, string> table = new SortedDictionary<string, string>();
while (!reader.EndOfStream)
{
string read = reader.ReadLine();
list.Add(read);
}
i am received the table inside my list
this is my table and i only want to values IP and precent:
===================================================================
IP Addresses value rate percent
-------------------------------------------------------------------
IP Addresses 31584 0.322127
159.0.89.20 6002 0.061215 19.00%
192.168.0.100 31288 0.319108 99.06%
60.240.244.115 16 0.000163 0.05%
204.83.232.29 2698 0.027517 8.54%
177.16.241.40 2499 0.025487 7.91%
90.231.37.56 848 0.008649 2.68%
117.204.2.26 172 0.001754 0.54%
69.247.52.146 1909 0.019470 6.04%
188.126.75.143 75 0.000765 0.24%
173.212.107.113 8 0.000082 0.03%
114.47.15.111 26 0.000265 0.08%
219.192.199.2 2 0.000020 0.01%
59.97.56.175 986 0.010056 3.12%
50.53.9.249 2376 0.024233 7.52%
76.18.194.203 123 0.001254 0.39%
41.233.19.39 428 0.004365 1.36%
203.84.186.210 659 0.006721 2.09%
58.40.202.85 2 0.000020 0.01%
88.160.36.13 2 0.000020 0.01%
117.199.195.22 432 0.004406 1.37%
112.202.141.240 443 0.004518 1.40%
46.240.116.228 7 0.000071 0.02%
41.46.174.7 1259 0.012841 3.99%
112.135.159.14 1 0.000010 0.00%
201.215.244.25 66 0.000673 0.21%
223.67.159.170 2 0.000020 0.01%
67.204.32.252 626 0.006385 1.98%
2001:0:9d38:6ab8:aa:a1a:b048:3f7d 286 0.002917 0.91%
2001:0:9d38:953c:2481:166c:90bb:db19 50 0.000510 0.16%
2607:5300:10:101::1:209 8 0.000082 0.03%
83.248.5.18 6 0.000061 0.02%
98.221.248.250 80 0.000816 0.25%
83.100.249.165 60 0.000612 0.19%
89.254.132.166 14 0.000143 0.04%
119.50.230.109 40 0.000408 0.13%
190.193.144.107
33 0.000337 0.10%
Regular Expressions will make your life a lot easier here. First, define the basic structure of data you want to capture:
private struct TSharkOutput
{
public IPAddress ip;
public uint value;
public decimal rate;
public decimal percent;
};
You can add/remove portions and change the data types as need.
Next comes the regular expression to handle this. I leave the brunt of the IPAddress matching to the internal classes.
var regTshark = new Regex(#"^\s*(?<ip>[\d.:]+)\s+(?<val>\d+)\s+(?<rate>\d+\.\d+)\s+(?<perc>\d+\.\d+)%", RegexOptions.Compiled);
Now for your parsing function, I'd do something like this;
_process = new ProcessStartInfo(_tsharkPath);
_process.Arguments = (string.Format("-r {1}{0}{1} -q -z ip_hosts,tree ", _filePath, "\""));
_process.WindowStyle = ProcessWindowStyle.Hidden;
_process.UseShellExecute = false;
_process.RedirectStandardOutput = true;
_process.RedirectStandardError = true;
_process.CreateNoWindow = true;
_process.UseShellExecute = false;
_process.ErrorDialog = false;
var tsharkProcess = Process.Start(_process);
var reader = tsharkProcess.StandardOutput;
tsharkProcess.WaitForExit(10000);
var list = new List<TSharkOutput>();
var regTshark = new Regex(#"^\s*(?<ip>[\d.:]+)\s+(?<val>\d+)\s+(?<rate>\d+\.\d+)\s+(?<perc>\d+\.\d+)%", RegexOptions.Compiled);
Match current;
string line = "";
while (!reader.EndOfStream)
{
line = reader.ReadLine();
if ((current = regTshark.Match(line)).Success)
{
var shark = new TSharkOutput()
{
value = uint.Parse(current.Groups["val"].Value),
rate = decimal.Parse(current.Groups["rate"].Value),
percent = decimal.Parse(current.Groups["perc"].Value)
};
if (IPAddress.TryParse(current.Groups["ip"].Value, out shark.ip))
list.Add(shark); // all good add to the list.
}
}
// sorted is an IEnumerable<TSharkOutput> which has been ordered by the percentage in descending order
var sorted = list.OrderByDescending(ts => ts.percent);
Please note, I'm not at home right now and so I haven't been able to try and compile the above code, but I'm fairly confident most of it should work. Let me know.
Cheers.

Convert string to tree representation with rules

I'm to do some simple RTF text parsing, I need to correct an iss. Given the following string:
{aaaaaaa\}aaaa\{aaaaa{bbbbbbbb{ccccc\{cccc}bbb{eeeee}{{gggg}ffff}bbbbbb}aaaaa}
Where:
\ means ignore next character
{ means expand
} means collapse up to parent
At any point in the string the state might be affected by any previous character except for characters in closed tags. eg {gggg} won't affect ffff but aaaaaaa}aaa.. will affect bbbb, ccc, eee, ggg, fff and so on.
From this we can split the above to just the meaningful blocks
A1 = aaaaaaa\}aaaa\{aaaaa
B1 = bbbbbbbb
C = ccccc\{cccc
B2 = bbb
E = eeeee
G = gggg
F = ffff
B3 = bbbbbb
A2 = aaaaa
Yielding:
{A1{B1{C}B2{E}{{G}F}B3}A2}
To describe the dependency I used X > Y means Y depends on X (as in X may change the meaning of Y)
A1
A1 > B1
A1 > B1 > C
A1 > B1 > B2
A1 > B1 > B2 > E
A1 > B1 > B2 > G
A1 > B1 > B2 > F
A1 > B1 > B2 > B3
A1 > B1 > B2 > A2
A1 > A2
So if we then have a node that can have a value and a ordered list of sub values. Such that the value tree would look like this:
A1
- B1
- - C
- - B2
- - - E
- - - G
- - - F
- - - B3
- A2
Then to get the characters that affect any node, I can just step up through each parent recursively.
What I keep getting stuck on is trying to parse the string into my node class:
public class myNode
{
public myNode Parent;
public string Value;
public List<myNode> subNodes;
}
I read the string character by character, when I encounter a \ I increment by two. When I encounter a { I save the previous text section as the node value and step into the child, and when I encounter a } I step down.
But I keep messing up the logic, especially for G and A2. It's simple to do on paper but when I then try having to do the actual logic for step down I keep messing it up.
Is there a more straight forward way to make this structure? (or is there a better structure I should be using). I would think that there should be some library that allows conversions of strings to trees but I can't seem to find any.
Use a "state machine" approach, where the state is the current node, and an escape flag:
string rtf = #"{aaaaaaa\}aaaa\{aaaaa{bbbbbbbb{ccccc\{cccc}bbb{eeeee}{{gggg}ffff}bbbbbb}aaaaa}";
Node root = new Node { Parent = null, Value = "root", SubNodes = new List<Node>() };
Node node = root;
bool escape = false;
foreach (char c in rtf) {
if (escape) {
node.Value += c;
escape = false;
} else {
switch (c) {
case '{':
node = new Node { Parent = node, Value = String.Empty, SubNodes = new List<Node>() };
node.Parent.SubNodes.Add(node);
break;
case '}':
node = new Node { Parent = node.Parent.Parent, Value = String.Empty, SubNodes = new List<Node>() };
if (node.Parent != null) node.Parent.SubNodes.Add(node);
break;
case '\\':
escape = true;
break;
default:
node.Value += c;
break;
}
}
}
PrintNode(root, String.Empty);
The Node class (just renamed a little):
public class Node {
public Node Parent;
public string Value;
public List<Node> SubNodes;
}
For display:
private static void PrintNode(Node node, string level) {
if (node.Value.Length > 0) Console.WriteLine(level + node.Value);
foreach (Node n in node.SubNodes) {
PrintNode(n, level + " ");
}
}
Output:
root
aaaaaaa}aaaa{aaaaa
bbbbbbbb
ccccc{cccc
bbb
eeeee
gggg
ffff
bbbbbb
aaaaa
Note that the G node is not a child of the E node, but a child of a node with an empty value.
Then of course you also have to add some error handling.

Categories