Isolating values from a listbox line - c#

I have got a line in a lisbox that i need so i can print out my receipt for the end of my 12 grade project im doing.
Example of my line :"cha1 Adidas Stan Smith White 1 2" (its padded).
Now what i want to do is isolate like cha1, Adidas stan Smith White,1,2 to add to my Microsoft Access Database, i somehow managed to do it with substring but i screwed up my code and now i cant do it , can somebody help me please ?
My code ,that used to work , looks like this :
foreach (string item in lstpreview.Items)
{
//create the string to print on the reciept
string nomeproduto = item;
float quantidade = float.Parse(item.Substring(item.Length -5, 5));
float precounitario = float.Parse(item.Substring(item.Length - 5, 5));
string totalproduto = item.Substring(item.Length - 6, 6);
txt1.Text = Convert.ToString(quantidade);
txt2.Text = Convert.ToString(precounitario);
//MessageBox.Show(item.Substring(item.Length - 5, 5) + "PROD TOTAL: " + totalproduto);
//float totalprice = 0.00f;
}

You say that the line is padded, but do not give any details. If you know that the first field is always the first 4 characters of the line, you can isolate it with string.Substring:
string field1 = line.Substring(0, 4);
and similarly for the other fields.
P.S. Please edit your post and remove the swear word.
Edit after parsing code added
I don't understand your comment, what is "your negative value"? Run the code in the debugger and find which line causes the error. Please post the exact error message.
Is there a reason for converting the substring to a float and then back to a string? I can imagine that you might want to validate that the field is numeric, but then you would be better to use TryParse.
Your second comment is helpful. The last 5 characters of the line are not all numeric, that's the problem.

Done it with this snippet of code together with a for each loop.
string[] caracteresnastring = item.Split(new char[] { ',' }.ToArray());
string code = caracteresnastring[0];
string name = caracteresnastring[1];
string price = caracteresnastring[2];
string quantity = caracteresnastring[3];

Related

Format unstructured string

I have tried several methods (by position, by white space, regex) but cannot figure how to best parse the following lines as a table. For e.g. let's say the two lines I want to parse are:
Bonds Bid Offer (mm) (mm) Chng
STACR 2015-HQA1 M1 125 120 5 x 1.5 0
STACR 2015-HQA12 2M2 265 5 x -2
I want that it should parse as follows for [BondName] [Bid] [Offer]:
[STACR 2015-HQA1 M1] [125] [120]
[STACR 2015-HQA12 2M2] [265] [null]
Notice the null which is an actual value and also the spaces should be retained in the bond name. FYI, the number of spaces in the Bond Name will be 2 as in the above examples.
Edit: Since many of you have asked for code here it is. The spaces between the points can range from 1-5 so I cannot reply on spaces (it was straightforward then).
string bondName = quoteLine.Substring(0, 19);
string bid = quoteLine.Substring(19, 5).Trim();
string offer = quoteLine.Substring(24, 6).Trim();
The only way I can see this working is that:
1st data point is STACR (Type)
2nd data point is the year and Series
(e.g. 2015-HQA1)
3rd data point is Tranche (M1)
4th data point is bid
(e.g. 125 ** bid is always available **)
5th data point is offer (e.g. 120 but can be blank
or whitespace which introduces complexity)
With the current set of requirements, I'm assuming the following
1. String starts with 3 part bond name
2. Followed by bid
3. Followed by offer (optional)
4. After that, we'll have something like ... x ... ... (we'll use x as reference)
Given they are valid, you can use the following code
var str = "STACR 2015-HQA1 M1 125 120 5 x 1.5 0"; //your data
var parts = str.Split(new char[] { ' ' }, StringSplitOptions.RemoveEmptyEntries).ToList();
//we'll use this pattern : <3 part bond name> <bid> <offer/null> <something x ....>
var xIsAt = parts.IndexOf("x"); //we'll use x as reference
if (xIsAt > 2) //first three are BondName
parts.RemoveRange(xIsAt - 1, parts.Count - xIsAt + 1); //remove "5 x 1.5 ..."
var bond = string.Join(" ", parts.Take(3)); //first 3 parts are bond
var bid = parts.Count > 3 ? parts.ElementAt(3) : null; //4th is bid
var offer = parts.Count > 4 ? parts.ElementAt(4) : null; //5th is offer
[EDIT]
I did not account for the blank 'Offer' so this method will fail on a blank 'Offer'. Looks like someone already has a working answer, but i'll leave the linq example for anyone that finds it useful.
[END EDIT]
Linq based option.
Split the string by spaces, and remove empty spaces. Then reverse the order so you can start from the back and work your way forward. The data appears more normalized at the end of the string.
For each successive part of the line, you skip the previous options and only take what you need. For the last part which is the long string, you skip what you don't need, then reverse the order back to normal, and join the segments together with spaces.
string test = "STACR 2015-HQA1 M1 125 120 5 x 1.5 0";
var split_string_remove_empty = test.Split(new char[]{ ' ' }, StringSplitOptions.RemoveEmptyEntries).Reverse();
var change = split_string_remove_empty.Take(1)
.SingleOrDefault();
var mm2 = split_string_remove_empty.Skip(1)
.Take(1)
.SingleOrDefault();
var mm3 = split_string_remove_empty.Skip(3)
.Take(1)
.SingleOrDefault();
var offer = split_string_remove_empty.Skip(4)
.Take(1)
.SingleOrDefault();
var bid = split_string_remove_empty.Skip(5)
.Take(1)
.SingleOrDefault();
var bonds = string.Join(" ", split_string_remove_empty.Skip(6)
.Reverse());
Output:

How do I Split string only at last occurrence of special character and use both sides after split

I want to split a string only at last occurrence of special character.
I try to parse a name of a tab from browser, so my initial string looks for example like this:
Untitled - Google Chrome
That is easy to solve as there is a Split function. Here is my implementation:
var pageparts= Regex.Split(inputWindow.ToString(), " - ");
InsertWindowName(pageparts[0].ToString(), pageparts[1].ToString());//method to save string into separate columns in DB
This works, but problem occurs, when I get a page like this:
SQL injection - Wikipedia, the free encyclopedia - Mozilla Firefox
Here are two dashes, which means, that after split is done, there are 3 separate strings in array and if I would continue normally, database would contain in first column value "SQL injection" and in second column value "Wikipedia, the free encyclopedia". Last value will be completely left out.
What I want is that first column in database will have value:
SQL injection - Wikipedia, the free encyclopedia" and second column will have:
"Mozilla Firefox". Is that somehow possible?
I tried to use a Split(" - ").Last() function (even LastOrDefault() too), but then I only got a last string. I need to get both side of the original string. Just separated by last dash.
You can use String.Substring with String.LastIndexOf:
string str = "SQL injection - Wikipedia, the free encyclopedia - Mozilla Firefox";
int lastIndex = str.LastIndexOf('-');
if (lastIndex + 1 < str.Length)
{
string firstPart = str.Substring(0, lastIndex);
string secondPart = str.Substring(lastIndex + 1);
}
Create a extension method (or a simple method) to perform that operation and also add some error checking for lastIndex.
EDIT:
If you want to split on " - " (space-space) then use following to calculate lastIndex
string str = "FirstPart - Mozzila Firefox-somethingWithoutSpace";
string delimiter = " - ";
int lastIndex = str.LastIndexOf(delimiter);
if (lastIndex + delimiter.Length < str.Length)
{
string firstPart = str.Substring(0, lastIndex);
string secondPart = str.Substring(lastIndex + delimiter.Length);
}
So for string like:
"FirstPart - Mozzila Firefox-somethingWithoutSpace"
Output would be:
FirstPart
Mozzila Firefox-somethingWithoutSpace
Please forgive me for my laziness ins this solution i'm sure there is a better approach but i will give you one solution proposal i'm assuming you are codding in C#.
First of all correct me if I get wrongly the question no matter what you just want to columns returned the first (all text even of it includes dashes but the last one) and last column (all the text after last dash) if it's ok. let's do it.
// I Only use split function when I want all data in separate variable (array position) in you case I assumed that you just want 2 values (if possible), so you can use substring.
static void Main(string[] args)
{
string firstname = "";
string lastName = "";
string variablewithdata = "SQL injection - Wikipedia, -the free encyclopedia - Mozilla Firefox";
// variablewithdata.LastIndexOf('-') = returns Integer corresponding to the last position of that character.
//I suggest you validate if variablewithdata.LastIndexOf('-') is equal to -1 or not because if it don't found your character it returns -1 so if the value isn't -1 you can substring
firstname = variablewithdata.Substring(0, (variablewithdata.LastIndexOf('-') - 1));
lastName = variablewithdata.Substring(variablewithdata.LastIndexOf('-') + 1);
Console.WriteLine("FirstColumn: {0} \nLastColumn:{1}",firstname,lastName);
Console.ReadLine();
}
If it's not what you want can you explain me for example for "SQL injection - Wikipedia,- the free - encyclopedia - Mozilla Firefox" what's suppose to be returned?
Forgive me for unclean code i'm bored today.
If you don't care about reassembling strings, you could use something like :
var pageparts= Regex.Split(inputWindow.ToString(), " - ");
var firstPart = string.Join(" - ", pageparts.Take(pageparts.Length - 1));
var secondPart = pageparts.Last()
InsertWindowName(firstPart, secondPart);

String formatting in C# to get identical spacing

I've been looking up string formatting and frankly I'm getting confused. This is what I want to do.
I have a "character stats" page (this is a console app), and I want it formatted like this:
=----------------------------------=
= Strength: 24 | Agility: 30 =
= Dexterity: 30 | Stamina: 28 =
= Magic: 12 | Luck: 18 =
=----------------------------------=
I guess basically I'm trying to find out how to make that middle '|' divider be in the same place regardless of how many letters the stat is or how many points the stat is.
Thanks for the input.
Edit: I also want the ending '=' to also be in the same spot.
I learned something new, it seems! As some of the others have mentioned, you can accomplish the same thing using String.Format.
The interpolation strings used in String.Format can also include an optional alignment component.
// index alignment
// v v
String.Format("Hello {0,-10}!", "World");
When this is negative, then the string is left-aligned. When positive, it is right aligned. In both cases, the string is padded correspondingly with whitespace if it is shorter than the specified width (otherwise, the string is just inserted fully).
I believe this is an easier and more readable technique than having to fiddle with String.PadRight.
You can also use String.PadRight (or String.PadLeft). Example:
class Stats {
// Contains properties as you defined ...
}
var stats = new Stats(...);
int leftColWidth = 16;
int rightColWidth = 13;
var sb = new StringBuilder();
sb.AppendLine("=----------------------------------=");
sb.Append("= ");
sb.Append(("Strength: " + stats.Strength.ToString()).PadRight(leftColWidth));
sb.Append(" | ");
sb.Append(("Agility: " + stats.Agility.ToString()).PadRight(rightColWidth));
// And so on.
I used to use this technique a lot back in the 80's doing text based games. Obviously we didn't have string.Format back in those days; but it allows you to visualize the layout in the code.
Pre-format the text as you want it to be laid out, then just use the string.Format() function like so...
string formattedText = #"
=----------------------------------=
= Strength: {0,2} | Agility: {3,2} =
= Dexterity: {1,2} | Stamina: {4,2} =
= Magic: {2,2} | Luck: {5,2} =
=----------------------------------=".Trim();
string output = string.Format(formattedText, 12, 13, 14, 15, 16, 1);
Console.WriteLine(output);
Console.ReadLine();
String.Format("{0,-20}|","Dexterity: 30")
would align the value to the left and pad it to 20 characters. The only problem is that if the parameter is longer than 20 it would not be truncated.
You will need to use a String.PadRight or a String.PadLeft. Do something like this:
Trip_Name1 = Trip_Name1.PadRight(20,' ');
This is what you are looking for I think.

how to place - in a string

I have a string "8329874566".
I want to place - in the string like this "832-98-4566"
Which string function can I use?
I would have done something like this..
string value = "8329874566";
value = value.Insert(6, "-").Insert(3, "-");
You convert it to a number and then format the string.
What I like most about this is it's easier to read/understand what's going on then using a few substring methods.
string str = "832984566";
string val = long.Parse(str).ToString("###-##-####");
There may be a tricky-almost-unreadable regex solution, but this one is pretty readable, and easy.
The first parameter of the .Substring() method is where you start getting the characters, and the second is the number of characters you want to get, and not giving it sets a default as value.length -1 (get chars until the end of the string):
String value = "8329874566";
String Result = value.Substring(0,3) + "-" + value.Substring(3,2) + "-" + value.Substring(6);
--[edit]--
Just noticed you didn't use one of the numbers AT ALL (number '7') in the expected result example you gave, but if you want it, just change the last substring as "5", and if you want the '7' but don't want 5 numbers in the last set, let it like "5,4".
Are you trying to do this like American Social Security numbers? I.e., with a hyphen after the third and and fifth numerals? If so:
string s = "8329874566";
string t = String.Format("{0}-{1}-{2}", s.Substring(0, 3), s.Substring(3, 2), s.Substring(5));
Just out of completeness, a regular expression variant:
Regex.Replace(s, #"(\d{3})(\d{2})(\d{4})", "$1-$2-$3");
I consider the Insert variant to be the cleanest, though.
This works fine, and I think that is more clear:
String value = "8329874566";
value = value.Insert(3, "-").Insert(6, "-");
The console outputs shows this:
832-98-74566
If the hyphens are to go in the same place each time, then you could simply concatenate together the pieces of the orginal string like this:
// 0123456789 <- index
string number = "8329874566";
string new = number.Substring(0, 3) + "-" + number.Substring(3, 2) + "-" + number.Substring(5);
For a general way of making mutable strings, use the StringBuilder class. This allows deletions and insertions to be made before calling ToString to produce the final string.
You could try the following:
string strNumber = "8329874566"
string strNewNumber = strNumber.Substring(0,3) + "-" + strNumber.Substring(4,2) + "-" strNumber.Substring(6)
or something in this manner
string val = "832984566";
string result = String.Format("{0}-{1}-{2}", val.Substring(0,3), val.Substring(3,2), val.Substring(5,4));
var result = string.Concat(value.Substring(0,3), "-", value.Substring(3,2), "-", value.Substring(5,4));
or
var value = "8329874566".Insert(3, "-").Insert(6, "-");
Now how about this for a general solution?
// uglified code to fit within horizontal limits
public static string InsertAtIndices
(this string original, string insertion, params int[] insertionPoints) {
var mutable = new StringBuilder(original);
var validInsertionPoints = insertionPoints
.Distinct()
.Where(i => i >= 0 && i < original.Length)
.OrderByDescending(i => i);
foreach (int insertionPoint in validInsertionPoints)
mutable.Insert(insertionPoint, insertion);
return mutable.ToString();
}
Usage:
string ssn = "832984566".InsertAtIndices("-", 3, 5);
string crazy = "42387542342309856340924803"
.InsertAtIndices(":", 1, 2, 3, 4, 5, 6, 17, 200, -1, -1, 2, 3, 3, 4);
Console.WriteLine(ssn);
Console.WriteLine(crazy);
Output:
832-98-4566
4:2:3:8:7:5:42342309856:340924803
Overkill? Yeah, maybe...
P.S. Yes, I am regex illiterate--something I hope to rectify someday.
A straightforward (but not flexible) approach would be looping over the characters of the string while keeping a counter running. You can then construct a new string character by character. You can add the '-' character after the 3rd and 5th character.
A better approach may be to use a function to insert a single character in the middle of the string at a specific index. String.Insert() would do well. The only thing to pay attention to here is that the string indexes will get off by one with each insert.
EDIT more language-specific as per comments

How to check if a position in a string is empty in c#

I have strings with space seperated values and I would like to pick up from a certain index to another and save it in a variable. The strings are as follows:
John Doe Villa Grazia 323334I
I managed to store the id card (3rd column) by using:
if (line.length > 39)
{
idCard = line.Substring(39, 46);
}
However, if I store the name and address (1st and 2nd columns) with Substring there will be empty spaces since they are not of the same length (unlike the id cards). How can I store these 2 values and removing the unneccasry spaces BUT allowing the spaces between name and surname?
Try this:
string line = " John Doe Villa Grazia 323334I";
string name = line.Substring(02, 16).Trim();
string address = line.Substring(18, 23).Trim();
string id = line.Substring(41, 07).Trim();
var values = line.Split(' ');
string name = values[0] + " " + values[1];
string idCard = values[4];
It will be impossible to do without database lookups on names if there aren't spaces for sure in the previous columns.
Are these actually space separated or are they really fix width columns?
By that I mean do the "columns" start at the same index into the string in each case - from the way you're describing the data is sounds like the later i.e. the ID column is always column 39 for 7 characters.
In which case you need to a) pull the columns using the appropriate substring calls as you're already doing and then, use "string ".Trim() to cut off the spaces.
If the rows, are, as it seems fixed with then you don't want to use Split at all.
How can you even get the ID like that, when everything in front of it is of variable length? If that was used for my name, "David Hedlund 323334I", the ID would start at pos 14, not 39.
Try this more dynamic approach:
var name = str.Substring(0, str.LastIndexOf(" "));
var id = str.Substring(str.LastIndexOf(" ")+1);
Looks like your parsing strategy will cause you a lot of trouble. You shouldn't count on the string's size in order to parse it.
Why not save the data in CSV format (John Doe, Villa Grazia, 323334I)?
that way, you can assume that each "column" will be separated by a comma which will make your parsing efforts easier.
Possible "DOH!" question but are you sure they are spaces and not Tabs? Looks like it "could" be a tab seperated file?
Also for browie points you should use String.Empty instead of ' ' for comparisons, its more localisation and memory friendly apparently.
The first approach would be - as already mentioned - a CSV-like structure with a defined token as the field separator.
The second one would be fixed field lengths so you know the first column goes from char 1 to char 20, the second column from char 21 to char 30, and so on.
There is nothing bad about this concept besides that the human readability may be poor if the columns are filled up to their maximum so no spaces remain between them.
You could write a helper function or class which knows about the field lengths and provides an index-based, fault-tolerant access to the particular column. This function would extract the particular string parts and remove the leading and trailing spaces but leave the spaces in between as they are.
If your values have fixed width, best not split it but use the right indexes in your array.
const string input = "John Doe Villa Grazia 323334I";
var name = input.Substring(0, 15).TrimEnd();
var place = input.Substring(16, 38).TrimEnd();
var cardId = input.Substring(39).TrimEnd();
Assuming your values cannot contain two sequential spaces in them we can maybe use " " (double space" as a separator?
The following code will split your string based on the double space
const string input = "John Doe Villa Grazia 323334I";
var entries = input.Split(new[]{" "}, StringSplitOptions.RemoveEmptyEntries)
.Select(s=>s.Trim()).ToArray();
string name = entries[0];
string place = entries[1];
string idCard = entries[2];

Categories