Search Unity

  1. Welcome to the Unity Forums! Please take the time to read our Code of Conduct to familiarize yourself with the forum rules and how to post constructively.
  2. We have updated the language to the Editor Terms based on feedback from our employees and community. Learn more.
    Dismiss Notice

Possible Glitch with String Comparison

Discussion in 'General Discussion' started by Kesarium, Feb 18, 2023.

  1. Kesarium

    Kesarium

    Joined:
    Dec 3, 2014
    Posts:
    43
    Hello, I'm getting some odd behavior when trying to compare two strings.

    private string password = "MyPassword";

    I'm comparing them like this : if(userInput.Equals(password))
    and its equaling false even though userInput is equal to "MyPassword" and password is equal to "MyPassword".

    user input is the environment command line arguments that are getting split by the " " in the command.

    Trimming all strings didn't help.

    if I do if(userInput.Equals(password.ToString()))
    it works just fine but should I be having to say if a string variable is string.ToString() ?
    I compare strings all the time with .Equals and I've not encountered this before.
     
  2. Kesarium

    Kesarium

    Joined:
    Dec 3, 2014
    Posts:
    43
    I'm using Unity 2021.3.18f1.
     
  3. DragonCoder

    DragonCoder

    Joined:
    Jul 3, 2015
    Posts:
    1,493
    Please post whole code that reproduces the issue, everything else is guesswork.
     
  4. CodeSmile

    CodeSmile

    Joined:
    Apr 10, 2014
    Posts:
    4,195
    Try stepping into that Equals method with the debugger to see what it does. If userInput is not declared as string but object it may perform a reference equality check rather than string comparison, which would explain why ToString() works.

    Note: comparing a plain text password with another gives me the creeps. I hope this is just some gameplay mechanic or local password and not used to compare passwords with a remote service account password.
     
    angrypenguin and DragonCoder like this.
  5. neginfinity

    neginfinity

    Joined:
    Jan 27, 2013
    Posts:
    13,337
    You should not store passwords as plain text.

    You should not use equals here. Use string comparison.

    Equals is an oddity in C#, and it may default to ReferenceEquals, which will return false in most cases.
     
  6. Kesarium

    Kesarium

    Joined:
    Dec 3, 2014
    Posts:
    43
    Its just some local testing password I'm using for starting up an official dedicated server for my game if the strings match, otherwise it starts up as an unofficial dedicated server.

    Here's the code, all of the Trim() stuff is pretty new for trying to get this to work. The following line is the line I'm talking about, "osp" is the password string that I was saying was behaving oddly.

    if (stringSplit[1].Trim().Equals(osp.ToString()))


    Code (CSharp):
    1. string[] args = System.Environment.GetCommandLineArgs();
    2. string[] stringSplit = new string[2];
    3.  
    4.  
    5.  
    6.             for (int a = 0; a < args.Length; a++)
    7.             {
    8.                 if (args[a].Trim().Equals("-server"))
    9.                 {
    10.                     is_Mode_Headless_Server = true;
    11.                 }
    12.                 else if (args[a].Trim().Equals("-permadeath"))
    13.                 {
    14.                     is_Permadeath_Headless_Server = true;
    15.                 }
    16.                 else if (args[a].Contains(":"))
    17.                 {
    18.                     stringSplit = args[a].Split(":");
    19.  
    20.                     if (stringSplit[0].Trim().Equals("-map"))
    21.                     {
    22.                         if (stringSplit[1].Trim().Equals("SavageLands"))
    23.                         {
    24.                             map_Headless_Server = 1;
    25.                             mapToLoad = 2;
    26.                         }
    27.                         else if (stringSplit[1].Trim().Equals("Savage_Lands"))
    28.                         {
    29.                             map_Headless_Server = 1;
    30.                             mapToLoad = 2;
    31.                         }
    32.                         else if (stringSplit[1].Trim().Equals("LaurasianWoodland"))
    33.                         {
    34.                             map_Headless_Server = 2;
    35.                             mapToLoad = 3;
    36.                         }
    37.                         else if (stringSplit[1].Trim().Equals("Laurasian_Woodland"))
    38.                         {
    39.                             map_Headless_Server = 2;
    40.                             mapToLoad = 3;
    41.                         }
    42.                         else if (stringSplit[1].Trim().Equals("PrimalMountains"))
    43.                         {
    44.                             map_Headless_Server = 3;
    45.                             mapToLoad = 4;
    46.                         }
    47.                         else if (stringSplit[1].Trim().Equals("Primal_Mountains"))
    48.                         {
    49.                             map_Headless_Server = 3;
    50.                             mapToLoad = 4;
    51.                         }
    52.                         else if (stringSplit[1].Trim().Equals("AncientJungle"))
    53.                         {
    54.                             map_Headless_Server = 4;
    55.                             mapToLoad = 5;
    56.                         }
    57.                         else if (stringSplit[1].Trim().Equals("Ancient_Jungle"))
    58.                         {
    59.                             map_Headless_Server = 4;
    60.                             mapToLoad = 5;
    61.                         }
    62.                         else if (stringSplit[1].Trim().Equals("TheGreatSands"))
    63.                         {
    64.                             map_Headless_Server = 5;
    65.                             mapToLoad = 6;
    66.                         }
    67.                         else if (stringSplit[1].Trim().Equals("The_Great_Sands"))
    68.                         {
    69.                             map_Headless_Server = 5;
    70.                             mapToLoad = 6;
    71.                         }
    72.                         else if (stringSplit[1].Trim().Equals("Pangaea"))
    73.                         {
    74.                             map_Headless_Server = 6;
    75.                             mapToLoad = 7;
    76.                         }
    77.                     }
    78.                     else if (stringSplit[0].Trim().Equals("-password"))
    79.                     {
    80.                         if (stringSplit[1].Trim().Equals(osp.ToString()))
    81.                         {
    82.                             is_Official_Server = true;
    83.                         }
    84.                         else
    85.                         {
    86.                             is_Official_Server = false;
    87.                             usp = stringSplit[1].Trim();
    88.                         }
    89.                     }
    90.                     else if (stringSplit[0].Trim().Equals("-spawn-creature-terrestrial"))
    91.                     {
    92.                         try
    93.                         {
    94.                             dinosaurSpawnsMaxTerrestrial = int.Parse(stringSplit[1].Trim());
    95.                         }
    96.                         catch (System.Exception e)
    97.                         {
    98.  
    99.                         }
    100.                     }
    101.                     else if (stringSplit[0].Trim().Equals("-spawn-creature-aerial"))
    102.                     {
    103.                         try
    104.                         {
    105.                             dinosaurSpawnsMaxAerial = int.Parse(stringSplit[1].Trim());
    106.                         }
    107.                         catch (System.Exception e)
    108.                         {
    109.  
    110.                         }
    111.                     }
    112.                     else if (stringSplit[0].Trim().Equals("-spawn-creature-amphibious"))
    113.                     {
    114.                         try
    115.                         {
    116.                             dinosaurSpawnsMaxAmphibious = int.Parse(stringSplit[1].Trim());
    117.                         }
    118.                         catch (System.Exception e)
    119.                         {
    120.  
    121.                         }
    122.                     }
    123.                     else if (stringSplit[0].Trim().Equals("-spawn-creature-aquatic-saltwater"))
    124.                     {
    125.                         try
    126.                         {
    127.                             dinosaurSpawnsMaxAquaticSaltwater = int.Parse(stringSplit[1].Trim());
    128.                         }
    129.                         catch (System.Exception e)
    130.                         {
    131.  
    132.                         }
    133.                     }
    134.                     else if (stringSplit[0].Trim().Equals("-spawn-creature-aquatic-freshwater"))
    135.                     {
    136.                         try
    137.                         {
    138.                             dinosaurSpawnsMaxAquaticFreshwater = int.Parse(stringSplit[1].Trim());
    139.                         }
    140.                         catch (System.Exception e)
    141.                         {
    142.  
    143.                         }
    144.                     }
    145.                     else if (stringSplit[0].Trim().Equals("-spawn-food-fish"))
    146.                     {
    147.                         try
    148.                         {
    149.                             foodSpawnsFish = int.Parse(stringSplit[1].Trim());
    150.                         }
    151.                         catch (System.Exception e)
    152.                         {
    153.  
    154.                         }
    155.                     }
    156.                     else if (stringSplit[0].Trim().Equals("-spawn-food-plants"))
    157.                     {
    158.                         try
    159.                         {
    160.                             foodSpawnsPlants = int.Parse(stringSplit[1].Trim());
    161.                         }
    162.                         catch (System.Exception e)
    163.                         {
    164.  
    165.                         }
    166.                     }
    167.                     else if (stringSplit[0].Trim().Equals("-spawn-food-trees"))
    168.                     {
    169.                         try
    170.                         {
    171.                             foodSpawnsTrees = int.Parse(stringSplit[1].Trim());
    172.                         }
    173.                         catch (System.Exception e)
    174.                         {
    175.  
    176.                         }
    177.                     }
    178.                     else if (stringSplit[0].Trim().Equals("-welcome"))
    179.                     {
    180.                         sMessage = stringSplit[1].Trim().Replace('_', ' ');
    181.                     }
    182.                     else if (stringSplit[0].Trim().Equals("-description"))
    183.                     {
    184.                         sDescription = stringSplit[1].Trim().Replace('_', ' ');
    185.                     }
    186.                     else if (stringSplit[0].Trim().Equals("-name"))
    187.                     {
    188.                         name_Headless_server = stringSplit[1].Trim().Replace('_', ' ');
    189.                     }
    190.                 }
    191.             }
     
  7. Kesarium

    Kesarium

    Joined:
    Dec 3, 2014
    Posts:
    43
    osp is declared in my class as follows (with the actual password string changed for public viewing)

    [HideInInspector] public string osp = "TestingMyPASSWORD";
     
  8. DragonCoder

    DragonCoder

    Joined:
    Jul 3, 2015
    Posts:
    1,493
  9. neginfinity

    neginfinity

    Joined:
    Jan 27, 2013
    Posts:
    13,337
    It doesn't become a mess if you parse it properly. You know, extract the whole thing as a list of trimmed tokens, instead calling Trim.Equals() on every line.
     
    MadeFromPolygons and Ryiah like this.
  10. Ryiah

    Ryiah

    Joined:
    Oct 11, 2012
    Posts:
    20,184
    Alternatively you can just write better code. Here are a couple of examples (written by a bot following instructions on how to restructure everything because I'm not typing all of that up myself).

    Code (csharp):
    1. string[] args = System.Environment.GetCommandLineArgs();
    2.  
    3. foreach (string arg in args)
    4. {
    5.     if (arg.StartsWith("-"))
    6.     {
    7.         string[] tokens = arg.Split(':');
    8.         string key = tokens[0];
    9.         string value = tokens.Length > 1 ? tokens[1] : "";
    10.  
    11.         switch (key)
    12.         {
    13.             case "-server":
    14.                 is_Mode_Headless_Server = true;
    15.                 break;
    16.             case "-permadeath":
    17.                 is_Permadeath_Headless_Server = true;
    18.                 break;
    19.             case "-map":
    20.                 switch (value.ToLower())
    21.                 {
    22.                     case "savagelands":
    23.                     case "savage_lands":
    24.                         map_Headless_Server = 1;
    25.                         mapToLoad = 2;
    26.                         break;
    27.                     case "laurasianwoodland":
    28.                     case "laurasian_woodland":
    29.                         map_Headless_Server = 2;
    30.                         mapToLoad = 3;
    31.                         break;
    32.                     case "primalmountains":
    33.                     case "primal_mountains":
    34.                         map_Headless_Server = 3;
    35.                         mapToLoad = 4;
    36.                         break;
    37.                     case "ancientjungle":
    38.                     case "ancient_jungle":
    39.                         map_Headless_Server = 4;
    40.                         mapToLoad = 5;
    41.                         break;
    42.                     case "thegreatsands":
    43.                     case "the_great_sands":
    44.                         map_Headless_Server = 5;
    45.                         mapToLoad = 6;
    46.                         break;
    47.                     case "pangaea":
    48.                         map_Headless_Server = 6;
    49.                         mapToLoad = 7;
    50.                         break;
    51.                 }
    52.                 break;
    53.             case "-password":
    54.                 if (value.Trim().Equals(osp.ToString()))
    55.                 {
    56.                     is_Official_Server = true;
    57.                 }
    58.                 else
    59.                 {
    60.                     is_Official_Server = false;
    61.                     usp = value.Trim();
    62.                 }
    63.                 break;
    64.             case "-spawn-creature-terrestrial":
    65.                 int.TryParse(value, out dinosaurSpawnsMaxTerrestrial);
    66.                 break;
    67.             case "-spawn-creature-aerial":
    68.                 int.TryParse(value, out dinosaurSpawnsMaxAerial);
    69.                 break;
    70.             case "-spawn-creature-amphibious":
    71.                 int.TryParse(value, out dinosaurSpawnsMaxAmphibious);
    72.                 break;
    73.             case "-spawn-creature-aquatic-saltwater":
    74.                 int.TryParse(value, out dinosaurSpawnsMaxAquaticSaltwater);
    75.                 break;
    76.             case "-spawn-creature-aquatic-freshwater":
    77.                 int.TryParse(value, out dinosaurSpawnsMaxAquaticFreshwater);
    78.                 break;
    79.             case "-spawn-food-fish":
    80.                 int.TryParse(value, out foodSpawnsFish);
    81.                 break;
    82.             case "-spawn-food-plants":
    83.                 int.TryParse(value, out foodSpawnsPlants);
    84.                 break;
    85.             case "-spawn-food-trees":
    86.                 int.TryParse(value, out foodSpawnsTrees);
    87.                 break;
    88.             case "-welcome":
    89.                 sMessage = value.Replace('_', ' ');
    90.                 break;
    91.             case "-description":
    92.                 sDescription = value.Replace('_', ' ');
    93.                 break;
    94.             case "-name":
    95.                 name_Headless_server = value.Replace('_', ' ');
    96.                 break;
    97.         }
    98.     }
    99. }

    Code (csharp):
    1. string[] args = System.Environment.GetCommandLineArgs();
    2. Dictionary<string, Action<string>> options = new Dictionary<string, Action<string>>()
    3. {
    4.     { "-server", value => is_Mode_Headless_Server = true },
    5.     { "-permadeath", value => is_Permadeath_Headless_Server = true },
    6.     { "-map", value => ProcessMapOption(value) },
    7.     { "-password", value => ProcessPasswordOption(value) },
    8.     { "-spawn-creature-terrestrial", value => int.TryParse(value, out dinosaurSpawnsMaxTerrestrial) },
    9.     { "-spawn-creature-aerial", value => int.TryParse(value, out dinosaurSpawnsMaxAerial) },
    10.     { "-spawn-creature-amphibious", value => int.TryParse(value, out dinosaurSpawnsMaxAmphibious) },
    11.     { "-spawn-creature-aquatic-saltwater", value => int.TryParse(value, out dinosaurSpawnsMaxAquaticSaltwater) },
    12.     { "-spawn-creature-aquatic-freshwater", value => int.TryParse(value, out dinosaurSpawnsMaxAquaticFreshwater) },
    13.     { "-spawn-food-fish", value => int.TryParse(value, out foodSpawnsFish) },
    14.     { "-spawn-food-plants", value => int.TryParse(value, out foodSpawnsPlants) },
    15.     { "-spawn-food-trees", value => int.TryParse(value, out foodSpawnsTrees) },
    16.     { "-welcome", value => sMessage = value.Replace('_', ' ') },
    17.     { "-description", value => sDescription = value.Replace('_', ' ') },
    18.     { "-name", value => name_Headless_server = value.Replace('_', ' ') }
    19. };
    20.  
    21. Dictionary<string, int[]> mapSelection = new Dictionary<string, int[]>
    22. {
    23.     { "savagelands", new int[] { 1, 2 } },
    24.     { "savage_lands", new int[] { 1, 2 } },
    25.     { "laurasianwoodland", new int[] { 2, 3 } },
    26.     { "laurasian_woodland", new int[] { 2, 3 } },
    27.     { "primalmountains", new int[] { 3, 4 } },
    28.     { "primal_mountains", new int[] { 3, 4 } },
    29.     { "ancientjungle", new int[] { 4, 5 } },
    30.     { "ancient_jungle", new int[] { 4, 5 } },
    31.     { "thegreatsands", new int[] { 5, 6 } },
    32.     { "the_great_sands", new int[] { 5, 6 } },
    33.     { "pangaea", new int[] { 6, 7 } }
    34. };
    35.  
    36. foreach (string arg in args)
    37. {
    38.     if (arg.StartsWith("-"))
    39.     {
    40.         string[] tokens = arg.Split(':');
    41.         string key = tokens[0];
    42.         string value = tokens.Length > 1 ? tokens[1] : "";
    43.  
    44.         if (options.ContainsKey(key))
    45.         {
    46.             options[key](value);
    47.         }
    48.     }
    49. }
    50.  
    51. private void ProcessMapOption(string value)
    52. {
    53.     if (mapSelection.TryGetValue(value.ToLower(), out int[] mapValues))
    54.     {
    55.         map_Headless_Server = mapValues[0];
    56.         mapToLoad = mapValues[1];
    57.     }
    58. }
    59.  
    60. private void ProcessPasswordOption(string value)
    61. {
    62.     if (value.Trim().Equals(osp.ToString()))
    63.     {
    64.         is_Official_Server = true;
    65.     }
    66.     else
    67.     {
    68.         is_Official_Server = false;
    69.         usp = value.Trim();
    70.     }
    71. }
     
  11. Kesarium

    Kesarium

    Joined:
    Dec 3, 2014
    Posts:
    43
    So the problem I'm having is not a real problem or what?
     
  12. halley

    halley

    Joined:
    Aug 26, 2013
    Posts:
    1,905
    Besides all the good advice to restructure that parsing nightmare, I suggest you add a method like this:

    Code (CSharp):
    1. void CheckStrings(string one, string two)
    2. {
    3.     print(System.Text.Encoding.Unicode.GetByteCount(one));
    4.     print(System.Text.Encoding.Unicode.GetByteCount(two));
    5.     print($"[[[{one}]]]");
    6.     print($"[[[{two}]]]");
    7. }
    And then call that method with your stringSplit[1] and osp.ToString() as arguments.

    For all we know, otp.ToString() may be adding whitespace. If either one of them have non-ASCII characters, there could be some sort of variation in the encoding to C#'s internal Unicode UTF-16 byte contents.