Home > Net >  C# letting user type inputs in any order by adding specific keywords and designate them to their str
C# letting user type inputs in any order by adding specific keywords and designate them to their str

Time:07-05

I basically want the user to be able to type his name, surname and age in any order by including the "keyword" in front as example !name [his name], !surname [his surname]...

//My abstract idea:

//User input in one line, order doesn't matter:

!name jon !surname doe !age 23
!surname doe !name jon !age 23
!age 23 !name jon !surname doe
etc...

// Inputs get filtered out and put to the designated variables.
// 
string name = "jon";
string surname = "doe";
string age = "23"

I'm overall confused how I should even start building, I have basically thought about using an if-statement which includes a string.Contains and if the statement is true it takes the string out with string.Substring, it works for the first keyword but I'm running in circles how it should work for the second and third string ( I'm thinking about a loop ). I have posted an example, maybe you can follow my gibberish thought process..


using System;

namespace ConsoleApp1
{
    internal class Program
    {
        static void Main(string[] args)
        {
            string name = "";
            
            Console.Write("input: ");
            string input = Console.ReadLine();

            if (input.Contains("!name "))
            {
                name = input.Substring(6, input.Length - 6);
                
                
            }
            

        }
    }
}



I have already tried playing around with if statements, trim, replace, contains, substring,loops but still couldn't find a solution. Please consider that I haven't learned regex etc. yet, I'm still at the beginning thank you.

CodePudding user response:

here a simple solution without using regex

static string getValue(string key, string input){
    string first = input.split('!').FirtOrDefault(s=>s.StartsWith(key));
    if(string.IsNullOrEmpty(first)) return null;
    return first.Substring(key.Length).Trim();
}

usage example:

string age = getValue("age", input); //returns "23"

CodePudding user response:

This may be a little over-engineered but there wasn't a huge amount of info around the wider problem. Presumably the example you've given could be a bit more complex and therefore it might be more useful to create a class that could then be passed around. Here's something that might work:

public class Person
{
    private string[] InputData;
    public string Name { get; set; }
    public string Surname { get; set; }
    public int? Age { get; set; }

    public Person(string data, string delimiter)
    {
        InputData = data.Split(delimiter);
        var properties = this.GetType().GetProperties();

        foreach (var property in properties)
        {
            SetPropertyValue(property);
        }
    }

    private void SetPropertyValue(PropertyInfo propertyInfo)
    {
        var dataTag = propertyInfo.Name.ToLower();
        var stringValue = InputData.FirstOrDefault(x => x.StartsWith(dataTag))?.Remove(0, dataTag.Count()).Trim();
        var value = propertyInfo.PropertyType == typeof(string) ? stringValue : TypeDescriptor.GetConverter(propertyInfo.PropertyType).ConvertFromInvariantString(stringValue);
        propertyInfo.SetValue(this, value, null);
    }
}

You can call it like this:

var person = new Person(@"!surname doe !name jon !age 23", "!");

This uses the names of the properties in the class to create the data tags that you want to search for in your string. It then sets the value of the properties in the class if it finds one that it can convert from string to that property type.

If your input string started containing a JobType for example like "!surname doe !name jon !age 23 !jobtype accountant" you would just need to add a property on the Person class called "JobType" and it should work. Might need some tweaking for different types but works for the string / int that you have provided.

CodePudding user response:

This example expects the input to be correctly formatted and have each keyword included in the input. Modify as-needed for safety check to avoid KeyNotFoundException's.

// sample input
string input = "!surname doe !name jon !age 23";

// use a case insensitive dictionary to hold the parsed string keyword and value
var dic = new Dictionary<string, string>( StringComparer.OrdinalIgnoreCase );

// split the input by the exclamation point
// each part will be the keyword and the value as a single string
var options = StringSplitOptions.RemoveEmptyEntries | StringSplitOptions.TrimEntries;
string[] parts = input.Split( '!', options );

// break each part into the keyword substring and the value
foreach( string str in parts )
{
    // ex: surname doe
    int idx = str.IndexOf( ' ' );
    // add the keyword as the dictionary key and the value as the value
    dic.Add( str[..idx], str[  idx..] );
}

// create the variables and assign the values from the dictionary
string name = dic[nameof( name )];
string surname = dic[nameof( surname )];
string age = dic[nameof( age )];

CodePudding user response:

I suggest extracting model, i.e. Key and validation as Value:

//TODO: add keys and their validations here 
private static readonly Dictionary<string, Func<string, string>> s_Keys = 
  new(StringComparer.OrdinalIgnoreCase) {
    { "name",    null},
    { "surname", null},
    { "age",     text => int.TryParse(text, out int age) && age >= 0 && age <= 121 
                           ? "" 
                           : "invalid age"}
};

Then you can implement something like this (with a help of regular expressions):

using System.Text.RegularExpressions;

...

private static (string key, string value) ReadKeyAndValue() {
  while (true) {
    Console.WriteLine("Please, input data:");

    var match = Regex.Match(Console.ReadLine(), 
                            @"^\s*!(?<key>\p{L} )\s (?<value>.*)\s*$");

    if (!match.Success)
      Console.WriteLine("Invalid syntax. Put data in !Key Value format");
    else if (!s_Keys.TryGetValue(match.Groups["key"].Value, out var validation))
      Console.WriteLine($"Unknown Key !{match.Groups["key"].Value}");
    else {
      if (validation == null)
        return (match.Groups["key"].Value, match.Groups["value"].Value);

      string error = validation(match.Groups["value"].Value);

      if (string.IsNullOrWhiteSpace(error))
        return (match.Groups["key"].Value, match.Groups["value"].Value);
      else  
        Console.WriteLine(error);
    }
  }
}

usage:

string key;
string value;

// Something like key = "age" and value = "67"
(key, value) = ReadKeyAndValue();
  •  Tags:  
  • c#
  • Related