currently i can take ints and one string from a text box but i am trying to be able to take multiple strings and ints at the same time. the problem im having is that the inputs are of different lengths with different combinations of ints and strings.
private void button1_Click(object sender, EventArgs e)
{
string[] Lines = ProgramWindow.Text.Split('\n');
int NumberOfCommands = Lines.Length;
{
for (int i = 0; i <= NumberOfCommands - 1; i )
{
String[] Input = CommandLine.Text.ToLower().Split(' ', (char)StringSplitOptions.RemoveEmptyEntries);
String Command = Input[0];
int[] Parameters = Input.Length <= 1 ? new int[0] : Input[1].Split(',').Select(item => int.Parse(item)).ToArray();
int X = Parameters.Length >= 1 ? Parameters[0] : 0;
int Y = Parameters.Length >= 2 ? Parameters[1] : 0;
Console.WriteLine(Command, X, Y);
Commands(Command, X, Y);
Refresh();
}
}
Input variations :
string = int
string = string int
string int
string int int
CodePudding user response:
I can't bear the thought of doing this in C#, since I've only used F# for several years now. This snippet in F# can possibly be of help in order to come up with an elegant solution in C# too.
type Element = AString of string | AnInt of int | AnEquals
let parseElements (line: string) : Element list =
line.Split (' ', StringSplitOptions.RemoveEmptyEntries ||| StringSplitOptions.TrimEntries)
|> Array.toList
|> List.map (fun elementText ->
match Int32.TryParse elementText with
| true, n -> AnInt n
| false, _ -> if elementText = "=" then AnEquals else AString elementText
)
type Command =
| NameIsInt of name:string * value:int
| NameIsTagInt of name:string * tag:string * value:int
| TagInt of tag:string * value:int
| TagIntInt of tag:string * value1:int * value2:int
| UnknownElements of Element list
let parseCommandLines (text: string) : Command list =
text.Split ('\n', StringSplitOptions.RemoveEmptyEntries ||| StringSplitOptions.TrimEntries)
|> Array.toList
|> List.map (fun line ->
match parseElements line with
| [ AString name; AnEquals; AnInt value ] -> NameIsInt (name, value)
| [ AString name; AnEquals; AString tag; AnInt value ] -> NameIsTagInt (name, tag, value)
| [ AString tag; AnInt value ] -> TagInt (tag, value)
| [ AString tag; AnInt value1; AnInt value2 ] -> TagIntInt (tag, value1, value2)
| elements -> UnknownElements elements
)
let sample = """a = 1
b = x 2
c 3
d 4 5
"""
let result = parseCommandLines sample
result
|> List.iter (fun command -> Console.WriteLine $"command : {command}")
(* This is the output:
command : NameIsInt ("a", 1)
command : NameIsTagInt ("b", "x", 2)
command : TagInt ("c", 3)
command : TagIntInt ("d", 4, 5)
*)
CodePudding user response:
var command = lines[0];
var parameters = new List<object>();
// skipping index 0, since it's the command name.
for(var i = 1; i < lines.Length; i )
{
// May want to consider how to handle empty/null items
// you can grow this list to support other data types like decimal.
// pretty much all base data types will have the .tryparse method.
if (int.TryParse(lines[i], out var intVar))
parameters.Add(intVar);
else // else assume string
parameters.Add(lines[i]);
}
// do whatever you need to do
// `command` is the command
// `parameters` contains a valid list of all parameters
However, I'd argue you put a little more structure to this and move the commands out into their own classes. This will prevent the problem you'll run into as each command starts needing drastically different parameters.
Each command would contain it's logic for validating/executing the command.
ProcessCommand("test\n5\nsomething");
ProcessCommand("test\n5\n4\nsomething");
void ProcessCommand(string input)
{
// would move this to the constructor for the class, and even DI depending on your situation.
var commands = new List<ICommand>()
{
new ExampleCommand(),
new Example1Command()
};
string[] lines = input.Split('\n');
// No command, exit.
if (lines.Length == 0)
return;
var command = lines[0];
var parameters = new List<object>();
// skipping index 0, since it's the command name.
for(var i = 1; i < lines.Length; i )
{
// May want to consider how to handle empty/null items
// you can grow this list to support other data types like decimal.
// pretty much all base data types will have the .tryparse method.
if (int.TryParse(lines[i], out var intVar))
parameters.Add(intVar);
else // else assume string
parameters.Add(lines[i]);
}
foreach (var cmd in commands)
{
// ignore casing since it's being typed in.
if (cmd.CommandName.Equals(command, StringComparison.OrdinalIgnoreCase))
{
cmd.RunCommand(parameters);
break; // stop once we found a suitable command.
}
}
}
class ExampleCommand : ICommand
{
public string CommandName => "Test";
public void RunCommand(List<object> parameters)
{
Console.WriteLine("Example Command");
for(var i = 0; i < parameters.Count; i )
{
Console.WriteLine($"{i} - {parameters[i].GetType()} - {parameters[i]}");
}
}
}
class Example1Command : ICommand
{
public string CommandName => "Test1";
public void RunCommand(List<object> parameters)
{
throw new NotImplementedException();
}
}
interface ICommand
{
string CommandName { get; }
void RunCommand(List<object> parameters);
}
Sample output from the code above:
Example Command
0 - System.Int32 - 5
1 - System.String - something
Example Command
0 - System.Int32 - 5
1 - System.Int32 - 4
2 - System.String - something
