VB6 to C# InsTR function conversion issue - c#

Is the VB6 code
i = InStr(1, strText, "Mc", CompareMethod.Binary)
If (i <> 0) And (i + 2 <= lngLength) Then Mid(strText, i + 2, 1) = UCase(Mid(strText, i + 2, 1))
doing the same as
i = strText.IndexOf("Mc");
if ((i != 1) && (i + 2 <= lngLength))
{
strText = strText.Substring(i + 2, 1);
strText = strText.ToUpper();
}
in C#? i is an int that has been initialized. Now I did make adjustment with the returned value if the comparisons are good from 0 in VB6 to 1 in C#.

It’s not doing the same. The assignment
Mid(strText, i + 2, 1) = UCase(Mid(strText, i + 2, 1))
replaces only that part (i.e. a single character at i+2) inside the string, and leaves the rest untouched. Your C# code throws the rest of the string away.
Since .NET strings are immutable, this approach cannot be directly translated.
The closest translation is to construct the string explicitly, i.e. to do
strText = strText.Substring(0, i + 1) +
strText.Substring(i + 2, 1).ToUpper() +
strText.Substring(i + 3);
However, doing this a lot inside a loop is very inefficient, which is why .NET offers the StringBuilder class for repeated constructions of strings. In general, VB6 code which manipulates strings in-place is best translated by using said StringBuilder.
That said, there is probably a simpler translation by going after the intent after the first code, rather than the letter. In both VB6 and C# you wouldn’t use InStr followed by substitution – you’d directly use String.Replace.
Also beware of the changed indices (C# and VB.NET are 0-based, VB6 may be 1-based).

StringBuilder strText = new StringBuilder("Mcdonald");
int lngLength = strText.Length;
int i = strText.ToString().IndexOf("Mc");
if ((i != 1) && (i + 2 <= lngLength))
{
strText[i + 2] = char.ToUpper(strText[i + 2]);
}
Console.WriteLine(strText.ToString()); // prints McDonald
EDIT: Basically, you don't have to get the string before/after the position at which the character is found and do a concatenation of it. StringBuilder helps to modify things in place (string as array of characters) and the ToString method joins the array of characters to a string.

Related

Can I use a string value to replace + or - operator in a C# calculation?

I have a string contained in operationComboBox.Text and I know that the string will be either "+" or "-". I can then perform an addition or subtraction between 2 equations using this code:
if ((operationComboBox.Text == "-"))
{
equation3XCoeff = equations[index1].XCoeff - equations[index2].XCoeff;
equation3YCoeff = equations[index1].YCoeff - equations[index2].YCoeff;
equation3Answer = equations[index1].Answer - equations[index2].Answer;
}
else //if (operationComboBox.Text=="+")
{
equation3XCoeff = equations[index1].XCoeff + equations[index2].XCoeff;
equation3YCoeff = equations[index1].YCoeff + equations[index2].YCoeff;
equation3Answer = equations[index1].Answer + equations[index2].Answer;
}
My question is, can I get rid of the if statement and use the string value directly in the sums to be performed so as to shorten my code some how? Its probably not too important but I just like my code to be short and the 3 calculations are almost duplicated but for the sign.
You can't use it directly - it is a string and strings can't be used instead of operator. But based on the text, you can initialize some numeric variable and use it in you equations:
var coef = operationComboBox.Text == "-" ? -1 : 1;
equation3XCoeff = equations[index1].XCoeff + coef * equations[index2].XCoeff;
equation3YCoeff = equations[index1].YCoeff + coef * equations[index2].YCoeff;
equation3Answer = equations[index1].Answer + coef * equations[index2].Answer;
I don't think you can because the code that you're writting in your visual studio isn't compile into the primitive type 'string'. Visual studio won't be able to interprete it, it will only see that you put some random primitive type 'string' in the middle of nowhere.
You better try it and you will see that it won't compile.

Bifurcate a string, removing the middle of the string instead of end

I want something similar to this question I found lead me to this answer on another question where I tried to convert it from php to c# my attempt to convert it... failed very badly:
private string trimString(string str, int maxCharacters = 16)
{
int textLength = str.Length;
return str.Substring(maxCharacters/2, textLength-maxCharacters).Insert(maxCharacters/2,"...");
}
So doing trimString("123456789", 9) outputs 123...789 when I meant to do something like 123...012 or something similar.. I can't quite figure it out and I've tried many different versions mostly resulting in an input that is out of order.
If it's possible I'd like it to be a simple function and not include other libraries or initializing a new object every call as I plan on using this a lot in a quick session. I'd really like it not to cut off words and place the ellipses however this is not required.
The problem is that Substring(maxCharacters/2, textLength-maxCharacters) into which you insert the ... already has the characters that you don't want to see - 456789. There's no way to fix it after that.
What you should do instead is to pick the prefix and the suffix, and join them together, like this:
private static string trimString(string str, int maxCharacters = 16) {
if (str.Length <= maxCharacters) {
return str;
}
var suffixLength = maxCharacters / 2;
// When maxCharacters is odd, prefix will be longer by one character
var prefixLength = maxCharacters - suffixLength;
return string.Format(
"{0}...{1}"
, str.Substring(0, prefixLength)
, str.Substring(str.Length-suffixLength, suffixLength)
);
}
Demo.
this returns 123...012 for trimString("123456789012", 6) the first and the last 3 characters, seperated with ....
public static string trimString(string str, int max = 16)
{
if (str.Length <= max)
{
return str;
}
return str.Substring(0, max / 2) + "..." + str.Substring(str.Length - max / 2, max / 2);
}

How to parse the following string

I am trying to generate a formula which could be anything like this, this is just a sample,
A + B + C > D - A
Now, A, B, C, D, etc are Column Names of a sheet (like excel sheet) i will be accessing in memory.
I need to generate a Rule, like the above A + B + C > D - A which will decide what kind of values user can add in a Cell.
Currently this is how i have begun:
string toValidate = "A + B + C > D + E - A";
string lhs = "", rhs = "";
string[] comparisonOperators = new string[] { "=", ">", "<", "<>", "!=" };
char[] arithmeticOperators = { '+', '-', '/', '*' };
toValidate = toValidate.Replace(#" ", "");
for (int i = 0; i < comparisonOperators.Length; i++)
{
if (toValidate.Contains(comparisonOperators[i]))
{
operatorIndex = toValidate.IndexOf(comparisonOperators[i]);
break;
}
}
lhs = toValidate.Substring(0, operatorIndex);
rhs = toValidate.Substring(operatorIndex + 1);
string[] columnLhsList = lhs.Split(arithmeticOperators);
string[] columnRhsList = rhs.Split(arithmeticOperators);
However even though i have the strings as lhs and rhs and even my operator which > in the above code, i am not able to understand how can i apply the formula on the sheet itself. I just need to know which Column has which operator associated.
Since i have the individual column names, but not the operator before them, for e.g,
+ before A - before A in another case.
How do i parse the above please help.
It is, however, a very fun question if you want to make simple formula parsers like this yourself.
I advice you to check out this article, since it is very clearly written and understandable because of it.
Shunting-yard Algorithm
Personally, I would never try/dare to create my own formula expression parser. Instead, I would (and did) use one of the may available ones, e.g. NCalc over at CodePlex.com.
Using these tools, it is as easy as writing
Expression e = new Expression("2 + 3 * 5");
Debug.Assert(17 == e.Evaluate());
to get your formula evaluated.
Usually such libraries are very solid, well tested and have a rich function set. It would take ages (if ever) to do such a high quality library on my own.
To further cite the NCalc website, you can even use variables like e.g.:
Expression e = new Expression("Round(Pow([Pi], 2) + Pow([Pi2], 2) + [X], 2)");
e.Parameters["Pi2"] = new Expression("Pi * [Pi]");
e.Parameters["X"] = 10;
e.EvaluateParameter +=
delegate(string name, ParameterArgs args)
{
if (name == "Pi")
args.Result = 3.14;
};
Debug.Assert(117.07 == e.Evaluate());

Postfix Calculator

Making a console application in C sharp to solve expressions in postfix notation by utilizing a stack, such as:
Expression: 43+2*
Answer: 14
What I've done so far:
using System;
using System.Collections;
using System.Linq;
using System.Text;
namespace ConsoleApplication7
{
class Program
{
static void Main(string[] args)
{
string input = "23+";
int counter = 0;
Stack values = new Stack();
while (counter < input.Length)
{
int temp1,
temp2,
answer;
char x = char.Parse(input.Substring(counter, 1));
if ( );
else if (x == '+')
{
temp1 = (int)values.Pop();
temp2 = (int)values.Pop();
values.Push(answer = temp1 + temp2);
}
else if (x == '-')
{
temp1 = (int)values.Pop();
temp2 = (int)values.Pop();
values.Push(answer = temp1 - temp2);
}
else if (x == '*')
{
temp1 = (int)values.Pop();
temp2 = (int)values.Pop();
values.Push(answer = temp1 / temp2);
}
else if (x == '/')
{
temp1 = (int)values.Pop();
temp2 = (int)values.Pop();
values.Push(answer = temp1 * temp2);
}
counter++;
}
Console.WriteLine(values.Pop());
}
}
For the if statement, what can I use as a condition to check if x is a operand?
Is your example input 2, 3, + (which equals 5), or 23, + (which is invalid input)? I'm assuming the former. How, then, would you write two-digit numbers? Your current approach doesn't seem to support this. I think you shouldn't be parsing this char-by-char, but split it into the separate components first, perhaps using a regex that recognizes numbers and punctuation. As a quick example: Regex.Matches("10 3+", #"(\d+|[\+\-\*/ ])") splits into 10, , 3, and +, which can be parsed and understood fairly easily with the code you already have, (spaces should be ignored; they're simply a punctuation I picked to separate numbers so that you can have multi-digit numbers) and int.TryParse (or double, which requires a more complicated regex pattern, see Matching Floating Point Numbers for that pattern) to see if an input is a number.
You should use a Stack<int> to avoid casting and make it compile-time safe.
Surely this is wrong:
((int)Char.GetNumericValue(x) <= 0 && (int)Char.GetNumericValue(x) >= 0)
I think it should be
((int)Char.GetNumericValue(x) <= 9 && (int)Char.GetNumericValue(x) >= 0)
I really think this is more like a code review but well so be it - first: please seperate some concerns - you baked everything into a big messy monster - think about the parts of the problem and put them into seperate methods to start with.
Then: if you cannot solve the hole problem, make it smaller first: Let the user enter some kind of seperator for the parts, or assume for now that he does - space will do just fine.
You can think of how to handle operators without spaces pre/postfixed later.
So try parsing "2 3 +" instead of "23+" or "2 3+" ...
If you do this you can indeed just use String.Split to make your life much easier!
As to how you can recognize an operant: very easy - try Double.TryParse it will tell you if you passed it a valid number and you don't have to waste your time with parsing the numbers yourself
Instead of using a while in there you should use a for or even better a foreach - heck you can even do this with LINQ and [Enumerable.Aggregate][1] and get FUNctional :D
And finally ... don't use this if/then/else mess if a switch does the job ...
You could say that there essentially are no operands. Even digits can be thought of as operators that multiply the top of the stack by 10 and add the digit value; accumulating a value over several digits as necessary. Then you just need an operator for seeding this by pushing a zero to the stack (perhaps a space character for that).
http://blogs.msdn.com/b/ashleyf/archive/2009/10/23/tinyrpn-calculator.aspx

c# longest common words sample

i am looking for a longest common words c# implementation. Most of the samples i have came across are comparing character by character.
in otherwords,
string1 = access
string2 = advised
should return null output from the function
any sample codes?
I think this problem is usually referred to as the Longest common substring problem. The Wikipedia article contains pseudocode, and C# implementations can be found on the Web.
If by word you mean these letter things, seperated from the others by punktuation, try this:
private String longestCommonWord(String s1, String s2)
{
String[] seperators = new String[] { " ", ",", ".", "!", "?", ";" };
var result = from w1 in s1.Split(seperators, StringSplitOptions.RemoveEmptyEntries)
where (from w2 in s2.Split(seperators, StringSplitOptions.RemoveEmptyEntries)
where w2 == w1
select w2).Count() > 0
orderby w1.Length descending
select w1;
if (result.Count() > 0)
{
return result.First();
}
else
{
return null;
}
}
This probably is not the most elegant way to do it, but it works for me. =)
Turning the algorithm which computes LCS of arrays of characters into one that does it to arrays of anything else -- like, say, an array of words -- is usually pretty straightforward. Have you tried that?
If you need some hints, here's an article I wrote a couple years ago on how to implement Longest Common Subsequence on an array of words in JScript. You should be able to adapt it to C# without too much difficulty.
http://blogs.msdn.com/ericlippert/archive/2004/07/21/189974.aspx
Finding differences in strings is called the Longest Common Subsequence problem. The following is a generic solution to the LCS problem, written in C#:
static int[,] GetLCSDifferenceMatrix<T>(
Collection<T> baseline,
Collection<T> revision)
{
int[,] matrix = new int[baseline.Count + 1, revision.Count + 1];
for (int baselineIndex = 0; baselineIndex < baseline.Count; baselineIndex++)
{
for (int revisionIndex = 0; revisionIndex < revision.Count; revisionIndex++)
{
if (baseline[baselineIndex].Equals(revision[revisionIndex]))
{
matrix[baselineIndex + 1, revisionIndex + 1] =
matrix[baselineIndex, revisionIndex] + 1;
}
else
{
int possibilityOne = matrix[baselineIndex + 1, revisionIndex];
int possibilityTwo = matrix[baselineIndex, revisionIndex + 1];
matrix[baselineIndex + 1, revisionIndex + 1] =
Math.Max(possibilityOne, possibilityTwo);
}
}
}
return matrix;
}
This code gives you a "difference" matrix, which can then be used to construct the difference from the two inputs. For unit tests and example usage, see http://sethflowers.com/2012/01/18/basic-diff-with-a-generic-solution-to-the-longest-common-subsequence-problem.html.

Categories