简体   繁体   中英

C# string(char[]) constructor with oversized array fails equality comparison

I'm working on a simple programming interview question to remove a set of unallowed characters from an input string.

Could someone with more experience tell me what is happening here in the underlying data, to cause this comparison failure?

using System;
using System.Collections.Generic;

class Solution {

    public static void Main() {

        var str = "hello world";
        var rmv = "aeiou";

        var res = Remove(str, rmv);


        Console.WriteLine(res);
        if(res == "hll wrld") Console.WriteLine("test 1 pass");
        else Console.WriteLine("test 1 fail");
    }

    public static string Remove(string input, string rmv) {

        var blacklist = new Dictionary<char, int>();

        for(int i = 0; i < rmv.Length; i++) {
            blacklist[rmv[i]] = 1;
        }

        // max length
        var charArray = new char[input.Length];
        var j = 0;

        for(int i = 0; i < input.Length; i++) {
            if(!blacklist.ContainsKey(input[i])) {
                charArray[j] = input[i];
                j++;
            }
        }

        return new string(charArray);
    }   
}

And the output:

9:05pm - me running 40 lines of C#
hll wrld
test 1 fail

Why does it fail the equality comparison when using a char array that has null elements to build the string? Interestingly, the test passes when using String.Compare(res, "hll wrld") == 0

The problem is because charArray is being initialized with the same length as the input string. Since you're removing vowels, the character array has null characters for each of the vowels.

Using the debugger, you can see that "hll wrld" !== "hll wrld\\0\\0\\0" . Where there are 3 \\0 's, one for each vowel removed. You need the charArray to not include those null characters.

One way to fix this is to change the return statement to the following:

return new string(charArray).Replace("\\0", "");

However, I would recommend this simple LINQ one-liner instead of your Remove() method. The HashSet makes the call to Contains be O(1).

var str = "hello world";
var rmv = new HashSet<char>("aeiou".ToArray());

var res = new string(str.Where(x => !rmv.Contains(x)).ToArray());

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM