Генератор паролей отображает kotlin.Unit

#android #string #kotlin #random #passwords

#Android #строка #kotlin #Случайный #пароли

Вопрос:

Я пытаюсь создать генератор случайных паролей на основе пользовательского ввода, и все в порядке, пока я не использую.Функция toCharArray().shuffle(), но без перетасовки она слишком предсказуема, потому что она помещает буквы в заранее определенные позиции. Есть ли какой-либо способ, которым этот код будет работать? Есть обходной путь? Я уже пробовал stringbuilder, но он обходит пользовательский ввод, поэтому я не знаю, что теперь делать.

 val chars= "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ~@#$%^amp;*()!"

 override fun onProgressChanged(seekBar: SeekBar?, progress: Int, fromUser: Boolean) {
        if (fromUser)
        {
            when(seekBar)
            {
                sbNumberOfLetters ->
                {
                    tvLetterCount.text = progress.toString()
                    smallLetters = progress
                }

                sbNumberOfCapitalLetters ->
                {
                    tvCapitalsCount.text = progress.toString()
                    capitalLetterNumber = progress
                }

                sbNumberOfNumerals ->
                {
                    tvNumeralsCount.text = progress.toString()
                    numeralsNumber = progress
                }

                sbNumberOfSpecialChars ->
                {
                    tvSpecialCharsCount.text = progress.toString()
                    specialCharNumber = progress
                }
            }
        }
    }



 private fun generatePassword() {

        for (y in 1..numeralsNumber)
        {
            var randomLetter = Random.nextInt(0, 9)
            listOfLetters.add(chars[randomLetter].toString())
        }

        for (w in 1..smallLetters)
        {
            var randomLetter = Random.nextInt(10, 36)
            listOfLetters.add(chars[randomLetter].toString())
        }

        for (x in 1..capitalLetterNumber)
        {
            var randomLetter = Random.nextInt(36, 62)
            listOfLetters.add(chars[randomLetter].toString())
        }

        for (z in 1..specialCharNumber)
        {
            var randomLetter = Random.nextInt(63, 73)
            listOfLetters.add(chars[randomLetter].toString())
        }

        password = (listOfLetters.joinToString(separator = "",)).toCharArray().shuffle().toString()

        tvGeneratedPassword.text = password

        listOfLetters.clear()
    }
  

Ответ №1:

shuffle возвращает Unit , поэтому вызов toString() on Unit вернет kotlin.Unit значение, определенное в Unit . Попробуйте это:

 listOfLetters.shuffle()
val password = listOfLetters.joinToString(separator = "")
tvGeneratedPassword.text = password
  

Комментарии:

1. С другой стороны, это решение не возвращает kotlin.Unit. Недостатком является то, что он, похоже, полностью игнорирует ввод пользователя. Даже если все переменные равны нулю, он все равно возвращает некоторую нежелательную строку из 10 букв. Всегда начинается с [C@

2. @Piotr Я думал, ты этого хочешь. Обновленный ответ для перетасовки списка и последующего преобразования в строку. Вам не нужно вызывать toCharArray()

3. Хорошо, теперь я понял, что просто нужно использовать несколько println, чтобы проверить, что именно происходит. Любезно благодарю вас, сэр.

Ответ №2:

Можно также использовать инструменты, предоставляемые Kotlin, для написания выразительного и поддерживаемого кода ( Random.nextInt правильные ли индексы в коде, который вы указали?). Вот одна альтернатива (здесь используются списки, а не массивы, и shuffled() возвращает новый список) :

 
abstract sealed class RandomChars {
    open val chars: CharArray = charArrayOf()
    fun get(count: Int) = (1..count).map { chars[Random.nextInt(0, chars.size)] }
}
object RandomDigits : RandomChars() {
    override val chars = "0123456789".toCharArray()
}
object RandomLowerCase : RandomChars() {
    override val chars = "abcdefghijklmnopqrstuvwxyz".toCharArray()
}
object RandomUpperCase : RandomChars() {
    override val chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZ".toCharArray()
}
object RandomSpecial : RandomChars() {
    override val chars = "~@#$%^amp;*()!".toCharArray()
}

fun main() {
    val password =
        (RandomDigits.get(1)   RandomLowerCase.get(2)   RandomUpperCase.get(2)   RandomSpecial.get(1))
            .shuffled()
            .joinToString(separator = "")

    println(password) // e.g. %Oa7Mt
}

  

Вот другой, более функциональный подход:

 
val charGenerator =
    { alphabet: CharArray -> { count: Int -> (1..count).map { alphabet[Random.nextInt(0, alphabet.size)] } } }

val randomDigits = charGenerator("0123456789".toCharArray())
val randomLowecase = charGenerator("abcdefghijklmnopqrstuvwxyz".toCharArray())
val randomUppercase = charGenerator("ABCDEFGHIJKLMNOPQRSTUVWXYZ".toCharArray())
val randomSpecial = charGenerator("~@#$%^amp;*()!".toCharArray())

fun main() {
    val password =
        (randomDigits(1)   randomLowecase(2)   randomUppercase(2)   randomSpecial(1))
            .shuffled()
            .joinToString(separator = "")

    println(password) // e.g. %Oa7Mt
}