Почему сравнение символов с .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
0
cabbaand000 3 Май 2019 в 00:13

4 ответа

Лучший ответ

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

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

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

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

Для сравнения 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");
}

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

2
2 Май 2019 в 22:02

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

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);

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

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

3
Scott Hannen 2 Май 2019 в 22:02

Для сравнения символов вы должны использовать одинарную кавычку «символ, а не» 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 + "'");
  }
}
0
Serhat Oz 2 Май 2019 в 21:20

В 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
LWChris 29 Ноя 2019 в 15:38