C# How to writeline specific string within the string? - c#

I'm new to c# and I have a little problem. I have the string:
string file = "Eep_A5000400A_A4000500A$1000219_Mura_20190409003057.eep";
string name1;
string name2;
string name3;
string name4;
How to get string's positions
6..12 -> "5000400"
16..22 -> "4000500"
33..36 -> "Mura"
53..55 -> "eep"
by using IndexOf or Substring? (file above just an example, string inside it may vary). For example given, my expectation result is:
Console.WriteLine(name1);
Console.WriteLine(name2);
Console.WriteLine(name3);
Console.WriteLine(name4);
Outcome:
5000400
4000500
Mura
eep
Do you guys have any idea? Thanks in advance.

Simple arithmetics should do:
string name = file.Substring(startIndex - 1, stopIndex - startIndex + 1);
In your case
name1 = file.Substring( 6 - 1, 12 - 6 + 1);
name2 = file.Substring(16 - 1, 22 - 16 + 1);
name3 = file.Substring(33 - 1, 36 - 33 + 1);
name4 = file.Substring(53 - 1, 55 - 53 + 1);
You may want to implement an extension method for this:
public static partial class StringExtensions {
public static string FromTo(this string value, int fromIndex, int toIndex) {
if (null == value)
throw new ArgumentNullException(nameof(value));
else if (fromIndex < 1 || fromIndex > value.Length)
throw new ArgumentOutOfRangeException(nameof(fromIndex));
else if (toIndex < 1 || toIndex > value.Length || toIndex < fromIndex)
throw new ArgumentOutOfRangeException(nameof(toIndex));
return value.Substring(fromIndex - 1, toIndex - fromIndex + 1);
}
}
And then put as simple as
name1 = file.FromTo( 6, 12);
name2 = file.FromTo(16, 22);
name3 = file.FromTo(33, 36);
name4 = file.FromTo(53, 55);

Use string.Substring(int, int) method
file.Substring(intIndex, intLength)
so you will get everything from chosen index with chosen length

C# String.Substring method
In C# and .NET, a string is represented by the String class. The String.Substring method retrieves a substring from a string instance in C#. The method has the following two overloaded forms.
Substring(Int32) - Retrieves a substring from the specified position
to the end of the string.
Substring(Int32, Int32 - Retrieves a substring from this instance
from the specified position for the specified length.
Therefore, in your case, you can use the following:
string file = "Eep_A5000400A_A4000500A$1000219_Mura_20190409003057.eep";
string name1 = file.Substring(6, 7); //6..12 -> "5000400"
string name2 = file.Substring(16, 7); //16..22 -> "4000500"
string name3 = file.Substring(33, 4); //33..36 -> "Mura"
string name4 = file.Substring(53, 2); //53..55 -> "eep"

Related

C# Extracting Ints from String and Comparing [closed]

Say for example I have a string of results from a few sport matches with each team represented by a letter. I want to focus on the Team 'A', and compare its scores with rest of the teams, to print out how many matches Team A has won, lost, drawn etc.... The sample string shown below.
string results = " A 1 B 0, A 2 C 4, A 1 D 8, A 5 E 9";
I think the best way to do this would to extract all the scores of Team A and populate an array with them and do the same with the remaining scores. I have tried index to solve this, but keep getting stumped. Any ideas ?
Edit: Due to not posting attempts:
char[] tobeconverted = results.Where(Char.IsDigit).ToArray();
int[] sequence = new int[10];
for (int i = 0; i < tobeconverted.Length; i++)
{
sequence[i] = Convert.ToInt32(tobeconverted[i].ToString());
}
This populates the array with all digits so I am unsure of how to distinguish between them.
string teamA = "A ";
int indexOfNextOccurance = results.IndexOf(teamA, results.IndexOf(teamA) + 1);
I then planned to use the indexs with substrings to extract the number and convert to an int, but this only works for the first and second occurrence and I have no idea how to get the other number values.
Split the string at the commas. This returns an array of strings.
Split each string in the array by whitespaces. This results in another array.
Extract the members of the array.
Here is a sample program.
class Program
{
static void Main(string[] args)
{
string results = " A 1 B 0, A 2 C 4, A 1 D 8, A 5 E 9";
string[] matches = results.Trim().Split(',');
List<Match> sportResults = new List<Match>();
foreach (string match in matches)
{
string[] parts = match.Trim().Split(null);
sportResults.Add(new Match() {
Team1 = parts[0], Score1 = int.Parse(parts[1]),
Team2 = parts[2], Score2 = int.Parse(parts[3])});
}
sportResults.ForEach(a => Console.WriteLine(a));
}
}
Encapsulate the team / score in a separate class.
class Match
{
public string Team1 { get; set; }
public string Team2 { get; set; }
public int Score1 { get; set; }
public int Score2 { get; set; }
public override string ToString()
{
return "Team " + Team1 + " " + Score1 + " VS " + Team2 + " " + Score2;
}
}
string results = "A 1 B 0, A 2 C 4, A 1 D 8, A 5 E 9";
List<int> teamAScores = new List<int>();
List<int> otherTeamScores = new List<int>();
foreach(string scoreSet in results.Split(','))
{
scoreSet.Replace(" ", "");
int teamA = -1;
int teamX = -1;
int.TryParse(scoreSet.Substring(1, 1), out teamA);
int.TryParse(scoreSet.Substring(3, 1), out teamX);
if (teamA > -1 && teamX > -1)
{
teamAScores.Add(teamA);
otherTeamScores.Add(teamX);
}
}
You now have a list where each game's scores match in terms of index.

C# Input Value how to validate from A to ZZZ

Input Value can be from A to ZZZ (only alphabetical, no numeric characters) how can I validate a from and to field.
Where the input can be A or AA or AAA
B > A
BB > A
BBB > A
BBB < B
BBB < BB
DD > C
but then D should be < CC fails because it is not a lexicographical order
I was thinking check the length first because if the from length is less than to length then it will always be less. If equal in length then an alphabetical check. Then I come unstuck.
Not simple lexicographical order because three possiable groups single, double, triple chars single group lower than double and triple group and double lower than triple group not just alphabetical.
You can do the following: Imagine the String AAA as a number, saying A*26^2 + A*26^1 + A*26^0
(Base 26, because there are that much letters)
Split the String, Cast values A to Z to 1 to 26 (WhiteSpace in front = 0) and you are done:
A = 0*26^2 + 0*26^1 + 1*26^0 => 1
B = 2 => 2
...
Z = 26 => 26
AA = 1 * 26^1 + 1 => 27
...
ZZ = 26*26^1 + 26 = 702
...
ZZZ = 26*26^2 + 26*26^1 + 26 => 18278
wrap it Like
public int LetterCodeToInt(String LetterCode)
{
//fill up whitespaces in front.
String s = LetterCode.PadLeft(3, '_').ToUpper();
int value = 0;
int k = s.Length -1;
for (int i = 0; i < s.Length; i++)
{
if (s[i] != '_')
{
//ASCII "A" is 65, subtract 64 to make it "1"
value += (((int)s[i]) - 64) * Convert.ToInt32(Math.Pow(26, k));
}
k--;
}
return value;
}
and you can do:
if (LetterCodeToInt("AAA") > LetterCodeToInt("AZ")){
}
have you thought about using a regexp? \b[A-Z]{1,3}\b
string from = "BB";
string to = "AAA";
bool valid = string.Compare(from, to) < 0; // false
So it works already in lexicographical order. Demo
You're on the right track. Create a custom comparer that checks the length first. For example:
public class MyComparer : IComparer<string>
{
public int Compare(string x, string y)
{
if (x.Length < y.Length) return -1;
if (x.Length > y.Length) return 1;
return Comparer.Default.Compare(x, y);
}
}

Concatenation in writeln?

I am new to D and I am just trying things out. A book I am using gave me an example of a generic Binary Search method. I then wanted to make my own main method to print out the results just for fun. I come from Java where String Concatenation is simply done using the + operator.
But when I try that in D, it says that the two types (String and bool in this case) are incompatible. I tried to use the << operation instead as I've seen in C++ but then it told me that it wasn't an integral. How do I concatenate then?
import std.stdio, std.array;
void main() {
bool b = binarySearch([1, 3, 6, 7, 9, 15], 6);
writeln("6 is in array: " + b);
b = binarySearch([1, 3, 6, 7, 9, 15], 5);
writeln("5 i sin the array: " + b);
}
bool binarySearch(T)(T[] input, T value) {
while(!input.empty) {
auto i = input.length / 2;
auto mid = input[i];
if(mid > value) input = input[0 .. i];
else if (mid < value) input = input[i + 1 .. $];
else return true;
}
return false;
}
Easiest for writeln is to just separate it with commas.
writeln("6 is in array: ", b);
Each argument is automatically converted to string and outputted. writeln can take any number of arguments.
In general though, string concat in D is done with the ~ operator: string a = b ~ c; Both b and c have to be of type string.
To convert to string, you can do:
import std.conv;
int a = 10;
string s = to!string(a); // s == "10"
bool c = false;
string s2 = to!string(c); // s2 == "false"
std.conv.to can also convert to and from other types, e.g. to!int("12") == 12.
Thus, string s = to!string(a) ~ " cool " ~ to!string(c); will work there.

Creating unequal age bands in C# Metadata

I need to create a set of unequal age groupings from a patient dataset in C# using Visual Studio 2010 using a Metada method
The age groups are <= 40, 41-50, 51-60, 61-70, 70+
Currently we have some code to do 5 year age groups:
public string AgeGroup5Yrs
{
get
{
int range = Math.Abs(Age / 5) * 5;
return string.Format("{0} - {1}", range, range + 5);
}
}
And some 10 year(equal agegroups)
public string AgeGroup
{
get
{
int range = Math.Abs(Age / 10) * 10;
return string.Format("{0} - {1}", range, range + 10);
}
}
However I need some unequal groups! Any ideas? I am new to C# so any help is useful
This uses Array.BinarySearch so should be pretty performant. indexOf ends up containing the index of the next-larger boundary.
static int[] boundaries = new[] { 40, 50, 60, 70 };
static string AgeGroupFor
{
get
{
int indexOf = Array.BinarySearch(boundaries, Age);
if (indexOf < 0)
indexOf = ~indexOf;
if (indexOf == 0)
return "<= " + boundaries[0];
if (indexOf == boundaries.Length)
return (boundaries[boundaries.Length - 1]) + "+";
return (boundaries[indexOf - 1]+1) + "-" + boundaries[indexOf];
}
}
Alternatively you could pre-calculate the strings:
static int[] boundaries = new[] { 40, 50, 60, 70 };
static string[] groups = new[] { "<= 40", "41-50", "51-60", "61-70", "70+" };
static string AgeGroupFor
{
get
{
int indexOf = Array.BinarySearch(boundaries, Age);
if (indexOf < 0)
indexOf = ~indexOf;
return groups[indexOf];
}
}

VB.Net to C# byte array issue

I have a VB.net project that I have converted over to C#. One part of the code gives a different result in C# than it does in VB.Net. Can someone tell me what is wrong with the C# code here and how to fix it?
VB.Net:
Private Sub mco_GetDataReturn(ByVal TransactionNumber As Short, ByVal DataType As ModiconComunications.ModiconComObject.GetDataType, ByVal Success As Boolean, ByVal UserData() As Byte) Handles mco.GetDataReturn
OrderNumber = ""
HeatNumber = ""
If UserData.GetUpperBound(0) < 17 Then
'MsgBox("ModComm1_GetDataReturn - Not enough data returned from PLC read : " & UBound(UserData, 1) + 1 & " bytes")
ReDim Preserve UserData(0 To 17)
ElseIf UserData.GetUpperBound(0) > 17 Then
'MsgBox("ModComm1_GetDataReturn - Too much data returned from PLC read : " & UBound(UserData, 1) + 1 & " bytes")
ReDim Preserve UserData(0 To 17)
End If
OrderNumber = System.Text.Encoding.ASCII.GetChars(UserData, 0, 8)
OrderRelease = System.Text.Encoding.ASCII.GetChars(UserData, 8, 2)
HeatNumber = System.Text.Encoding.ASCII.GetChars(UserData, 10, 6)
PieceNumber = UserData(16) * 256 + UserData(17)
End Sub
C#:
private void mco_GetDataReturn(short TransactionNumber, ModiconComunications.ModiconComObject.GetDataType DataType, bool Success, byte[] UserData)
{
OrderNumber = "";
HeatNumber = "";
if (UserData.GetUpperBound(0) < 17)
{
Array.Resize(ref UserData, 18);
}
else if (UserData.GetUpperBound(0) > 17)
{
Array.Resize(ref UserData, 18);
}
OrderNumber = System.Text.Encoding.ASCII.GetString(UserData, 0, 8).ToString();
OrderRelease = System.Text.Encoding.ASCII.GetString(UserData, 8, 2).ToString();
HeatNumber = System.Text.Encoding.ASCII.GetString(UserData, 10, 6).ToString();
PieceNumber = UserData[16] * 256 + UserData[17];
}
The specific problem is with the last statement for PieceNumber. In VB.Net the statement produces the actual piece number, however in the C# code it produces 0 (zero). How do these statements differ? The PieceNumber variable is declared as an int in both projects.
In VB.net, when you create an array with new Array(10), you indicate that its upper bound will be 10, thus it contains 11 elements.
In C#, new Array(10) will create an array of 10 elements (from 0 to 9).
I guess it's the root of your problem.
Doesn't it depend on the initial content of UserData? Are you sure you call it with the same parameters?
if it is, say, 10 bytes long, and you resize it to 18 bytes, the 'new' values will be zero.
Thus UserData[16] * 256 + UserData[17] == 0 * 256 + 0 = 0
Besides, in VB you have
OrderNumber = System.Text.Encoding.ASCII.GetChars(UserData, 0, 8)
While in C# you have
OrderNumber = System.Text.Encoding.ASCII.GetString(UserData, 0, 8).ToString();
You do that also for other two strings? Why the difference if it is a simple rewrite?
following code (in LinQPad) works as expected. Give us some sample data to investigate.
var testData = new Dictionary<string, int> {
{ "01234567890123", 0 },
{ "012345678901234", 0 },
{ "0123456789012345", 0 },
{ "01234567890123456", 13824 },
{ "012345678901234567", 13879 },
{ "0123456789012345678", 13879 },
{ "01234567890123456789", 13879 },
{ "012345678901234567890", 13879 }
};
foreach (var pair in testData){
var testCase = pair.Key;
var expected = pair.Value;
var UserData = System.Text.Encoding.ASCII.GetBytes(testCase);
if (UserData.GetUpperBound(0) < 17)
{
Array.Resize(ref UserData, 18);
}
else if (UserData.GetUpperBound(0) > 17)
{
Array.Resize(ref UserData, 18);
}
var OrderNumber = System.Text.Encoding.ASCII.GetString(UserData, 0, 8).ToString();
var OrderRelease = System.Text.Encoding.ASCII.GetString(UserData, 8, 2).ToString();
var HeatNumber = System.Text.Encoding.ASCII.GetString(UserData, 10, 6).ToString();
var PieceNumber = UserData[16] * 256 + UserData[17];
(new {
TestCase = testCase,
OrderNumber,
OrderRelease,
HeatNumber,
PieceNumber,
Success = PieceNumber == expected
}).Dump();
}

Resources