dynamic substring in c# - c#

I have a set of code in c# I want to store into the database what the user is entering in the textbox.
The user enters into the textbox like this
input namexyzpan9837663placeofbirthmumbailocationwadala
This is what user enters
(name: xyz pan: 9837663 place of birth: mumbai location: wadala)
Output into the database
xyz 9837663 mumbai wadala
OR
name xyzapan72placeofbirthgoalocationpanji
(> name: xyza pan: 72 place of birth: goa location: panji)
Output into the database
xyza 72 goa panji
name, age, location and placeofbirth are static but the value inside
them are dynamic
I know substring is helpfull but i don't know how to use it.

Use can use Split if the keywords are static :
string strMain = "namexyzpan9837663placeofbirthmumbailocationwadala";
var results = strMain.Split(new string[] { "name", "pan", "placeofbirth", "location" }, StringSplitOptions.RemoveEmptyEntries);
string name = results[0];
string pan = results[1];
string location = results[2];
You said you didn't know how to use Substring, well here it is working:
Note that the second parameter for this method is the length of the string to be taken and not the index at which to stop.
string strMain = "namexyzpan9837663placeofbirthmumbailocationwadala";
int indexOfName = strMain.IndexOf("name");
int indexOfPan = strMain.IndexOf("pan");
int indexOfBirth = strMain.IndexOf("placeofbirth");
int indexOflocation = strMain.IndexOf("location");
int effectiveIndexOfName = indexOfName + "name".Length;
int effectiveIndexOfPan = indexOfPan + "pan".Length;
int effectiveIndexOfBirth = indexOfBirth + "placeofbirth".Length;
int effectiveIndexOflocation = indexOflocation + "location".Length;
string name1 = strMain.Substring(effectiveIndexOfName, indexOfPan- effectiveIndexOfName);
string pan1 = strMain.Substring(effectiveIndexOfPan, indexOfBirth - effectiveIndexOfPan);
string birth1 = strMain.Substring(effectiveIndexOfBirth, indexOflocation - effectiveIndexOfBirth);
string location1 = strMain.Substring(effectiveIndexOflocation);
namenamepan9837663placeofbirthmumbailocationwadala works using the second method. But namepanpan9837663placeofbirthmumbailocationwadala is an interesting case that definitely needs a workaround.

Regex is designed for such case.
var input = #"namexyzpan9837663placeofbirthmumbailocationwadala";
var match = Regex.Match(input, #"^\s*"
+ #"name\s*(?<name>\w+?)\s*"
+ #"pan\s*(?<pan>\w+?)\s*"
+ #"placeofbirth\s*(?<placeOfBirth>\w+?)\s*"
+ #"location\s*(?<location>\w+)\s*" + #"$");
var name = match.Groups["name"].Value;
var pan = match.Groups["pan"].Value;
var placeOfBirth = match.Groups["placeOfBirth"].Value;
var location = match.Groups["location"].Value;

Related

String Manipulation and splitting string

string url = "test:app:https://test#hotmail.co.uk:Test
I need to split this up to display as follows
string first = "app";
string second = "https://test#hotmail.co.uk:Test";
i have tried the following but falls over on the last colon.
string remove= "";
remove= url.Replace("test:", "");
string first= remove.Substring(remove.LastIndexOf(':') + 1);
string second= remove.Substring(0, remove.IndexOf(':'));
Doing this i get
first = "app";
second = "Test";
When i need
first = "app";
second = "https://test#hotmail.co.uk:Test";
Your use of LastIndexOf is just a bit wonky.
string url = "test:app:https://test#hotmail.co.uk:Test";
string remove = url.Replace("test:", "");
string first = remove.Substring(0, remove.IndexOf(":"));
string second = remove.Substring(remove.IndexOf(first) + first.Length + 1);
First grab the app, and we can use the location of app to derive the rest of the string. Because the last index of : would be the one in :Test. We don't want the last index of :. Instead we just want whatever comes after app.
As everything is prefixed with test: you can use a starting position after that and then split after the first occurrance of the : character.
const int IndexOfPrefix = 5; // start position after "test:"
string url = "test:app:https://test#hotmail.co.uk:Test";
var indexOfApp = url.IndexOf(':', IndexOfPrefix);
var part1 = url.Substring(IndexOfPrefix, indexOfApp - IndexOfPrefix);
var part2 = url.Substring(indexOfApp + 1);
Console.WriteLine(part1);
Console.WriteLine(part2);
Something like this should do the trick:
public void ManipulateStrings()
{
string url = "test:app:https://test#hotmail.co.uk:Test";
url = url.Replace("test:", "");
string first = url.Substring(0, url.IndexOf(':'));
string second = url.Substring(url.IndexOf(':') + 1);
}
This basically removed test: from your string, then assigns first and second their values without creating string remove = "" for no reason.
You can use Split(Char[], Int32) to get the desired number of elements (3 : the first unwanted part, the first expected part and the remaining) along with Skip() to remove the unwanted one :
string url = "test:app:https://test#hotmail.co.uk:Test";
var splitted = url.Split(new [] { ':' }, 3).Skip(1).ToArray();
var first = splitted[0];
var second = splitted[1];
Console.WriteLine(first);
Console.WriteLine(second);
This outputs
app
https://test#hotmail.co.uk:Test
Another way to do that is using regular expressions :
The pattern :(?<first>.*?):(?<second>.*) will :
: search for the characters :
(?<first>.*?) creates a group named first that will match any number of any character (lazy)
: search for the characters :
(?<second>.*) creates a group named second that will match any number of any character (greedy)
In example :
string url = "test:app:https://test#hotmail.co.uk:Test";
var pattern = ":(?<first>.*?):(?<second>.*)";
var regex = new Regex(pattern); // using System.Text.RegularExpressions;
Match match = regex.Match(url);
if (match.Success)
{
var first = match.Groups["first"].Value;
var second = match.Groups["second"].Value;
Console.WriteLine(first);
Console.WriteLine(second);
}
This outputs
app
https://test#hotmail.co.uk:Test
you need to change the variable with name "first" to "second" and to change the variable with name "second" to "first"
This is your code:
string url = "test:app:https://test#hotmail.co.uk:Test";
string remove = "";
remove = url.Replace("test:", "");
string second = remove.Substring(0, remove.IndexOf(':'));
string first = remove.Substring(remove.IndexOf(":") + 1);
and this is the correct code:
string url = "test:app:https://test#hotmail.co.uk:Test";
string remove = "";
remove = url.Replace("test:", "");
string first = remove.Substring(0, remove.IndexOf(':'));
string second = remove.Substring(remove.IndexOf(":") + 1);

Number format in Word document

I have some fields in an Word document with instructional text, for example like this one:
{ MERGEFIELD MyField1 \# "000" }
I'm reading those fields using OpenXML SDK, as shown here, and replacing them with some data.
I'm applying the number format that is specified in the field to my data, like this:
string fieldFormat = "000";
int data = 1234;
string fieldValue = data.ToString(fieldFormat);
In most cases this works great, but now I got a document that has "xxx" as a number format and when using the above I get "xxx" for fieldValue.
string fieldFormat = "xxx";
int data = 1234;
string fieldValue = data.ToString(fieldFormat); // Problem!
I saw that .NET doesn't support this in Custom numeric format, but Word supports this in a way that it removes any digits that come after the "x" symbols place.
So for the above, it should result in "234". How can I do that in C#?
EDIT, added some additional examples:
int number = 1158;
string format1 = "x";
string format2 = "xx";
string format3 = "x#";
string format4 = "x,###";
string format5 = "x,xxx";
string format6 = "x##.00";
string format7 = "xxxxxxx.00";
Console.WriteLine("(number + format1) should result to: 8");
Console.WriteLine("(number + format2) should result to: 58");
Console.WriteLine("(number + format3) should result to: 58");
Console.WriteLine("(number + format4) should result to: 1,158");
Console.WriteLine("(number + format5) should result to: 1,158");
Console.WriteLine("(number + format6) should result to: 158.00");
Console.WriteLine("(number + format7) should result to: 1158.00");

I want to read text and replace parts that are surrounded by signals

I have a chunk of text for example
string OriginalText = "Hello my name is <!name!> and I am <!age!> years old";
I'm struggling to write a function that I can enter this text into and it will return the same string except with the values surrounded by the Tags "<!" and "!>" to be replace with actual values. I have some code written but don't know how to progress any further.
if(OriginalText.Contains("<!")) //Checks if Change is necessary
{
string[] Total = OriginalText.Split(
new Char[] { '<', '!' },
StringSplitOptions.RemoveEmptyEntries);
if(Total[1].Contains("!>")) //Checks if closing tag exists
{
string ExtTag = Total[1].Split(
new Char[] { '<', '!' },
StringSplitOptions.RemoveEmptyEntries)[0];
ExtData.Add(Total[1].Split(
new Char[] { '<', '!' },
StringSplitOptions.RemoveEmptyEntries)[0]);
return Total[1];
}
}
The desired output would be
"Hello my name is James and I am 21 years old"
I am currently getting this text from a database and so this functions purpose would be to read that text and input the correct information.
Edit: Figured out how to do it so I'm going to include it below however I'm writing this in a program called mattersphere so there will reference to functions that aren't standard c#, I will put comments next to them explain what they do.
private string ConvertCodeToExtData(string OriginalText) //Accepts text with the identifying symbols as placeholders
{
string[] OriginalWords = OriginalText.Split(' '); //Creates array of individual words
string ConvertedText = string.Empty;
int Index = 0;
foreach(string OriginalWord in OriginalWords) //Go through each word in the array
{
if(OriginalWord.Substring(0,1).Equals("<") && OriginalWord.Substring(OriginalWord.Length-1 ,1).Equals(">")) //Checks if Change is necessary
{
string[] ExtDataCodeAndSymbols = OriginalWord.Substring(1, OriginalWord.Length-2).Split('.'); //Decided to create 4 different parts inbetween the <> tags it goes Symbol(e.g £, $, #) . area to look . field . symbol //separates the Code Identifier and the ExtData and Code
try
{
foreach(ExtendedData ex in this.CurrentSession.CurrentFile.ExtendedData) //Search through All data connected to the file, Extended data is essentially all the data from the database that is specific to the current user
{
if(ex.Code.ToLower() == ExtDataCodeAndSymbols[1].ToLower())
{
OriginalWords[Index] = ExtDataCodeAndSymbols[0] + ex.GetExtendedData(ExtDataCodeAndSymbols[2]).ToString() + ExtDataCodeAndSymbols[3]; //Replace code with new data
break;
}
}
}
catch (Exception ex)
{
System.Windows.Forms.MessageBox.Show("Extended Data Field " + ExtDataCodeAndSymbols[1] + "." + ExtDataCodeAndSymbols[2] + " Not found, please speak to your system administrator"); //Handles Error if Ext Data is not found
}
}
Index++;
}
foreach(string Word in OriginalWords)
{
ConvertedText += Word + " "; //Adds all words into a single string and adds space
}
ConvertedText.Remove(ConvertedText.Length -1, 1); //Removes Last Space
return ConvertedText;
}
The text goes in "Hello my name is <.Person.name.> and I have <£.Account.Balance.> in my bank account" and comes out "Hello my name is James and I have £100 in my bank account"
The symbols are optional but the "." are necessary as they are used to split the strings early in the function
If you have to use <!...!> placeholders, I suggest regular expressions:
using System.Text.RegularExpressions;
...
string OriginalText = "Hello my name is <!name!> and I am <!age!> years old";
Dictionary<string, string> substitutes =
new Dictionary<string, string>(StringComparer.OrdinalIgnoreCase) {
{ "name", "John" },
{ "age", "108"},
};
string result = Regex
.Replace(OriginalText,
#"<!([A-Za-z0-9]+)!>", // let placeholder contain letter and digits
match => substitutes[match.Groups[1].Value]);
Console.WriteLine(result);
Outcome:
Hello my name is John and I am 108 years old
Assuming you are stuck with that format, and assuming you know the list of fields ahead of time, you can compose a dictionary of replacement strings and, well, replace them.
//Initialize fields dictionary
var fields = new Dictionary<string, string>();
fields.Add("name", "John");
fields.Add("age", "18");
//Replace each field if it is found
string text = OriginalText;
foreach (var key in fields.Keys)
{
string searchFor = "<!" + key + "!>";
text = text.Replace(searchFor, fields[key]);
}
If the values for the replacement fields come from a domain object, you could just iterate over the properties using reflection:
class Person
{
public string Name { get; set; }
public int Age { get; set; }
}
class Program
{
const string OriginalText = "Hello my name is <!name!> and I am <!age!> years old";
public static void Main()
{
var p = new Person();
p.Age = 18;
p.Name = "John";
//Initialize fields dictionary
var fields = new Dictionary<string, string>();
foreach (var prop in typeof(Person).GetProperties(BindingFlags.Public | BindingFlags.Instance))
{
fields.Add(prop.Name, prop.GetValue(p).ToString());
}
///etc....
And if you need the tag check to be case insensitive, you can use this instead of String.Replace():
string searchFor = #"\<\!" + key + #"\!\>";
text = Regex.Replace(text, searchFor, fields[key], RegexOptions.IgnoreCase);
I think you're looking for this:
var str = string.Format("Hello my name is {0} and I am {1} years old", name, age);
Or, since C# 6, you can just use this:
var str = $"Hello my name is {name} and I am {age} years old";

Extract name and surname from string in c#

I need extract the name and surname from a email string.
In the database I have two type of address email working :
name.surname#xxxx.eu
Or
name.surname#xxxx.com
And I have tried this code :
string Email1 = Email.ToString().ToUpper().Replace("#", "");
if (Email1.Contains("XXXX.COM"))
{
Response.Write(Email1.ToString().Replace(".", " ").ToUpper().Remove(Email1.Length - 8, 8) + "<br />");
}
else
{
Response.Write(Email1.ToString().Replace(".", " ").ToUpper().Remove(Email1.Length - 7, 7) + "<br />");
}
This code not working for only these addresses emails :
VINCENT.NAPOLITAIN#XXXX.EU
because the return is :
VINCENT NAPOLITAINX
Not working for :
MARK.CHAIN#XXXX.COM
because the return is :
MARK CHAINX
Not working for :
NICODEMUS.ANGELICUM#XXXX.EU
because the return is :
NICODEMUS ANGELICUMX
How to do resolve this?
Please help me, thank you so much in advance.
why don't you split your address by the both seperator characters # and .
string email = "VINCENT.NAPOLITAIN#XXXX.EU";
string[] result = email.Split('.', '#').ToArray();
string firstname = result[0];
string lastname = result[1];
Simplistic approach (based on the requirements that you specified, which seem to be a bit strange):
var test = "name.surname#xxxx.eu";
var name = test.Substring(0, test.IndexOf('#')).Replace(".", " ");
Might want to add exception handling, of course.
You can use String.split():
string email = "VINCENT.NAPOLITAIN#XXXX.EU";
string names = email.Split('#')[0];
string name = "";
string surname = "";
if (names.Contains('.'))
{
var nameSurname = names.Split('.');
name = nameSurname[0]; //
surname = nameSurname[1];
}
You can use Regex Pattern:
(.+)\.(.+)(?=\#)
Explanation:
(.+) - Matches any character in a group
\. - Matches (.) dot
(?=\#) - Exclude # character
Code:
var match = Regex.Match(email, pattern);
var name = match.Groups[1].Value;
var surname = match.Groups[2].Value;
One option is to find the index of the . and the index of the # and do substrings on that:
string email = "aa.bb#cc.dd";
int periodIndex = email.IndexOf('.');
int atIndex = email.IndexOf('#');
string firstName = email.Substring(0, periodIndex);
string lastName = email.Substring(periodIndex + 1, atIndex - periodIndex - 1);
An easier way is to use a regular expression that cuts out the names.
This one will do:
(.*?)\.(.*?)#(.*)
The first capture is the first name, the second capture is the last name.
I would just use split in order to do it:
var nameDOTsurname = Email1.Split('#'); // This would leave in nameDOTsurname[0] the name.surname and in nameDOTsurname[1] the XXX.whatever
var name = nameDOTsurname[0].Split('.')[0];
var surname = nameDOTsurname[0].Split('.')[1];
This will work if your email address format sticks to firstname.secondname#wherever...
here is the code that works for you...
string e = "VINCENT.NAPOLITAIN#XXXX.EU";
string firstname = e.Substring(0, e.IndexOf("."));
string secondname = s.Substring(s.IndexOf(".")+1, s.IndexOf("#")-s.IndexOf(".")-1);
It works for all your emails

How to parse a text file?

Basically I need someone to help me or show me the code that will allow me to read a name and a price from a file i have called c1.txt.
This is what i already have.
TextReader c1 = new StreamReader("c1.txt");
if (cse == "c1")
{
string compc1;
compc1 = c1.ReadLine();
Console.WriteLine(compc1);
Console.WriteLine();
compcase = compc1;
compcasecost = 89.99;
}
also how to select a line to read from a text document would be great.
You haven't told us the format of the text file. I am going to assume the following:
Milk|2.69
Eggs|1.79
Yogurt|2.99
Soy milk|3.79
You also didn't specify the output. I am going to assume the following:
Name = Milk, Price = 2.69
Name = Eggs, Price = 1.79
Name = Yogurt, Price = 2.99
Name = Soy milk, Price = 3.79
Then the following will read such a file and produce the desired output.
using(TextReader tr = new StreamReader("c1.txt")) {
string line;
while((line = tr.ReadLine()) != null) {
string[] fields = line.Split('|');
string name = fields[0];
decimal price = Decimal.Parse(fields[1]);
Console.WriteLine(
String.Format("Name = {0}, Price = {1}", name, price)
);
}
}
If your separator is different then you need to change the parameter '|' to the method String.Split (invoked on the instance of String named line as line.Split('|')).
If your format needs to be different then you need to play with the line
String.Format("Name = {0}, Price = {1}", name, price)
Let me know if you have any questions.
You can also try using a parsing helper class as a starting point, such as the one described at http://www.blackbeltcoder.com/Articles/strings/a-text-parsing-helper-class.
static void ReadText()
{
//open the file, read it, put each line into an array of strings
//and then close the file
string[] text = File.ReadAllLines("c1.txt");
//use StringBuilder instead of string to optimize performance
StringBuilder name = null;
StringBuilder price = null;
foreach (string line in text)
{
//get the name of the product (the string before the separator "," )
name = new StringBuilder((line.Split(','))[0]);
//get the Price (the string after the separator "," )
price = new StringBuilder((line.Split(','))[1]);
//finally format and display the result in the Console
Console.WriteLine("Name = {0}, Price = {1}", name, price);
}
It gives the same results as #Jason's method, but I think this is an optimized version.

Categories