Populating a TextBox from a text file - c#

Im trying to get specific lines from a file and put them in a another string or maybe if we can put it in anothe textbox it wont be a prob :P
string[] msglines;
msglines = System.IO.File.ReadAllLines(#"C:\\Users\xA\Desktop\MESSAGES.txt");
for (int x = 0; x < msglines.Length; x++)
{
this.textBox5.Text = msglines[c];
c = c + 2;
}
I get a :
Index was outside the bounds of the array.

If you want to get every second line.
Change your loop to
//Odd Lines
for (int x = 0; x < msglines.Length; x = x + 2)
{
this.textBox5.Text += msglines[x];
}
//Even Lines
for (int x = 1; x < msglines.Length; x = x + 2)
{
this.textBox5.Text += msglines[x];
}
As was pointed out in the comments, you can shorten x = x + 2 to x += 2
And in the interest of LinqY Goodness...
//ODDS
msgLines
.Where((str, index) => index % 2 == 0)
.ToList()
.ForEach(str => textBox1.Text += String.Format("{0}\r\n", str));
//EVENS
msgLines
.Where((str, index) => index % 2 == 1)
.ToList()
.ForEach(str => textBox1.Text += String.Format("{0}\r\n", str));

your loop is controlled by x, but you're indexing by c [hence you need logic to prevent c getting greater than size of the array]

Because you are increasing the line index (c) by 2 each time; just use x:
this.textBox5.Text = msglines[x];
Of course, from a loop this will result in just the last line being shown. What line is it you actually want to show?
Edit re comment; in which case, simply:
StringBuilder sb = new StringBuilder();
for (int x = 1; x < msglines.Length; x+=2)
{
sb.AppendLine(msglines[x]);
}
this.textBox5.Text = sb.ToString();

In your for loop, you are using c. You need to use x. Could I suggest that you have a look at the reference for for.
Try this instead...
string[] msglines;
msglines = System.IO.File.ReadAllLines(#"C:\\Users\xA\Desktop\MESSAGES.txt");
for (int x = 0; x < msglines.Length; x++)
{
this.textBox5.Text = msglines[x];
}

Then you should use X as an index, with a step of 2, instead of 1.

Try this
string[] msglines;
msglines = System.IO.File.ReadAllLines(#"C:\Users\xA\Desktop\MESSAGES.txt");
for (int x = 0; x < msglines.Length; x++)
{
this.textBox5.Text = msglines[x++];
}

You say you want all odd-numbered lines in the TextBox, but your loop will only show the last line, as you overwrite the contents on each pass.
To show all odd-numbered lines, separated by line breaks:
string lineSep = "";
for (int x = 0; x < msglines.Length; x += 2)
{
this.textBox5.Text += lineSep + msglines[x];
lineSep = "\r\n";
}

For simplicity I'll use an example of taking every other character from a string, but the case of taking every other line from an array of strings is analogous.
Lets take "Hello" as an example for your msglines string
(source: javabat.com)
and let us say that your global variable c i initialized to 0 before you enter the for loop. Your msglines.Lenght will be 5. In the the fourth iteration through the loop (x == 3) you are going to try to access msglines[6], which is outside of the bounds of the array, hence the error.
You probably wanted something along the lines of
int x = 0;
while(x <= msglines.Lenght){
this.textBox5.Text += msglines[x];
x = x + 2;
}
or
for(x=0; x <= msglines.Lenght ; x+=2){
this.textBox5.Text += msglines[x];
}
To get the odd lines you would start with x initialized to 1.
As for which of the two fully equivalent versions above to use, I would suggest using the one that is more readable to you. In my experience that is always the better choice.

You have a double backslash in the ReadAllLines() call, causing it to fail opening the file.
Also, you are using c as an array index, it looks like you want x

The code i wrote is exactly how I want it to be.....
I actually want every odd line from my file to be sent to the textbox.and yeah P.S C initializes from 1

Besides the already mentioned indexing problems of c versus x, you are also overwriting textBox5.Text on every iteration, so you'll only ever see the last line. It seems somehow unlikely to be intended behaviour. You might want something like this instead:
this.textBox5.Text += msglines[x]; // note x instead of c
Or if you really want everything and the +2 was a typo in itself you could do this without any loop:
this.textBox5.Text = String.Join( "\n", msglines );

The following function will return an IEnumerable that gives the odd numbered lines in a file:
private IEnumerable<string> GetOddLines(string fileName)
{
string[] lines = File.ReadAllLines(fileName);
IEnumerator allLines = lines.GetEnumerator();
while (allLines.MoveNext())
{
yield return (string)allLines.Current;
if (!allLines.MoveNext())
{
break;
}
}
}
If you want the even numbered lines, just add a call to allLines.MoveNext() before the while loop.

You need to loop the array with Length -1. Array of 45 Length will only index to 44.

Related

Trouble whilst creating a while loop

So i was given this question below to answer and I initially created a for loop to do this which worked fine but i was told i could also do it in a while loop which is what i am trying now however i am not sure where I've gone wrong in my code below as i'm getting a indexoutofrange exception.
Question 4 -
Write a piece of software that compares two strings and outputs the number of characters in the same position.
E.g. “helloworld” and “worldhello” would output 2 as there are two l’s in the same positions
compare the strings below to calculate your answer.
String1 - "helloworld"
String2 - "worldhello"
My for loop code which works perfectly
string string1 = "helloworld";
string string2 = "worldhello";
int list = 0;
for (int i = 0; i < string1.Length; i++)
{
if (string1[i] == string2[i])
{
list = list + 1;
}
}
Console.WriteLine(list);
Now this is my while loop code which isn't working
string string1 = "helloworld";
string string2 = "worldhello";
int i = 0;
int total = 0;
while (i < string1.Length)
{
i++;
if (string1[i] == string2[i])
{
total = total + 1;
}
}
You are nearly there!
The third part of the for loop (i++) will run at the end of each iteration, so you should not put i++; as the first statement in the while loop version. You should put it as the last statement:
while (i < string1.Length)
{
if (string1[i] == string2[i])
{
total = total + 1;
}
i++;
}
In general, a for loop of the form:
for (x ; y ; z) { w; }
can be written as a while loop like this:
x;
while (y) {
w;
z;
}

How to add a line feed after each digit that came before a letter

i have a string like that:
String s ="6,44 6,35 +0,63asd 4,27fgh 4,14 45,6 +777,4cvbvc";
I want to insert a line feed into those points between every digit and letter like: +0,63(here must be a line break)asd. I wrote the code below but it gave length changed error. Maybe it may occur either because of my program's features or c#'s feature. But i need to stay stick to the features. So can you recommend me a solution in those limits? The code below could not solve it and i could not find any other way.
int k = s.Length;
for (int i = 0; i < k; i++)
if (char.IsDigit(s[i - 1]) && char.IsLetter(s[i]))
s = s.Insert(i, Strings.Chr(10).ToString());
Thank you for your help. Cheers.
You need to start the cycle from 1 or you will get an exception because when i=0 s[i-1] becomes s[-1].
Now your program should work but i would suggest you to use a stringbuilder because string.Insert creates a new string instance everytime you call it making your program very slow if the input string is long.
Also if you are in a Windows environment a line break is represented by "\r\n" wich is Environment.NewLine in c#.
So your code should be something like this:
StringBuilder builder=new StringBuilder(s);
int offset=0;
for (int i = 1; i < s.Length; i++)
{
if (char.IsDigit(s[i - 1]) && char.IsLetter(s[i]))
{
builder.Insert(i+offset, Environment.NewLine);
//every time you add a line break you need to increment the offset
offset+=Environment.NewLine.Length;
}
}
s=builder.ToString();
please try this code
String myString="";
int k = s.Length;
for (int i = 0; i < k; i++)
if (char.IsDigit(s[i - 1]) && char.IsLetter(s[i]))
myString = myString + Strings.Chr(10).ToString() + s.Substring(i,k-i);
s=myString;
Your solution hase one mistake - loop index range, you should start with 1, because you have expression (i-1)
here is solution
https://dotnetfiddle.net/FMvpqj
You can do like this:
int k = s.Length;
int i= 1;
while (i < s.Length)
{
if ((char.IsDigit(s[i - 1]) && char.IsLetter(s[i])) ||
(char.IsLetter(s[i-1]) && char.IsDigit(s[i])))
{
s = s.Insert(i, ((char)10).ToString());
i++;
}
i++;
}

Nested Loop function taking minuets to run, anyway to improve efficiency?

I knew the function would include a lot of data processing, but I didn't think it would end up taking minuets to process.
The function in question is fed a jagged 2D array which is made up of Paragraphs > Sentences this is made from a text file fed by the user so can be massive. It takes this array and compares every sentence to each other and saves a score between each sentence which is the number of common words.
This takes forever and I honestly didn't think it would.
My main test text is only 181 sentences long, but this translates to 32.7 thousand values scored in a 2D array.
This matrix of values is then used to calculate and select the most "relevant" sentences from each paragraph, and other things.
The 181 sentence text takes 1min 15seconds to process, a text of only 70 sentences takes 35 seconds, but this is based on number of sentences not words, but it gives you an idea. I dread to think how long it would take on an actual document.
The function in question:
protected void Intersection2DArray()
{
mainSentenceCoord = -1;
for (int x1 = 0; x1 < results.Length; x1++)
{
for (int x2 = 0; x2 < results[x1].Length; x2++)
{
var mainSentencesWords = wordSplit(results[x1][x2]);
secondarySentenceCoord = -1;
mainSentenceCoord++;
for (int y1 = 0; y1 < results.Length; y1++)
{
for (int y2 = 0; y2 < results[y1].Length; y2++)
{
var secondarySentencesWords = wordSplit(results[y1][y2]);
int commonElements = mainSentencesWords.Intersect(secondarySentencesWords).ToList().Count();
secondarySentenceCoord++;
intersectionArray[mainSentenceCoord, secondarySentenceCoord] = commonElements;
}
}
}
}
}
The wordSplit function:
protected List<String> wordSplit(string sentence)
{
var symbols = "£$€#&%+-.";
var punctuationsChars = Enumerable.Range(char.MinValue, char.MaxValue - char.MinValue)
.Select(i => (char)i)
.Where(c => char.IsPunctuation(c))
.Except(symbols)
.ToArray();
var words = sentence.Split(punctuationsChars)
.SelectMany(x => x.Split())
.Where(x => !(x.Length == 1 && symbols.Contains(x[0])))
.Distinct()
.ToList();
return words;
}
I initially wanted to do this split using one Regex line, but wouldn't figure it out, that may make it faster.
This loops through to select each sentence against each other, this is best I could come up. I'm fine with doing a total overall if it will drastically increase speed.
Edit: Using Moby Disk suggestion heres my new instant code:
Word Split function which is called once now and returns a List of List
public List<List<string>> createWordList()
{
List<List<string>> wordList = new List<List<string>>();
var symbols = "£$€#&%+-.";
var punctuationsChars = Enumerable.Range(char.MinValue, char.MaxValue - char.MinValue)
.Select(i => (char)i)
.Where(c => char.IsPunctuation(c))
.Except(symbols)
.ToArray();
for (int x1 = 0; x1 < results.Length; x1++)
{
for (int x2 = 0; x2 < results[x1].Length; x2++)
{
var words = results[x1][x2].Split(punctuationsChars)
.SelectMany(x => x.Split())
.Where(x => !(x.Length == 1 && symbols.Contains(x[0])))
.Distinct()
.ToList();
wordList.Add(words);
}
}
return wordList;
}
And the now super slim Intersection Function
protected void intersectionMatrix()
{
List<List<string>> wordList = createWordList();
mainSentenceCoord = -1;
for (var x = 0; x < wordList.Count; x++)
{
secondarySentenceCoord = -1;
mainSentenceCoord++;
for (var y = 0; y < wordList.Count; y++)
{
secondarySentenceCoord++;
intersectionArray[mainSentenceCoord, secondarySentenceCoord] = wordList[x].Intersect(wordList[y]).Count();
}
}
}
See update at the end:
There is some "low-hanging fruit" here that could speed it up a lot with out changing the algorithm itself:
wordSplit() recalculates "punctuationsChars" each time it is called. Do that once up front.
You are calling wordSplit() for the same sentence a N^2 number of times instead of N number of times since it is in both the outer (x1,x2) loop and the inner (y1,y2) loop. You only need to split 181 sentences, not 181^2 number of sentences. So instead, loop through results, call wordSplit once on each sentence, and store that result. If that takes up too much memory, look into memoization (http://en.wikipedia.org/wiki/Memoization) although I think you should be okay since it will only result in about 1 more copy of the text.
You don't need the ToList() after the Intersect(). That creates a list you don't use.
I'm confused as to the values of mainSentenceCoord and secondarySentenceCoord. What are the dimensions of the resulting intersectionArray?
OMG! #1 is it! That sped this up by a factor of 80x. Look at this line:
Enumerable.Range(char.MinValue, char.MaxValue - char.MinValue)
char.MaxValue is 65536. So if N=181, you are looping 181 x 181 x 65536! I just ran the profiler to confirm it: 98.4% of the CPU time is spent in the ToArray() calls in wordSplit.

XNA C# .txt file Tile Engine

I'm not very experienced when it comes to using .txt files in XNA and therefore i need some help.
I'm tring to make a Tile Engine read and put information depending on what number is in the .txt document. It looks something like this:
1,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1
1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1 etc
Now, this document contains 50 characters in X (25 without [ , ]) and has 15 lines in Y. The problem is that it only reads the first line in Y and not the other 14 remaining ones in Y, which is causing it to crash.
Here is the code:
public void LoadMap(string MapName)
{
using (StreamReader streamReader = new StreamReader("Content/" + MapName + ".txt"))
{
do
{
string line = streamReader.ReadLine();
string[] numbers = line.Split(',');
int temp = 0;
for (int y = 0; y < loopY; y++)
{
for (int x = 0; x < loopX; x++)
{
Blocks[y, x] = new Block();
//Crashes here when temp reaches 25
if (int.Parse(numbers[temp]) == 1)
Blocks[y, x].color = Color.Blue;
else if (int.Parse(numbers[temp]) == 2)
Blocks[y, x].color = Color.Violet;
else
Blocks[y, x].color = Color.White;
temp++;
}
}
} while (!streamReader.EndOfStream);
}
}
Based on your reply to my question:
"Index was outside the bounds of the array." Yes i checked it loopX is 25 and Numbers is 25
numbers[] is zero-indexed, so the upper bounds is numbers[24]. If loopX is 25 then, yes, you'll see an exception.
You're iterating through loopX and then loopY and incrementing temp every time. You'll either need to set temp back to 0 after each loopX iteration, or just use the numbers array instead of the loop values instead.
I suggest changing your loop to use numbers instead:
for (int x = 0; x < numbers.Length; x++)
And then, to use your existing code, check value using:
if (int.Parse(numbers[x]) == 1)
EDIT: This is what I was trying to explain:
using (StreamReader streamReader = new StreamReader("Content/" + MapName + ".txt"))
{
int y = 0;
do
{
string line = streamReader.ReadLine();
string[] numbers = line.Split(',');
for (int x = 0; x < numbers.Length; x++)
{
Blocks[y, x] = new Block();
if (int.Parse(numbers[x]) == 1)
Blocks[y, x].color = Color.Blue;
else if (int.Parse(numbers[x]) == 2)
Blocks[y, x].color = Color.Violet;
else
Blocks[y, x].color = Color.White;
}
y++;
} while (!streamReader.EndOfStream);
}
I see following things in your code, which seem suspicious to say the least:
If your temp >= numbers.Length, than you will get "Index was outside the bounds of the array".
If that happens after reading the first line, of course you will not read any further lines, because you got an exception and it will break.
You are overwriting your Blocks with every new line: If you read the first line and get into x and y loops, at the very first iteration of x and y, they will both be 0. So you write Blocks[0,0] = new Block(). After you read the next line, you get again into x and y loops. They start again with 0, so at the very first iteration of x and y while processing the second line you will write Blocks[0,0] = new Block(). Which will in fact overwrite the Block you wrote previously on index [0,0] during the handling of the first line. The same problem exists for all other combinations of x and y.
Debug, step-through and watch variables. That will help you understand what is going on.

How can i check the index length in long[] array?

For example i have a long[] x
And im doing:
for (int i=0; i<x.length;x--)
{
}
I know that in x for example i have 30 indexs cells.
How can i loop over the cells(indexs) in the x array and find on each cell the length of it and also to get/show the numbers in each cell.
If in x[0] there is 232
And in x[1] there is 21
And so on...
I want to display 232,21,....etc
And then i want to check that if x[i].length is above 0 do...
But there is no x[i].length
So how do i do it ?
I did:
public long GetHistogramMaximum(long[] histogram)
{
long result = 0;
long count = 0;
for (int i = 0; i < histogram.Length; i++)
{
if (histogram[i] > 0)
{
MessageBox.Show(histogram[i].ToString());
break;
}
}
return result;
}
And its working but each time its showing me the number twice why the messagebox is working twice each time ?
If in the first array the number is 33454 then i see the messagebox once and then once again. Whats wrong here ? I want it to show me the number only once each time.
Its like repeating each number and show it once and then once again and only then moving to the next one.
EDIT **
Maybe the problem its showing the number twice each time have something to do with the scroll event im using ?
void trackBar1_Scroll(object sender, EventArgs e)
{
myTrackPanelss1.trackBar1.Minimum = 0;
myTrackPanelss1.trackBar1.Maximum = counter - 1;//list_of_histograms.Count-1;
long[] tt = list_of_histograms[myTrackPanelss1.trackBar1.Value];
histogramControl1.DrawHistogram(tt);
long res = GetTopLumAmount(tt, 1000);
long max = GetHistogramMaximum(tt);
if (res > -1)
label24.Text = (res / 1000.0).ToString();
setpicture(myTrackPanelss1.trackBar1.Value);
this.pictureBox1.Refresh();
}
For some reason its getting to the scroll and do everything here again. Twice in a row.
What can be the problem ?
A long[] basically holds a number of long values. Doing x[i].length is invalid, because a long does not have a property length. What is it that you are trying to achieve?
long[] x = {1,2,3} ;
x.length; //this is valid because you are querying the length / count of the array
x[0].length; //this is invalid because 1 does not have a property length
EDIT
Your loop counter will be the index. So,
for (int i =0; i < x.Length; i++)
{
//check for maximum, when you find it
Console.WriteLine("The maximum value is " + x[i]);
Console.WriteLine("The maximum value is present at index " + i);
}
As Michael says, you can find the length of the array via x.Length. In C#, x.Length (where x is an array) will return a 32-bit integer that represents the total number of elements across all dimensions. You only have a 1D array here, so that should be sufficient for what you're trying to achieve.
If you're also after the value stored in the array, the value is called as:
x[i];
So, in an example:
for ( int i = 0; i < x.Length; i++)
{
Console.WriteLine(x[i]);
}
... would display the value in the array in your console.
Is that what you were asking?
Here is how to do something based on the values in the array.:
for (int i=0; i < x.Length; i++)
{
// print the number to the screen.
Console.WriteLine(x[i]);
if (x[i] > 0) {
// do something else.
}
}
I'm not sure what you meant by x--, but that's probably wrong from your description.
You could cast it to a string and get the length property.
x[i].ToString().Length
Although if you want to check if the length is above zero, then surely just the presence of a value proves this?
Your function has a terrible problem:
public long GetHistogramMaximum(long[] histogram)
{
long result = 0;
long count = 0;
for (int i = 0; i < histogram.Length; i++)
{
if (histogram[i] > 0)
{
MessageBox.Show(histogram[i].ToString());
break;
}
}
return result;
}
This way, you check the values in your array.
When i=0, it checks x[i]. So, 33454 (the value you gave in x[0]) is greater than 0, it shows the number and "break;", so it stops the "for" and do what's next: it returns the result variable that is never modified.
So variables result and count are useless in your code.
Rewrite with something that way for getting the maximum in your array:
public long GetHistogramMaximum(long[] histogram)
{
long result = 0;
for (int i = 0; i < histogram.Length; i++)
{
if (histogram[i] > result)
{
MessageBox.Show(string.Format("{0} is greater than {1}", histogram[i], result);
result = histogram[i];
}
}
return result;
}

Categories