How do I check for null in a array list and remove them? It keeps giving me a error of "ArgumentOutOfRange was handled" or if I change the SMTPException to just Exception it says "Index out of range". Looking at the debugger and taking a look specifically at mails.Count it gives me Count = 4. I originally gave it 3 emails to check. The last Array is a "". I believe this is causing the problem.
private void button1_Click(object sender, EventArgs e)
{
try
{
if (textBox1.Text == "")
{
textBox3.Text += "[-] Listbox is Empty!!!!\r\n";
return;
}
// textBox1.Text.Split(new string[] { "\n" }, StringSplitOptions.RemoveEmptyEntries);
// Grabs Emails supplied in textbox1 amd then seperates array using '\n'
ArrayList mails = new ArrayList(textBox1.Text.Split('\n'));
// Note: For thought
// IEnumerable<string> myResults = mails.Split('\n').Where<string>(s => !string.IsNullOrEmpty(s));
for (int i = 0; i < mails.Count; i++)
{
// Seperates user & pass to be passed for authentification.
ArrayList mailInfo = new ArrayList(mails[i].ToString().Split(':'));
textBox3.Text += "[+] Checking email format for" + "\r\n" + "[/] " + mails[i] + "\r\n";
// Attach domain name if not attached.
if (!mailInfo[0].ToString().EndsWith("#gmail.com")) mailInfo[0] = mailInfo[0] + "#gmail.com";
// Debug: Check point
//
// Error message:
// Index was out of range. Must be non-negative and less than the size of the collection. Parameter name index.
// mails.Count = 4 when feeding only 3 emails.
//
// Function: Check mail & Password
// error: index out of range
// MessageBox.Show(mailInfo[0].ToString() + "\n\n" + mailInfo[1].ToString());
if (mails[i] == "") throw new ArgumentOutOfRangeException("No Mail", "No more mail to check.");
if (checkAccount(mailInfo[0].ToString(), mailInfo[1].ToString()))
{
textBox3.Text += "[+] Connection Successful! Checking mail.: mailInfo[0].ToString()\r\n";
}
}
}
What am I doing wrong??? Is the null my problem and if so how do I remove it or am I missing something?
To remove items from a list by checking conditions can be tricky. If you're not using a nifty LINQ statement (since you're using an ArrayList im going to assume LINQ is not availiable to you) you will need to use reverse iteration.
If you iterate over a list like this:
foreach(object o in ArrayList)
{
}
Or
for(int i = 0; i < myArray.Count; i++)
{
}
You will run into issues removing items because you'll run out of items (since the list is now smaller than when you defined your for/foreach).
You need to use reverse iteration or store a list of items to remove later.
Example 1: Reverse Iteration
for(int i = myArray.Count - 1; i >= 0; i--)
{
object o = myArray[i];
if (<some condition here>)
myArray.Remove(i);
}
Example 2: Removal List*
ArrayList toRemove = new ArrayList();
foreach(object o in myArray)
{
if(<some condition here>)
toRemove.Add(o);
}
foreach(object o in toRemove)
myarray.Remove(o);
Example 3: LINQ Approach
var cleanEntities = myArray.Where(x => <some condition on x, which is your item>);
Try populating the array like this:
ArrayList mails = new ArrayList(textBox1.Text.Trim().Split('\n'));
That should remove any trailing white space and remove that last item from getting into the array.
I think the empty entry is caused by a carriage return after the last item in your textbox.
It's generally simpler to iterate over one list while building up another. Hard to go wrong that way.
Related
I have created an array like this
string[] directories = new string[15];
And then I want to do something with it like so
for (int i = 0; i < directories.Length; i++) {
//code
}
The user can input as many directories in the array as they want, but if they don't put 14 elements in it, the rest of the array is obviously going to be NULL and the for loop doesn't stop untill it reaches the 14th element. How can I make the loop stop at the last directory in the array and not count the NULL?
I've tried this but it returns the following error: System.NullReferenceException: 'Object reference not set to an instance of an object.'
for (int i = 0; i < directories .Length; i++) {
//code
string directory = directories[i];
if (directory.Equals(null)){
return;
}
// more code
}
Thank you and sorry for the lack of experience and bad English.
Try:.
directories.Count(x => x != null):
If you can always guarantee that after the first null, everything else is null, then the following will work to replace the if statement in your code, and be more efficient than the linq above:
if (directory == null)
break;
The break keywords prevents any more looping in c#.
If you really want to have a set of values in an array followed by a set of nulls, have you considered using a list rather than an array?
If directory is null, you won't be able to call Equals().
Just try directory == null
A quick and easy way to check for directories (if they are directories and the strings aren't null) would be something like this, using Linq:
namespace FooApp {
using System.IO;
using System.Linq;
class MyFoo {
public static void Main(string[] args) {
foreach (var dir in args.Where(a => !string.IsNullOrEmpty(a) && Directory.Exists(a))) {
// Valid directory. Do as you please
}
}
}
}
EDIT:
If you don't want to check if a directory is valid and just want to check if the string is non-null,you can leave Directory.Exists() out.
If you can skip index you can use Linq's Where:
foreach (var dir in directories.Where(x => x != null)
{
}
If you need index of items:
for (int i = 0; i < directories.Length; i++)
{
string directory = directories[i];
if (directory == null)
{
return; // Note that rest of items will be ignored. method will end code outside for loop will not be executed
//break; // exit loop on first null. code outside for loop will be executed
//continue; // use continue to skip null item and process rest of items. code outside for loop will be executed
}
// more code
}
Use a List <string> instead of string[]:
string strDir = "./";
List<string> directories = new List<string>();
directories.Add(strDir);
for (int i = 0; i < directories.Length; i++) {
//code
}
edit: Of course a null-check can be implemented, however in my opinion it is not necessary due to
The user can input as many directories in the array as they want
So I need to count lines in a textbox, to do this i use:
if (subject.Length <= 20)
{
bool moreLines = true;
int onLine = 2;
int count = 0;
while (moreLines)
{
textBody[count] = TextBox_Text.Text.Split('\n')[onLine];
Console.WriteLine("Line saved: " + textBody[count]);
onLine++;
count++;
try
{
if (TextBox_Text.Text.Split('\n')[onLine] == null)
{
}
}
catch (IndexOutOfRangeException)
{
moreLines = false;
}
}
return true;
}
I insert the split strings into textBody[] array but once I approach the last lines where there is no text I want the loop to stop. I tried to do an if statement which checks if the next line is null, and if yes stop the loop. However, I kept getting an IndexOutOfRangeException so I just put the whole thing in a try catch, but I feel like there would be an easier way to do this?
I think you might have over complicated things massively.
The String.Split method have multiple overloads, some of them takes as an argument a member of the StringSplitOptions enum - one of it's members is called None, and the other is called RemoveEmptyEntries - so as far as I understand, all you need is this:
var textBody = TextBox_Text.Text.Split(
new char[] {'\n'},
StringSplitOptions.RemoveEmptyEntries);
An easy way to do this would just to use the following:
TextBox_Text.Text.Split('\n').Length
The Length property returns the length of the array.
so I just used the LineCount property instead and done a compare to the onLine
if (TextBox_Text.LineCount >= onLine)
{
moreLines = false;
}
So I am so fresh into the world of programming, starting new, I decided to start messing around in C# to create simple apps from ideas that come to mind, with this little app, I'm trying to have multiple TextBoxes named d1,d2,d3,d4,etc... the user inserts numbers into the textboxes then clicks button1, which begins the process in the code below creating a new list which contains all of the values of the textboxes and then the list is converted to an array and the array is then converted into an int array, etc....
BUT, when starting the application and I add values to the textboxes and then click button1, it shows 2 error like shows in the //gray code line below
Please help.
private void button1_Click(object sender, EventArgs e)
{
List<string> dodo = new List<string>();
dodo.Add(d1.Text); dodo.Add(d2.Text); dodo.Add(d3.Text); dodo.Add(d4.Text); dodo.Add(d5.Text);
dodo.Add(d6.Text); dodo.Add(d7.Text); dodo.Add(d8.Text); dodo.Add(d9.Text); dodo.Add(d10.Text);
dodo.Add(d11.Text); dodo.Add(d12.Text); dodo.Add(d13.Text); dodo.Add(d14.Text); dodo.Add(d15.Text);
dodo.Add(d16.Text); dodo.Add(d17.Text); dodo.Add(d18.Text); dodo.Add(d19.Text); dodo.Add(d20.Text);
foreach(string numb in dodo)
{
if (numb == "")
numb = "0"; //numb word has a red underline
}
string[] terms = dodo.ToArray();
int[] valv = {};
int x = 0;
for(int i=0;i<=19;i++)
{
valv[i] = int.Parse(terms[i]); //the ; in the end has a red underline and shows "FormatException was unhandled" error
i++;
x = x + valv[i];
}
string myString;
myString = x.ToString();
Result1.Text = myString;
}
you can't change the iteration variable which is numb in your case. Please change in the List container instead
List<string> dodo = new List<string>();
dodo.Add(d1.Text); dodo.Add(d2.Text); dodo.Add(d3.Text); dodo.Add(d4.Text); dodo.Add(d5.Text);
dodo.Add(d6.Text); dodo.Add(d7.Text); dodo.Add(d8.Text); dodo.Add(d9.Text); dodo.Add(d10.Text);
dodo.Add(d11.Text); dodo.Add(d12.Text); dodo.Add(d13.Text); dodo.Add(d14.Text); dodo.Add(d15.Text);
dodo.Add(d16.Text); dodo.Add(d17.Text); dodo.Add(d18.Text); dodo.Add(d19.Text); dodo.Add(d20.Text);
int k = 0;
foreach (string numb in dodo)
{
if (numb == "")
{
//numb = "0"; //numb word has a red underline
dodo[k] = "0";
}
k++;
}
Now your code on parsing into integer won't give any runtime error.
The first line "tells" you that you are not able to assign a new value to the variable which is used as a foreach iteration variable.
The second line, "tells" you that you have string value which is not able to be parsed correctly (e.g. user put string which is not a number). To avoid this you can use Int32.TryParse method instead, which will safely try to parse the given string.
The best and easiest way to achieve what you need is using LINQ methods, here is the example based on few things/assumptions:
Since you are converting empty strings into zeros, you could simply skip those entries from counting
To avoid FormatException, you should use TryParse method instead. Since TryParse method will safely parse the given string, you don't even have to filter empty strings at all (they will be skipped). However, I deliberately left filtering part, to get you a better overview of a solution.
You can use list initializer to make list initialization more readable
Solution:
List<string> dodo = new List<string>()
{
d1.Text, d2.Text //...others
};
int sum = dodo
.Where(item => !String.IsNullOrEmpty(item))
.Sum(item =>
{
if (Int32.TryParse(item, out int parsedItem))
{
return parsedItem;
}
return 0;
});
You can get more familiar with LINQ and used methods on following link
I'm attempting to make a simple realtime search using a streamreader to read from a txt file and search and display the results in a listview, problem is I can only search for 1 letter, so searching for "1" will show me results for everything starting with 1, example search 1 results in "123", but searching for "12" or "123" wont show the same result. Easier explained with this code I've tried.
Edit, text-file I'm reading from has this structure:
123;asd;asd;asd;asd;asd;asd <- example of a row
public static string[] testtt(string sökord)
{
StreamReader asd = new StreamReader("film.txt");
string temp;
string[] xd;
while (asd.Peek() >= 0) // if I can read another row (I.E next row isnt empty)
{
temp = asd.ReadLine();
xd = temp.Split(';');
for (int i = 0; i < xd.Length; i++)
{
// this should check if my searchword is equal to any member of "xd"
// but this is where the problem occurs when the input is more than 1
// character, will post error message from debugger below this code.
if (xd[i].Substring(0, sökord.Length).ToLower() == sökord.ToLower())
return xd;
}
}
return null;
}
private void textBox1_TextChanged(object sender, EventArgs e)
{
try
{
listView1.Items.Clear();
ListViewItem item = new ListViewItem(testtt(textBox1.Text)[0]);
item.SubItems.Add(testtt(textBox1.Text)[1]);
item.SubItems.Add(testtt(textBox1.Text)[2]);
item.SubItems.Add(testtt(textBox1.Text)[3]);
item.SubItems.Add(testtt(textBox1.Text)[4]);
item.SubItems.Add(testtt(textBox1.Text)[5]);
item.SubItems.Add(testtt(textBox1.Text)[6]);
listView1.Items.Add(item);
if (textBox1.Text == "")
listView1.Items.Clear();
}
catch (Exception ex)
{
//MessageBox.Show(ex.Message);
}
}
ex
{"Index and length must refer to a location within the string.\r\nParameter name: length"} System.Exception {System.ArgumentOutOfRangeException}
This is fairly simple. This error will always appear when the line you have read form the stream reader, and you split and store the value in xd. Say the length of xd is n. And the sokord string you entered has say m length. Now when you write:
(xd[i].Substring(0, sökord.Length)
whenever the length of xd that is n is less than m, the Substring function would be trying to make a substring of m letters from only n letters. And hence it gives the error you mentioned.
In any case just a simple check should do ok:
String sString = null;
if(xd[i].length>=sokord.length){
sString = xd[i].SubString(0,sokord.length).toLower();
if(sString.equals(sokord.toLower()))
return xd;
}
Digvijay
PS: To be honest I have written the answer from what best I could understand of what is trying to be done, so the code might be a little offtrack in one scenario. But in any case the error i have described above is 100% correct. So it would be best if you just look into that and follow the track. =)
Still dont know if I understood the question correctly, but wouldnt this be much easier to read and understand?
private String[] FindSome(String searchword)
{
foreach (String s in System.IO.File.ReadLines("myfile.txt"))
{
String[] tmp = s.Split('c');
foreach (String t in tmp)
{
if (t.StartsWith(searchword,StringComparison.CurrentCultureIgnoreCase)) return tmp;
}
}
return null;
}
I have a large string that contains text:
"value 1
value 2
value 3
etc..." //over 100 values
I am trying to create a listbox with it's items based on the values in this string.
I used a try catch as I was getting an argument out of range exception which stopped the error but I can't see any items in the listbox :P
string value = "";
int currentIndexPos = 0;
foreach (System.Text.RegularExpressions.Match m in System.Text.RegularExpressions.Regex.Matches(listStr, "\r\n?"))
{
try
{
value = formatted.Substring(currentIndexPos, m.Index - 1); // -1 so the matched value isn't used.
listBox1.Items.Add(value);
currentIndexPos = m.Index + 1;
}
catch
{
//argument out of range exception
//Index and length must refer to a location within the string. Parameter name: length
}
}
As many have said, just use String.Split. However, there's no need for a foreach loop or resorting to LINQ, just do this:
listBox1.Items.AddRange(String.Split(...));
Try something like this
var values = listStr.Split("\r\n".ToCharArray(), StringSplitOptions.RemoveEmptyEntries);
foreach(string value in values)
{
listBox1.Items.Add(value);
}
Since you are in essence doing a split why not use that function and ignore the index operations.
var lst = String.Split("\r".ToCharArray(),"listStr");
lst.select((x)=>listBox1.Items.Add(x));