0

So the task is that I have to code a program that lets the user enter text. After that, I have to filter the text for non-capital letters only and put them in a list. Every letter should only be in the list once. My code's problem is that when I enter a word like "even", the method selects out e and v but the method doesn't skip the second "e" and ends there.

for (int i = 0; i < text.Length; i++)
{
    if (letters.Contains(text[i]) == false && (text[i] >= 'a' && text[i] <= 'z'))
    {
        letters.Add(text[i]);
        Console.WriteLine($"{letters[i]}");
    }
}

I get an index out of range error message.

Michał Turczyn
  • 32,028
  • 14
  • 47
  • 69
Noots
  • 11
  • 1
  • 3
    I think that the Exception is being caused by this line: `Console.WriteLine($"{letters[i]}");` can you replace it by `Console.WriteLine($"{text[i]}");` ? – Tony Sep 22 '19 at 16:51
  • 1
    Your trying to access index that is not available in letters in this `Console.WriteLine($"{letters[i]}")` – hprakash Sep 22 '19 at 16:53

5 Answers5

4

It seems that the Exception is being caused by this line:

Console.WriteLine($"{letters[i]}");

can you replace it by

Console.WriteLine($"{text[i]}");

or you can use a foreach and another variable caller letter:

foreach (var letter in text)
{
    if (letters.Contains(letter) == false && (letter >= 'a' && letter <= 'z'))
    {
        letters.Add(letter);

        Console.WriteLine($"{letter}");
    }
}
Uwe Keim
  • 39,551
  • 56
  • 175
  • 291
Tony
  • 16,527
  • 15
  • 80
  • 134
1

The cause for IndexOutOfRangeException lies in the following lines.

letters.Add(text[i]);
Console.WriteLine($"{letters[i]}");

When i= 3, you are attempting to process character 'n' (assuming your input is 'even'), which doesn't exist in the letters List. You then add it to letters List and print letters[3]. However, at this point, letters only have 2 items('e' and 'v') in it. This is the reason, IndexOutOfRangeException is raised.

What you could do to print the last element added to letters is

Console.WriteLine($"{letters.Last()}");

Or

Console.WriteLine($"{letters[letters.Count - 1]}");

Meanwhile, as juharr pointed out, even printing the text[i] would produce the same result as it is the same character.

Console.WriteLine($"{text[i]}");
Anu Viswan
  • 17,797
  • 2
  • 22
  • 51
  • even better `text[i]` should be the last letter. – juharr Sep 22 '19 at 16:58
  • @juharr yes. But thought it was better to direct OP in finding the last character added to List, even though both are the same. Thought that would help in pointing out the mistake in a better way. – Anu Viswan Sep 22 '19 at 16:59
0

Char class already has extensions that verifies the characters, you can use char.IsLetter(character) and char.IsLower(character) to get a lower case letters only.

here is an example of your code :

string input = "Even if I'm a string, I still like odd numbers like 1, 3, 5 ..etc.";

var text = input.ToCharArray();

List<char> letters = new List<char>();

for(int x =0; x < text.Length; x++)
{
    if (char.IsLetter(text[x]) && char.IsLower(text[x]) && !letters.Contains(text[x]))
    {
        letters.Add(text[x]);
        Console.WriteLine($"{text[x]}");
    }

}
iSR5
  • 3,274
  • 2
  • 14
  • 13
0

There are few things that could help you here:

  1. HashSet
  2. Char.IsLetter

Short example:

            HashSet<char> characters = new HashSet<char>();

            foreach (char c in text)
            {
                if (Char.IsLetter(c))
                {
                    // This will add the character ONLY if it is not there
                    characters.Add(c);
                }
            }

Full console app. If you want to try it create a new console app and replace all the Programs.cs by this:

using System;
using System.Collections.Generic;
using System.Linq;

namespace ConsoleApp1
{
    class Program
    {
        static void Main(string[] args)
        {
            string text = "evEn There";

            // HashSet is like a list, but without duplicates
            HashSet<char> characters = new HashSet<char>();

            // First make all characters lower case
            text = text.ToLower();

            foreach (char c in text)
            {
                if (Char.IsLetter(c))
                {
                    // This will add the character ONLY if it is not there, if not it returns false
                    bool couldBeInserted = characters.Add(c);
                }
            }

            string allCharacters = new String(characters.ToArray());

            //This will print: "evnthr"
            Console.WriteLine(allCharacters);

        }
    }
}
Carlos Garcia
  • 2,771
  • 1
  • 17
  • 32
  • @Noots, Maybe you already knows this, in that case dismiss it :) : In general, if possible you should try to avoid using index because these kind of errors can happen. That is the reason why it is better to use foreach when possible – Carlos Garcia Sep 22 '19 at 18:08
0

You can do it easily with LINQ Where method and ToHashSet method for unique items in array:

var text = "Avene";
var letters = text.Where(ch => char.IsLower(ch)).ToHashSet();
// leters contain now 'e', 'v' and 'n'

To get rid out of that exception you just could do:

Console.WriteLine($"{text[i]}");

which would work just as you want it.

Michał Turczyn
  • 32,028
  • 14
  • 47
  • 69