C# Split String and Assign Splitted Value To Another Variable - c#

I am trying to split a string and assign the different values. The string it returns to me is:
0077|PCK|PRD|05025066840471|4|Can Opener|1|10|B|20.00|0|100|0|0.00|0|0|1|0|0
So I want to split the string on "|" and assign each of them to another variable. That is what I tried to do:
public static void LoadPRD(string sData)
{
string[] s = null;
prdType PRD = new prdType();
s = sData.Split("|");
PRD.bCode = s.Left(s[0], 14);
PRD.PCode = s.Left(s[1], 12);
PRD.Desc = s.Left(s[2], 40);
PRD.Pack = s.Val(s[3]);
PRD.Unit = s.Left(s[4], 12);
PRD.VATCode = s.Left(s[5], 1);
PRD.VATRate = Conversion.Val(s[6]);
PRD.Cost = Conversion.Val(s[7]);
PRD.Sell = Conversion.Val(s[8]);
PRD.Stock = Conversion.Val(s[9]);
PRD.AWS = Conversion.Val(s[10]);
PRD.OnOrder = Conversion.Val(s[11]);
PRD.OrderQty = Conversion.Val(s[12]);
PRD.LabelQty = Conversion.Val(s[13]);
PRD.Restriction = s.Left(s[14], 1);
PRD.MinStock = s.Val(s[15]);
PRD.PromoCode = s.Left(s[16], 3);
PRD.MnM = s.Left(s[17], 3);
}
The error message says that the Strings does not exist in the context, but it is not too of a helpful information, I do understand what it means but I am very confused on how to approach the solution.
Just so you know, I did create the variable before hand, I've posted them below:
public struct prdType
{
public string bCode;
public string PCode;
public string Desc;
public Int16 Pack;
public string Unit;
public string VATCode;
public float VATRate;
// Stored in pence
public long Cost;
public long Sell;
public long Stock;
public float AWS;
public long OnOrder;
public long OrderQty;
public long LabelQty;
public string Restriction;
public long MinStock;
public string PromoCode;
}
Your help will be much appreciated.
Thanks.
EDIT:
On
s = sData.Split("|");
it says: "The best overloaded method match for string.Split(params char[]) has some invalid arguments. It also says that arguments cannot be converted to char. Any ideas?

Rather than use legacy VB methods for this, I would suggest using C# methods all the way.
string[] s = sData.Split('|');
The use of Strings.Left is not readily apparent. Since you've already split the line, you'll have each element of the split in its entirety. If you want to take only the first n characters, you can do that, but there is no built-in equivalent for Strings.Left in C#.
For those elements that are a different type, you can use Convert.ToX:
PRD.Pack = Convert.ToInt16(s[3]));
PRD.VATRate = Convert.ToSingle(s[6]));
PRD.Cost = Convert.ToInt64(s[7]);
And so on. Note that float uses Convert.ToSingle, not Convert.ToFloat.
ADDED
Based on #Raphael's comment, Convert.ToX is not a direct replacement for Conversion.Val(), but as long as the string is strictly numeric you will be ok and will get the correct type.

These methods come from Microsoft.VisualBasic namespace.It should be only used if you know what you're doing (see Tim's comment on this answer).
I wouldn't advise you to use these methods.
They are equivalent methods in c# (or they're rather easy to implement).
Like String.Split, for example (so you could do var s = sData.Split('|'); )
A way to do something equivalent to String.Left
Wouldn't advise to do this, but anyway :
If you want absolutely use them, you should :
Add a reference to Microsoft.VisualBasic assembly (right click on project's references, you should find it in Framework libs)
Add the right using at the top of your code : using Microfost.VisualBasic;

You need to do s = sData.Split('|');

Related

MVC - Handling Common Key Values

I have a question that I'm sure has already been answered. Any help pointing me in the right direction would be appreciated.
I have a standard ASP MVC site. As with any site, I have the usual collection of key values for various aspects of the application.
Hair Color
10 = Green
20 = Brown
...
Status
10 = Active
20 = Paused
99 = Inactive
...
SubscriptionType
10 = 1 Week
20 = 1 Month
30 = 3 Month
...
Approval
0 = Pending Approval
10 = Approved
20 = Approved with Conditions
99 = Rejected
etc..etc..etc...
Normally, I have a bunch of DB tables associated with the various types but I find all the overall management of this method tedious (creating, adding values, SQL calls)
My question:
Is there a simple and straightforward way of defining and accessing these key values within the MVC code itself. I know I can use various means (Lists, Dictionary, Hashtables, Enums, etc..) but I'm looking for something that I can easily access across various Controllers AND Views (in some Common Helper class?). I want to be able to get the value from the key OR the reverse and get the key from the value.
I know there are probably 1000 ways to skin this cat but I'd be interested if anyone could point me to a simple and straightforward way to do it. Is this something that could (or should) be done in the Model layer? A Helper "CommonValues" class? Any suggestions would be welcome.
Apologies if this is "Programming 101" stuff. (I'm self taught)
For integers
You can use an enum, like this:
enum SubscriptionType
{
OneWeek = 10,
OneMonth = 20,
ThreeMonths = 30
}
You could certainly define your enums as members of a CommonValues class, if you have one. Or you could define them within the namespace and outside of any class, which would make them globally available.
For strings (or integers if you like this method better)
You can define constants as a member of a class. Constants are exposed as static fields so they are accessible anywhere.
public class CommonValues
{
public const string ColorRed = "RED";
public const string ColorBlue = "BLUE";
public const string WorkflowStateStopped = "STOPPED";
public const string WorkflowStateRunning = "RUNNING";
}
//Main program
var a = CommonValues.ColorRed;
var b = CommonValues.WorkflowStateRunning;
Notice the messy "ColorXXX" pattern. Seems a little 90s to me. If you want to restrict namespaces so your intellisense works a bit more usefully, you can use a nested class.
public class CommonValues
{
public class Colors
{
public const string Red = "RED";
public const string Blue = "BLUE";
}
public class WorkflowStates
{
public const string Running = "RUNNING";
public const string Stopped = "STOPPED";
}
}
//Main program
var b = CommonValues.Colors.Red;
var c = CommonValues.WorkflowStates.Running;
Display
When it comes to display the meaning of one of these codes, naturally your display elements should come from resources, which will automatically adapt to the current culture (after all, some day you will be an international giant). You can organize your resources with names like this:
var resources = new ResourceManager("CommonValues", myAssembly);
//Example for use with enum
SubscriptionType code = SubscriptionType.OneWeek;
var display = resources.GetString("SubscriptionType." + code.ToString()); //Resource ID = "SubscriptionType.OneWeek";
//Example for use with string constant
var colorCode = CommonValues.Colors.Red;
var display = resources.GetString("Colors." + colorCode); //Resource ID = "Colors.Red";
I wanted to put in some details of what I did in case this helps others down the line. Using John Wu's answer from above (thanks!!), here's what I did.
Create the enum. You need to put this in some class that you can reference in the View. I called mine EnumValues in the EnumHelper namespace.
namespace MyProject.EnumHelper
{
public static class EnumValues
{
public enum ProjectStatus
{
Active = 10,
Paused = 20,
Inactive = 99
}
...
So the beginning of my View looks like
#using MyProject.EnumHelper;
#model MyProject.Models.ProjectViewModel;
...
Now, if I have the integer value (say from the DB call) and I want the decoded string (ex. "Active"), I did this in the view.
var projectstatus = (EnumValues.ProjectStatus)Model.project_status;
If I need to get the enum integer value (ex. in a dropdown), I did this in the view.
var projectstatusid = (int)EnumValues.ProjectStatus.Active;
Thanks again to John Wu for pointing me in the right direction.

How to reference a method return value in a subsequent method?

I am just wondering if there is a way to simplify this code:
var myStr = GetThatValue();
myStr = myStr.Substring(1, myStr.Length - 2); // remove first and last chars
into this:
// how to get hold of GetThatValue return value?
var myStr = GetThatValue().Substring(1, hereWhat.Length - 2);
I though about this keyword but it does not work in this context. It will reference the class instance as expected.
Nope. The alternative is this:
var myStr = GetThatValue().Substring(1, GetThatValue().Length - 2);
Which, as you can see, invokes GetThatValue() twice. So if that operation is expensive or returns different values then it probably shouldn't be re-invoked.
Even if it's not an expensive operation, this is exactly a textbook case of what variables are for... storing values.
It's possible to have a scenario where this is perfectly acceptable, though. Consider C#'s properties, which are really just syntactic sugar over classic getter/setter methods. If we look at those getters in a traditional Java sense, we might have something like this:
private thatValue;
public string GetThatValue() { return someString; }
// later...
var myStr = GetThatValue().Substring(1, GetThatValue().Length - 2);
In this case it's not an expensive operation, nor would it return different values. (Threading notwithstanding.) In this case there's no discernible logical difference between using the variable vs. the method, as the method is simply a wrapper for a class-level variable.
In fact, this approach is often used when the getter has some logic which should always wrap the access to that variable, even for private-only members.
You can try this way (using a temporary variable):
string temp;
var myStr = (temp = GetThatValue()).Substring(1, temp.Length - 2);
or (even shorter):
string myStr = (myStr = GetThatValue()).Substring(1, myStr.Length - 2);
It works too. You have to change var to string while declaring the myStr variable.
another altenative - make an extension method:
public static class Util
{
public static string Trim(this string input, int headTrim, int tailTrim)
{
return input.Substring(headTrim, input.Length - headTrim - tailTrim);
}
}
usage:
var str = GetThatValue().Trim(1, 1);
one-line solution (just for excercise)
regex to remove 1st and last char
string result = Regex.Replace(Regex.Replace(GetThatValue(), "^.", ""), ".$", "");

c# can i optimize this code?

I have this on a button:
private void Button_Click(object sender, RoutedEventArgs e)
{
string s = "x12y04";
//make new instance for MyMath class
MyMath dRet01 = new MyMath();
//use the doubleArrayXY (in MyMath class) to get doubble array back
double[] retD = dRet01.doubleArrayXY(s);
//use the calcResultFromDoubleArray (in MyMath class) to get result
MyMath dRet02 = new MyMath();
double result = dRet02.calcResultFromDoubleArray(retD[0], retD[1]);
//DEBUG!
/*
string TEST1 = Convert.ToString(returnedDouble[0]);
MessageBox.Show(TEST1);
string TEST2 = Convert.ToString(returnedDouble[1]);
MessageBox.Show(TEST2);
string TEST3 = Convert.ToString(result);
MessageBox.Show(TEST3);
*/
}
where the class "MyMath" is:
public double[] doubleArrayXY(string inputValue)
{
//in case there are upper case letters, set all to lower
string inpLow = inputValue.ToLower();
//split the string on the Y (so this tech should also work for x89232y329)
//so this will create res[0] that is x89232 and an res[1] that is 329
string[] res = inpLow.Split(new string[] { "y" }, StringSplitOptions.None);
//in the first string that looks like x89232, remove the x
string resx = res[0].Replace("x", null);
//now get the x value to a double
double x = double.Parse(resx);
//now get the y valye to a double
double y = double.Parse(res[1]);
//return in a double array the x and then the y (x=double[0] and y=double[1])
return new double[] {x,y};
}
public double calcResultFromDoubleArray(double one, double two)
{
return (one * two);
}
Now I know the part in the class that is "calcResultFromDoubleArray" is kind of useless at this point, but I want to make that do some extra stuff later on.
what I wonder about the most is in the main code where I make this new dRet10, and later on make dRet02.
I was thinking at first I could do something like this:
double result = dRet01.calcResultFromDoubleArray(retD[0], retD[1]);
So in that case I would not need to create a new instance of MyMath, but this does not work.
So I need to call a new instance for the class (like I did), or can I do this in a more elegant way?
I'm still kind of new to C#, so I'm trying to learn how to program in a nice and elegant way, besides just making it work.
Since your methods don't really use any other state information besides the parameters passed they probably should be static so you would not have to create any instances of your class at all:
double[] retD = MyMath.DoubleArrayXY(s);
double result = MyMath.CalcResultFromDoubleArray(retD[0], retD[1]);
If all of your methods in MyMath are static, declare the class itself static - just like the System.Math class, so you cannot create instances at all.
You could make your calcResultFromDoubleArray method static, and then call it via MyMath.calcResultFromDoubleArray(val1, val2)
In your code there is not really a point of creating an instance of MyMath class. You can make the methods static
public static double[] doubleArrayXY(string inputValue) { ... }
public static double calcResultFromDoubleArray(double one, double two) { ... }
and call them like so
double[] retD = MyMath.doubleArrayXY(s);
double result = MyMath.calcResultFromDoubleArray(retD[0], retD[1]);
If you make your methods static you can do the following in your main class:
double result = MyMath.calcResultFromDoubleArray(MyMath.doubleArrayXY(s));
And change calcResultFromDoubleArray to take the array rather than two values (as its title suggests).
FYI you can also chain String operations because they return Strings as such:
string[] res = inputValue.ToLower().Split(new string[] { "y" }, StringSplitOptions.None);
No need to create double x and double y. Change the last part of the method to:
return new double[] {double.Parse(resx), double.Parse(res[1]};
While changes such as these (there are more, there often are) will be minimal increases in performance, they will increase it a bit (the most from the static part - new is relatively expensive).
Most importantly though, they make the code more readable and elegant.
It looks to me like the two methods on MyMath could (or possibly should) both be static since they rely on nothing at all outside the method. Quite often this is the case with things like Maths libraries. It seems others have said this too though.
In addition you may be better off to create a class or struct to represent your X/Y. It may be that it isn't appropriate but if it represents a thing then you might want a class to represent that thing as well. See for example the Point and PointF classes. I'd suggest one of these but they don't have the same precision that you are using (and your X/Y may not be points so it might not be appropriate)
Also the line you said didn't work:
double result = dRet01.calcResultFromDoubleArray(retD[0], retD[1]);
This should have worked with the code as shown. What error were you getting on it? dRet01 exists and so it should have worked just as well as creating a new instance. The comments that it should be static are most applicable but if you are new to C# I thought it worth pointing this out so you don't build up any wrong ideas about what is and isn't possible. :)

String insertion problem in c#

I am trying to insert a string at a position for C# string, its failing
here is the snippet.
if(strCellContent.Contains("<"))
{
int pos = strCellContent.IndexOf("<");
strCellContent.Insert(pos,"<");
}
please tell me the solution
The return value contains the new string that you desire.
strCellContent = strCellContent.Insert(pos,"<");
Gunner and Rhapsody have given correct changes, but it's worth knowing why your original attempt failed. The String type is immutable - once you've got a string, you can't change its contents. All the methods which look like they're changing it actually just return a new value. So for example, if you have:
string x = "foo";
string y = x.Replace("o", "e");
the string x refers to will still contain the characters "foo"... but the string y refers to will contain the characters "fee".
This affects all uses of strings, not just the particular situation you're looking at now (which would definitely be better handled using Replace, or even better still a library call which knows how to do all the escaping you need).
I think you might be better of with a Replace instead of an Insert:
strCellContent = strCellContent.Replace("<", "<");
Maybe doing Server.HtmlEncode() is even better:
strCellContent = Server.HtmlEncode(strCellContent);
When I look at your code I think you want to do a replace, but try this:
if(strCellContent.Contains("<"))
{
int pos = strCellContent.IndexOf("<");
strCellContent = strCellContent.Insert(pos,"<");
}
.Contains is not a good idea here, because you need to know the position. This solution will be more efficient.
int pos = strCellContent.IndexOf("<");
if (pos >= 0) //that means the string Contains("<")
{
strCellContent = strCellContent.Insert(pos,"<"); //string is immutable
}
As others have explained with the code, I will add that
The value of the String object is the
content of the sequential collection,
and that value is immutable (that is,
it is read-only).
For more information about the immutability of strings, see the Immutability and the StringBuilder Class section.
from: http://msdn.microsoft.com/en-us/library/system.string.aspx

how to create multiple objects and enumerate them in c#

my problem is as follows:
Im building a console application which asks the user for the numbers of objects it should create and 4 variables that have to be assigned for every object.
The new objects name should contain a counting number starting from 1.
How would you solve this?
Im thinking about a class but im unsure about how to create the objects in runtime from userinput. Is a loop the best way to go?
What kind of class, struct, list, array .... would you recommend. The variables in the object are always the same type but i need to name them properly so I can effectivly write methods to perform operations on them in a later phase of the program.
Im just learning the language and I would be very thankful for a advice on how to approach my problem.
If I understand your problem correctly:
class MyClass
{
public int ObjectNumber { get; set; }
public string SomeVariable { get; set; }
public string AnotherVariable { get; set; }
}
// You should use keyboard input value for this
int objectsToCreate = 10;
// Create an array to hold all your objects
MyClass[] myObjects = new MyClass[objectsToCreate];
for (int i = 0; i < objectsToCreate; i++)
{
// Instantiate a new object, set it's number and
// some other properties
myObjects[i] = new MyClass()
{
ObjectNumber = i + 1,
SomeVariable = "SomeValue",
AnotherVariable = "AnotherValue"
};
}
This doesn't quite do what you described. Add in keyboard input and stuff :) Most of this code needs to be in some kind of Main method to actually run, etc.
In this case, I've chosen a class to hold your 4 variables. I have only implemented 3 though, and I've implemented them as properties, rather than fields. I'm not sure this is necessary for your assignment, but it is generally a good habit to not have publically accessible fields, and I don't want to be the one to teach you bad habits. See auto-implemented properties.
You mentioned a struct, which would be an option as well, depending on what you want to store in it. Generally though, a class would be a safer bet.
A loop would indeed be the way to go to initialize your objects. In this case, a for loop is most practical. It starts counting at 0, because we're putting the objects in an array, and array indexes in C# always start at 0. This means you have to use i + 1 to assign to the object number, or the objects would be numbered 0 - 9, just like their indexes in the array.
I'm initializing the objects using object initializer syntax, which is new in C# 3.0.
The old fashioned way would be to assign them one by one:
myObjects[i] = new MyClass();
myObjects[i].ObjectNumber = i + 1;
myObjects[i].SomeVariable = "SomeValue";
Alternatively, you could define a constructor for MyClass that takes 3 parameters.
One last thing: some people here posted answers which use a generic List (List<MyClass>) instead of an array. This will work fine, but in my example I chose to use the most basic form you could use. A List does not have a fixed size, unlike an array (notice how I initialized the array). Lists are great if you want to add more items later, or if you have no idea beforehand how many items you will need to store. However, in this case, we have the keyboard input, so we know exactly how many items we'll have. Thus: array. It will implicitly tell whoever is reading your code, that you do not intend to add more items later.
I hope this answered some questions, and raised some new ones. See just how deep the rabbit hole goes :P
Use a list or an array. List example:
int numberOfObjects = 3;
List<YourType> listOfObjects = new List<YourType>();
for(int i = 0 ; i < numberOfObjects ; i++ )
{
// Get input and create object ....
// Then add to your list
listOfObjects.Add(element);
}
Here, listOfObjects is a Generic list that can contain a variable number of objects of the type YourType. The list will automatically resize so it can hold the number of objects you add to it. Hope this helps.
If I understood what you are asking you could probably do something like this:
class Foo
{
private static int count;
public string name;
public Foo(...){
name = ++count + "";
}
}
I'm guessing what you're trying to do here, but this is a stab in the dark. The problem I'm having is dealing with the whole "the new objects name should contain a counting number starting from 1" thing. Anyway, here's my attempt:
public class UserInstantiatedClass
{
public int UserSetField1;
public int UserSetField2;
public int UserSetField3;
public int UserSetField4;
public string UserSpecifiedClassName;
}
public static class MyProgram
{
public static void Main(string [] args)
{
// gather user input, place into variables named
// numInstances, className, field1, field2, field3, field4
List<UserInstantiatedClass> instances = new List< UserInstantiatedClass>();
UserInstantiatedClass current = null;
for(int i=1; i<=numInstances; i++)
{
current = new UserInstantiatedClass();
current.UserSpecifiedClassName = className + i.ToString(); // adds the number 1, 2, 3, etc. to the class name specified
current.UserSetField1 = field1;
current.UserSetField2 = field2;
current.UserSetField3 = field3;
current.UserSetField4 = field4;
instances.Add(current);
}
// after this loop, the instances list contains the number of instances of the class UserInstantiatedClass specified by the numInstances variable.
}
}

Categories

Resources