How to make this code more functional or 'prettier' - c#

I've been working on a project where I need on a button press that this line gets executed.
if (listView1.SelectedItems[0].SubItems[3].Text == "0") //Checks to see Value
{
listView1.SelectedItems[0].SubItems[3].Text = "1";// If Value is Greater, Increase and Change ListView
questionNumberLabel.Text = listView1.SelectedItems[0].SubItems[3].Text;// Increase and Change Label
}
Now I have this repeated about 10 times with each value increasing by one. But I know that this is ugly, and dysfunctional. As well as conflates the file size. I've tried a few things. Primarily this method.
if (listView1.SelectedItems[0].SubItems[3].Text == "0")
{
for (var i = 1; i < 100;)
{
if (!Int32.TryParse(listView1.SelectedItems[0].SubItems[3].Text, out i))
{
i = 0;
}
i++;
listView1.SelectedItems[0].SubItems[3].Text = i.ToString();
Console.WriteLine(i);
}
}
But instead of just adding one, it does the 100 instances and ends. The reason this is becoming a pain in the *** is because the
listView1.SelectedItems[0].SubItems[3].Text
is just that - it's a string, not an int. That's why I parsed it and tried to run it like that. But it still isn't having the out come I want.
I've also tried this
string listViewItemToChange = listView1.SelectedItems[0].SubItems[3].Text;
Then parsing the string, to make it prettier. It worked like it did before, but still hasn't given me the outcome I want. Which to reiterate is, I'm wanting the String taken from the list view to be changed into an int, used in the for loop, add 1, then restring it and output it on my listView.
Please help :(

You say you want the text from a listview subitem converted to an int which is then used in a loop
so - first your creating your loop variable, i, then in your loop you're assigning to it potentially 3 different values 2 of which are negated by the, i++. None of it makes sense and you shouldn't be manipulating your loop variable like that (unless understand what you're doing).
if you move statements around a little..
int itemsToCheck = 10; // "Now I have this repeated about 10 times "
for (var item = 0; item < itemsToCheck; item++)
{
int i;
if (!Int32.TryParse(listView1.SelectedItems[item].SubItems[3].Text, out i))
{
i = 0;
}
i++;
listView1.SelectedItems[item].SubItems[3].Text = i.ToString();
Console.WriteLine(i);
}
Something along those lines is what you're looking for. I haven't changed what your code does with i, just added a loop count itemsToCheck and used a different loop variable so your loop variable and parsed value are not one in the same which will likely be buggy.

Maybe this give you an idea. You can start using this syntax from C# 7.0
var s = listView1.SelectedItems[0].SubItems[3].Text;
var isNumeric = int.TryParse(s, out int n);
if(isNumeric is true && n > 0){
questionNumberLabel.Text = s;
}
to shortcut more
var s = listView1.SelectedItems[0].SubItems[3].Text;
if(int.TryParse(s, out int n) && n > 0){
questionNumberLabel.Text = s;
}

Related

Apply last non empty string to empty string?

A file is read in. Looks for lines that have a number that beings with an S The lines that do not have an S are maintained. Saves to an array. I am then populating an existing gridview with the same amount of lines.
As a place holder I have set the blank lines to *** This is where I'm stuck. I need the empty strings to be populated with the last non empty string.
So for example if the readout is:
1
2
3
Empty
Empty
Empty
4
Empty
6
I'd want it displayed as:
1
2
3
3
3
3
4
4
6
I can't figure out how to do that. I've been searching all day for examples but can only find ways of grabbing either the first or last number of my array is all. Here is my code.
var sLines = File.ReadAllLines(cboPartProgram.Text)
.Where(s => !s.StartsWith("'"))
.Select(s => new
{
SValue = Regex.Match(s, "(?<=S)[\\d.]*").Value,
})
.ToArray();
string LastSValue = "";
string Value = "";
for (int i = 0; i < sLines.Count(); i++)
{
if (sLines[i].SValue == "")
{
LastSValue = "***";
Value = LastSValue;
}
else
{
Value = (sLines[i].SValue);
}
}
Ok I think I got it.
for (int i = 0; i < sLines.Length; i++)
{
if (sLines[i].SValue == "" && i > 0)
{
foreach (var empt in sLines[i].SValue)
{
LastSValue = sLines[i - 1].SValue;
Value = LastSValue;
}
}
else
{
Value = (sLines[i].SValue);
}
On a side note, when I copy my code I use the code option above to format it, but I notice someone always has to correct my spacing. Its copied straight from the IDE but there are always spaced each line that I guess shouldn't be. Is there a different way I should do it?
UPDATE
If I should ask this as a new question let me know, but it's so dependent on this that I thought I should keep it here.
Using the code I posted above that does what I needed it too. I've been trying to edit this so that if there is NO previous number, so for example if there if line 1 has no number but the rest do, then just apply the string "NA" otherwise still do what the code above does to the rest of the lines.
I guess maybe the best way would be to just take the results from the above code, and if there are any empty spaces left, apply "NA" but I can't figure it out.
In your example, you just need to take the value of the row before to fill the current value. Something like the following :
for (int i = 0; i < sLines.Length; i++)
{
if (sLines[i].SValue == "" && i > 0)
{
sLines[i].SValue = sLines[i-1].SValue;
}
else
{
sLines[i].SValue = sLines[i].SValue;
}
}
Your example has one more issue but currently I'll focus only on gathering the "last non empty" string.
If you look at your example you can spot few things that could potentially help you finding solution. These are for loop and reference to original list that stays intact.
For my example I'll use Linq because it will be much easier.
First of all I'll copy all from before for loop ( if that makes sense :D ) :
var sLines = File.ReadAllLines(cboPartProgram.Text)
.Where(s => !s.StartsWith("'"))
.Select(s => new
{
SValue = Regex.Match(s, "(?<=S)[\\d.]*").Value,
})
.ToArray();
string LastSValue = "";
string Value = "";
Just because it's okay and will work for now.
With your for loop I'll make modifications :
for (int i = 0; i < sLines.Count(); i++)
{
// `i` is representing current "index" of processed "word"
// we can use this to find last "valid" element
// string notEmpty = sLines.Take(i).LastOrDefault(word => !string.IsNullOrEmpty(word));
// but since you want to assign this to `Value` and there can be not empty string at `i` index
// we can make it in one line :
Value = string.IsNullOrEmpty(sLines[i]) ? sLines.Take(i).LastOrDefault(word => !string.IsNullOrEmpty(word)) : sLines[i].SValue;
// instead of your previous logic :
//if (sLines[i].SValue == "")
//{
// LastSValue = "***";
// Value = LastSValue;
//}
//else
//{
// Value = (sLines[i].SValue);
//}
}
Another problem which I think you'll face is that first value ( judging by the input ) can also be empty. Which will throw exception in my example. This will also be impossible to fit this kind of solution because there's no previous value ( at all ).
From what I understand, if you want to store the result in Value and do something else with it inside the loop (instead of changing it in the array), what you probably want is this:
for (int i = 0; i < sLines.Count(); i++)
{
if (sLines[i].SValue == "")
{
Value = LastSValue;
}
else
{
Value = (sLines[i].SValue);
LastSValue = Value;
}
// use Value
}
I would also suggest using sLines.Length instead of Count(), which is made for sequences where the length isn't known in advance - it's supposed to literally count the elements one by one. In this case it would probably be optimized but if you know you're dealing with an array, it's a good idea to ask for the length directly.
EDIT:
To get "NA" if there's no previous number, just initialize LastSValue to this value before the loop:
string LastSValue = "NA";
That way, if Value is empty and there was not LastSValue set before, it will still be "NA".
EDIT2:
A solution similar to the one from #Cubi, to change it in place:
for (int i = 0; i < sLines.Length; i++)
{
if (sLines[i].SValue == "")
sLines[i].SValue = i > 0 ? sLines[i-1].SValue : "NA";
}

Comparing char arrays method

I've been playing space engineers which has been epic since they added in-game programming, I'm trying to make a gps auto-pilot navigation script and have to get the block positions finding the blocks by name looking for a smaller string within their bigger string name. I wrote this method to find a small string (word) in a larger string (name of the block):
bool contains(string text, string wordInText)
{
char[] chText = text.ToCharArray();
char[] chWord = wordInText.ToCharArray();
int index = 0;
for(int i = 0 ; i < chText.Length - chWord.Length ; i++)
for(int j = 0; j < chWord.Length;j++,index++)
if (chWord[0] == chText[i])
index = i;
else if (chWord[j] == chText[index]){}
else if (index == chWord.Length-1)
return true;
else break;
return false;
}
Am I even doing it right, should I be doing it another shorter way?
This is simple with .Contains() which returns a bool.
text.Contains(wordInText);
If you simply want to check if a string contains an other string, then you can use string.Contains, the string class already provides a bunch of methods for string operations.
As already mentioned, the String class already has a Contains method that should give you what you need.
That said, your code doesn't work. I can see where you're going with it, but it's just not going to work. Stepping through it in a proper dev environment would show you why, but since this is more in the way of a script that's probably not an option.
So... the basic idea is to iterate through the string you're searching in, looking for matches against the string your searching. Your outer for statement looks fine for this, but your inner statements are a bit messed up.
Firstly, you're doing the first character check repeatedly. It's wasteful, and misplaced. Do it once per iteration of the outer loop.
Second, your exit condition is going to fire when the first character of wordInText matches the characters at index wordInText.Length in text which is not apparently what you want.
In fact you're all tripped up over the index variable. It isn't actually useful, so I'd drop it completely.
Here's a similar piece of code that should work. It is still much slower than the library String.Compare method, but hopefully it shows you how you might achieve the same thing.
for (int i = 0; i <= chText.Length - chWord.Length; i++)
{
if (chText[i] == chWord[0])
{
int j;
for (j = 0; j < chWord.Length; j++)
{
if (chText[i + j] != chWord[j])
break;
}
if (j == chWord.Length)
return true;
}
}
return false;

While Looping an Array

I'm trying to understand a book from Don Gosselin on ASP.NET Programming with Visual C#. To solve it I just simply make it to work by adhering to while loops: one while loop is to assign a number to an array element, the other while loop is to display that array. Total array count displays 1 through 100. This should have worked but didn't. Visual Studio 2013 debugger for some reason assigns count = 100, that's why it's failing.
<%
int count = 0;
int[] numbers = new int[100];
while (count <= 100)
{
numbers[count] = count;
++count;
}
while (count <= 100)
{
Response.Write(numbers[count] + "<br />");
++count;
}
%>
You should set count to 0 after first while loop:
int count = 0;
int[] numbers = new int[100];
while (count <= 100)
{
numbers[count] = count;
++count;
}
count = 0;
while (count <= 100)
{
Response.Write(numbers[count] + "<br />");
++count;
}
You need to reset the count to 0 before you attempt the next while statement. Currently, the first loop ends when it reaches a count equal to 101. WHen you proceed to the next while, the count is 101 so the loop automatically ends. Just set count = 0; before the second while loop.
This seems like a very convoluted and unrealistic way of using while loops and arrays. In order to understand it better, it may be worth thinking about it per step.
var i = 0;
while (i < 100)
{
Response.Write(++i + "<br />");
}
The first important distinction is between i++ and ++i. The former utilises the value, and then increments by one; the latter, increments the number and then utilises the value.
In C#, you should really be working with Collections, rather than Arrays. Arrays are zero-indexed, and are renowned for causing serious errors, including exposing potential exploits. Being statically allocated, there is no failsafe when attempting to access indicies outside of the bounds of the Array. Collections, on the other hand, are (for the most part) one-indexed, dynamically allocated, and provide fallbacks when accessing indicies. The most commonly used Collection is a List.
var i = 1;
var list = new List<int>();
while (i <= 100)
{
list.Add(i++);
}
For the second while loop, it's not really suitable to use a while loop here, for any practical example. The excercise is forcing while loops where they are not needed. In this instance, the aim is to iterate through each element in the array (List) and dump its contents to the screen. Because we want to perform an action for each element, a while loop may cause issues. If the array has less than 100 elements, the program will crash, if the array has more than 100 elements, we'll miss some of them. By using a foreach loop, instead of a while, we can eliminate these potential errors.
foreach (var num in list)
{
Response.Write(num + "<br />");
}
Now, I realise that the excercise is about while loops, however, it is teaching you to use them in the wrong way. A much better way - and how you'll most often use them - is to perform an action until a particular condition is met, rather than for simple iteration. By this, I mean, a condition is set to false, then inside the while loop, we manipulate a variable, test the condition, and if it's still false, we go round again. The most common example of this is to work out factorials of numbers.
var num = 5;
var factorial = 1;
while (counter > 1)
{
factorial *= num--;
}
Response.Write(String.Format("{0}! = {1}", input, factorial));
The other main way in which while loops are used is to force an infinite loop, unless a break condition is met. I'll show a very arbitrary use of this here, but a real world example would be the loop() method in Arduino C coding, or a HTTP Listener that constantly repeats the same procedures, until stopped.
var stop = 13;
Response.Write("Pick a number between 1 and 100...<br /><br />");
while (true)
{
var num = new Random().Next(1, 101);
Response.Write(num + " ..... ");
if (num == stop) break;
Response.Write("You got lucky!<br />");
}
Response.Write("Unlucky for you!);
The best way to learn these things is to practice them. Pick a task and find out just how many ways there are to complete it. There is one last important distinction to mention though. a while loop tests the condition at the beginning of the loop. A do while loop, tests the condition at the end.
while(false)
{
// This code will never be run.
}
Compared to:
do
{
// This code will be run once only.
}
while(false)
As a final thought, here's how I'd write the original code (using a LINQ foreach loop):
var numbers = new List<int>();
for (var count = 1; count <= 100; count++)
{
numbers.Add(count);
}
numbers.ForEach(num => Response.Write(num + "<br />")));

How to stop While Loop in c#

I have an array that are having some different values. one array called saveforRR this should work like whenever i have any value that less that 0, it will be removed from the array. Also, the values in the array must reduced by 1. I do not know how many iterations are going to take to make my array Length =0. so I used while loop. However, when i run the code my loop stops in this line fortheaddingvalue = (int)saveforRR[w]; //It says her that my array is out from boundaries, which i do not know how? How can I fix this problem? can you advise me please?
//Create variables and set up the arrays
int value = 7;
int [] saveforRR = {1,2,3,4,5,15,86};
//start get the values reduced
int fortheaddingvalue;
int w = 0;
//Run the while loop to reduce the value in the saveforRR array.
while(saveforRRName.Length !=0 && saveforRR.Length !=0)
{
fortheaddingvalue = (int)saveforRR[w]; //It says her that my array is out from boundaries, which i do not know how?
fortheaddingvalue = fortheaddingvalue - 1;
if (fortheaddingvalue > 0)
{
saveforRR[w] = fortheaddingvalue;
txtOutput.Text += "\r\n" +saveforRR[w] + " this is the value";
}
else
{
Array.Clear(saveforRR, w, 1);
txtOutput.Text += "\r\n" + saveforRR[w] + "this is the value Remover";
}
w++;
}
The length of your array will never be zero. The Clear method doesn't remove items from the array.
An array can't be resized. You can use the Resize method to get the same effect, as that will create a new array with a different size, and copy the items to it. That's however not efficient, you should use a List<int> instead, as that supports actual resizing.
It seems that nobody mentioned the break-statement. You can use it break out of any loop:
while(true)
{
// Eternal loop here...
// Break out
break;
}
Read more about it here: break
Other ways to exit loop include for example goto, return or setting the loop expression not to match

Dynamic UI, Loop

I created a dynamic UI that shows each module that the user has added to their selection and all the assessments for that module underneath the module name,
All data is saved in array lists - including objects as textBoxes and labels.
Here's what it looks like:
http://www.4shared.com/photo/fullsize/Ja3jHpRJ/screen1.html
Then the user should enter their marks for each assessments
And the Calculate button should calculate their overall mark for each module
At this stage I am just adding the marks together.
The program works fine when there's only one module added, but when there are more modules it seems to think that a TextBox is empty, even though i fill them all with numbers.
here is my code
private void calculateButton_Click(object sender, EventArgs e)
{
int modLength = dat.ModuleTitle.Count;
int modAsses = 0;
int loopCount = 0;
for (int i = 0; i < modLength; i++)
{
int total = 0;
if ((textboxComputer[loopCount] as TextBox).Text == "")
{
Console.WriteLine("!!!!!");
}
else
{
modAsses = int.Parse(dat.ModuleAssessNum[i].ToString());
for (int y = 0; y < modAsses; y++)
{
total = total + int.Parse((textboxComputer[loopCount] as TextBox).Text.ToString());
loopCount = loopCount + 1;
}
Console.WriteLine(total);
}
}
}
When i add two or more modules it displays the "!!!!!" message, but calculates the mark for the first module added.
here's some output
http://www.4shared.com/photo/fullsize/PlY29BMQ/screen2.html
You need to make sure that the code that creates the extra dynamic elements on screen is being called as part of the page load, so that then the viewstate is inserted back into the elements and can be read back out by your code.
there is something wrong with your code, probably a lot wrong(except the names of your variables).
Take a look at your loopCount variable - you will only conditionally change it in your loop but you always use it at the start of the loop(where you do textboxComputer[loopCount]).
So what's the expected behavior of that? The first time you get in to the loop if you go to your 'else' part you may print the total as you say but you also change the loopCount variable, once you get to the Console.WriteLine("!!!!!"); you never change it again - so your iterations will behave the same.

Categories

Resources