Метод Equals () не распознает похожие / одинаковые символы при сравнении - PullRequest
1 голос
/ 03 мая 2019

Почему сравнение символов с .Equals всегда возвращает false?

char letter = 'a';
Console.WriteLine(letter.Equals("a")); // false

В общем, я пытаюсь написать переводчик с английского на азбуку Морзе. Я столкнулся с проблемой сравнения значений char, показанных выше. Я начал с foreach, чтобы проанализировать все символы из ввода ReadLine(), используя метод WriteLine(), все символы были транспонированы нормально, но при попытке сравнить их с помощью метода .Equals (), неважно то, что я делал, всегда выдает false при попытке сравнить символы.

Я успешно использовал метод .Equals() с другими строками, но, похоже, он не работает с моими символами.

using System;
public class MorseCode {
  public static void Main (string[] args) {
    Console.WriteLine ("Hello, write anything to convert it to morse code!");
    var input = Console.ReadLine();
    foreach (char letter in input) {
      if(letter.Equals("a")) {
        Console.WriteLine("Its A - live");
      }
      Console.WriteLine(letter);
    }
    var morseTranslation = "";
    foreach (char letter in input) {
      if(letter.Equals("a")) {
       morseTranslation += ". _ - ";
      }
      if(letter.Equals("b")) {
       morseTranslation += "_ . . . - ";
      }
      if(letter.Equals("c")) {
       morseTranslation += "_ . _ . - ";
      }
      ...
      }
    }
    Console.WriteLine("In morse code, " + input + " is '"morseTranslation + "'");
  }
}

В начале я написал foreach, чтобы проверить, распознал ли он и выполнил ли правильный вывод, но в конце, когда я написал «sample» в ReadLine(), он дал мне:

Hello, write anything to convert it to morse code!
sample
s
a
m
p
l
e

Ответы [ 4 ]

3 голосов
/ 03 мая 2019

Когда вы делаете это:

var c = 'x';
var isEqual = c.Equals("x");

результат (isEqual) всегда будет ложным, потому что он сравнивает string с char. Это вернет true:

var isEqual = c.Equals('x');

Разница в том, что "x" является литералом string, а 'x' является литералом char.

Часть того, что делает это запутанным, состоит в том, что когда вы используете метод Equals объекта, он позволяет вам сравнивать любой тип с любым другим типом. Чтобы вы могли сделать это:

var x = 0;
var y = "y";
var isEqual = x.Equals(y);

... и компилятор разрешит это, даже если сравнение между int и string не будет работать. Это даст вам предупреждение:

При сравнении типов значений, таких как int или char, с другими значениями того же типа, мы обычно используем ==, например,

if (someChar == someOtherChar)

Тогда, если вы попытались сделать это:

if(someChar == "a") 

Это не скомпилируется. Он скажет вам, что вы сравниваете char с string, и тогда это проще, потому что вместо запуска программы и поиска ошибки она просто не будет компилироваться, и она точно скажет, где проблема.


Просто для удовольствия, вот еще одна реализация.

public static class MorseCodeConverter
{
    private static readonly Dictionary<char, string> Codes 
        = CreateMorseCodeDictionary();

    public static string Convert(string input)
    {
        var lowerCase = input.ToLower();
        var result = new StringBuilder();
        foreach (var character in input)
        {
            if (Codes.ContainsKey(character))
                result.Append(Codes[character]);
        }
        return result.ToString();
    }

    static Dictionary<char, string> CreateMorseCodeDictionary()
    {
        var result = new Dictionary<char, string>();
        result.Add('a', ". _ - ");
        result.Add('b', "_ . . . - ");
        // add all the rest
        return result;
    }
}

Одно отличие состоит в том, что это отдельный класс без консольного приложения. Затем вы можете использовать его в консольном приложении. Прочитайте ввод с клавиатуры и затем наберите

MorseCodeConverter.Convert(input);

чтобы получить результат, а затем вы можете распечатать его на консоли.a

Помещение всех символов в словарь означает, что вместо повторения if/then вы можете просто проверить, есть ли каждый символ в словаре.

2 голосов
/ 03 мая 2019

Важно помнить, что в то время как ключевые слова char и string выглядят напоминающими друг друга, когда вы смотрите на печатные значения, вы должны заметить, что они размещены не одинаково.

Когда вы проверяете строку, вы можете использовать:

string s = "A";
if(s.Equals("A"))
{
    //Do Something
}

Однако вышеприведенное не будет работать с char. разница между символами ( типами значений ) и строками ( ссылочными типами ) на уровне поверхности - это использование доступа - одиночная кавычка (апостроф) против цитаты.

Для сравнения char вы можете сделать это:

char s = 'A';
if(s.Equals('A'))
{
    //Do Something
}

В точке, относящейся к вашему конкретному случаю, однако, азбука Морзе потребует от вас использовать только один алфавит, поэтому при попытке сравнить с 'A' и 'a' вы можете позвонить input.ToLower(), чтобы уменьшить var (строка) для всех строчных букв, поэтому вам не нужно обслуживать как прописные, так и строчные буквы.

Хорошо, что вам известны сравнения строк и вы не используете сравнение прямых значений как это:

if (letter == 'a')
{
    Console.WriteLine("Its A - live");
}

Позволил бы вам сравнивать char, но это плохая практика, так как это может привести к ленивому сравнению строк таким же образом, а это:

if (letter == "a")
{
    Console.WriteLine("Its A - live");
}

Это нерепрезентативный метод сравнения для сравнения строк, поскольку он оценивает ссылку, а не прямое значение, см. здесь

1 голос
/ 03 мая 2019

В C # вы можете сравнивать строки как целые числа, то есть с оператором ==.Equals - это метод, унаследованный от класса object, и обычно реализации делают некоторые проверки типов.char letter - это (очевидно) символ, в то время как "a" - это одна буква string.

Вот почему он возвращает false.

Вы можете использовать if (letter.Equals('a')) { ... } или проще if (letter == 'a') { ... }

Еще проще, чем это будет switch (letter) { case 'a': ...; break; ... }.

Или что-то более элегантное, но, возможно, слишком сложное для начинающих, используя LINQ :

var validCharacters = "ABCDE...";
var codes = new string[] {
".-", "-...", "-.-.", "-..", ".", ...
};
var codes = input.ToUpper() // make uppercase
  .ToCharArray() // explode string into single characters
  .Select(validCharaters.IndexOf) // foreach element (i. e. character), get the result of "validCharacters.IndexOf",
                                  // which equals the index of the morse code in the array "codes"
  .Where(i => i > -1) // only take the indexes of characters that were found in "validCharacters"
  .Select(i => codes[i]); 

// retrieve the matching entry from "codes" by index
// "codes" is now an IEnumerable<string>, a structure saying
// "I am a list of strings over which you can iterate,
//  and I know how to generate the elements as you request them."
// Now concatenate all single codes to one long result string
var result = string.Join(" ", codes);
0 голосов
/ 03 мая 2019

Для сравнения символов вы должны использовать одинарную кавычку 'символ, а не' this. Кстати, в первом цикле foreach вы пишете образец в порядке убывания, потому что вы пишете все буквы в новой строке. Поэтому приведенный ниже код будет работать для вас:

using System;
public class MorseCode {
  public static void Main (string[] args) {
    Console.WriteLine ("Hello, write anything to convert it to morse code!");
    var input = Console.ReadLine();
    /*foreach (char letter in input) {
      if(letter.Equals("a")) {
        Console.WriteLine("Its A - live");
      }
      Console.WriteLine(letter);
    }*/
    var morseTranslation = "";
    foreach (char letter in input) {
      if(letter.Equals('a')) {
       morseTranslation += ". _ - ";
      }
      if(letter.Equals('b')) {
       morseTranslation += "_ . . . - ";
      }
      if(letter.Equals('c')) {
       morseTranslation += "_ . _ . - ";
      }
      ...
      }
    }
    Console.WriteLine("In morse code, " + input + " is '"morseTranslation + "'");
  }
}
...