I'm trying to validate user input so that the only allowed characters in a string are A-Z, a-z, _, - and whitespace. To do that I wrote the following code:
val regex = Regex("[\\w\\s-]")
val flag = regex.matches("Hello Overlay")
But the value of flag is false and I can't figure out why.
To match the whole string meeting a pattern use
val regex = Regex("[\\w\\s-]+")
Or, to avoid overescaping:
val regex = Regex("""[\w\s-]+""")
See the Kotlin demo. Note that matches requires a full string match, but [\w\s-] only matches a single character.
val regex = Regex("""[\w\s-]+""")
val flag = regex.matches("Hello Overlay")
println(flag) // => true
val regex = Regex("""[\w\s-]+""")
val flag = regex.matches("Hello Overlay")
println(flag) // => true
Related
I'm not sure I worded the question correctly.
I have a set of variables, that go like: STO1, STO2, STO3.....STO9; and I need to get the user to input the digit to store and to recall those memory addresses.
So is there a way that the 'STO' be concatenated to the digit (1...9) to get to the var name?
The var names are declared already. I just need to either store a value or retrieve it.
I know that in other languages that is indirect addressing, I think.
Thanks in advance for any input.
Ray.
If variables defined insisde the class (so they are properties) it can be done via Reflection Api.
class Example {
var sto1 = "s1"
var sto2 = "s2"
}
fun main() {
val obj = Example()
val userInput = "1"
val prop = Example::class.memberProperties.find { it.name == "sto$userInput"}
prop as KMutableProperty<*>
//get value example
println(prop.get(obj))
//set value example
prop.setter.call(obj, "new value")
println(prop.get(obj))
}
In order to compile it you should add kotlin-reflect lib to your maven/gradle project.
I'm trying to write some test cases for my compose functions.
I have an outlined Text field with a maximum value of 16 characters.
So I want to test this feature. Here is the test:
#Test
fun checkMaxTaxCodeLength_16Character() {
val taxCode = composeRule.onNodeWithTag(testTag = AUTHENTICATION_SCREEN_TAX_CODE_EDIT_TEXT)
for (i in 'A'..'Z')
taxCode.performTextInput(i.toString())
taxCode.assertTextEquals("ABCDEFGHIJKLMNOP")
}
But although I can see the input is correct, the test fails, and it seems assertTextEquals doesn't work correctly. So:
first of all, what am I doing wrong?
Second, is there any way to, instead of checking the equality, check the text does not contain specific characters?
here is the code of text field:
OutlinedTextField(
value = state.taxCode,
maxLines = 1,
onValueChange = { string ->
viewModel.onEvent(
AuthenticationEvent.TaxCodeChanged(string)
)
},
label = {
Text(text = stringResource(id = R.string.tax_code))
},
modifier = Modifier
.fillMaxWidth()
.testTag(TestingConstant.AUTHENTICATION_SCREEN_TAX_CODE_EDIT_TEXT)
)
The maximum length is handled in the view model. If the user adds more characters than 16, the view model won't update the state and keep the old value.
first of all, what am I doing wrong?
assertTextEquals() takes the value of Text and EditableText in your semantics node combines them and then does a check against the values you pass in. The order does not matter, just make sure to pass in the value of the Text as one of the arguments.
val mNode = composeTestRule.onNodeWithText("Email"))
mNode.performTextInput("test#mail.com")
mNode.assertTextEquals("Email", "test#mail.com")
Please note the text Email is the label for the textfield composable.
To get the semantic information about your nodes you can have
#Test
fun print_semantics_tree() {
composeTestRule.onRoot(useUnmergedTree = true).printToLog(TAG)
}
For the TAG you can use any string. After running the above test you can search the logcat with the specified TAG. You should see something like
|-Node #3 at (l=155.0, t=105.0, r=925.0, b=259.0)px
| Focused = 'false'
| ImeAction = 'Default'
| EditableText = 'test#mail.com'
| TextSelectionRange = 'TextRange(0, 0)'
| Text = '[Email]'
| Actions = [RequestFocus, GetTextLayoutResult, SetText, SetSelection,
OnClick, OnLongClick, PasteText]
Please note you can also obtain the semantics node object with an index operation rather than iterating through all the values.
val value = fetchSemanticsNode().config[EditableText]
assertEquals("test#mail.com", value.toString())
Ok, still, the problem is open, but I achieved what I wanted another way. I used semantic nodes to get what is in edit text and compared it with what it should be:
#Test
fun checkMaxTaxCodeLength_16Character() {
val taxCode = composeRule.onNodeWithTag(testTag = AUTHENTICATION_SCREEN_TAX_CODE_EDIT_TEXT)
for (i in 'A'..'Z')
taxCode.performTextInput(i.toString())
for ((key,value) in taxCode.fetchSemanticsNode().config)
if (key.name =="EditableText")
assertEquals("ABCDEFGHIJKLMNOP",value.toString())
}
I'm a beginner in Android software development. I'm making a calculator app to test my skills. In a calculator there are 0-9 numeric and some others operators like +, -, *, / etc.
In the time of Equal functionality, I have to make sure that the last string of the TextView has any number (0-9), not any operators.
My equal fun is like that:
fun onEqual(view: View) {
if (tv_input.text.contains("0-9")) {
Toast.makeText(this, "Last string is a number, not operator", Toast.LENGTH_SHORT).show()
}
}
You need to use Kotlin regular expression matches
val lastString = "573" // input
val pattern = "-?\\d+(\\.\\d+)?".toRegex()
/**
-? allows zero or more - for negative numbers in the string.
\\d+ checks the string must have at least 1 or more numbers (\\d).
(\\.\\d+)? allows zero or more of the given pattern (\\.\\d+)
In which \\. checks if the string contains . (decimal points) or not
If yes, it should be followed by at least one or more number \\d+.
**/
val isLastString = pattern.matches(lastString)
https://kotlinlang.org/api/latest/jvm/stdlib/kotlin.text/ends-with.html
fun String.endsWith(
suffix: String,
ignoreCase: Boolean = false
): Boolean
Returns true if this string ends with the specified suffix.
Thanks everyone.
I did my own solution.
Here is the code I've wrote:
fun onEqual(view: View) {
if (!tv_input.text.toString().equals("")) {
val last = tv_input.text.toString()
val lastNumber: String = last.get(last.length - 1).toString()
Toast.makeText(this, lastNumber, Toast.LENGTH_SHORT).show()
}else {
return
}
}
So I have a textField where you should enter your "coded" text and get it translated back to non-coded language by using .replace to remove certain characters. But I can't get it to work.
There is a kids "code-language" where you take a word, like cat and for every consonant you add an "o" and the consonant again. So a "b" would be "bob". With vowels they just stay as they are. Cat would be cocatot.
fun translateBack(view : View) {
val konsonanter = "bcdfghjklmnpqrstvwxzBCDFGHJKLMNPQRSTVWXZ"
var input = editText.text.toString()
var emptyString = ""
for(i in konsonanter) {
val find_text = i + "o" + i
var conso = i.toString()
textView.text = input.replace(find_text, conso, false)
}
}
Would like for it to remove the two following letters for every consonant (if possible). So if i enter "cocowow" I should get out "cow". Right now I just get back what I enter in the textField...
Use a forEach loop through the chars of input and replace:
konsonanter.forEach { input = input.replace("${it}o${it}", "${it}", false) }
textView.text = input
The issue is that you're setting the text in textView in every loop, and never updating input. So you're essentially only seeing the result of the replace call that happens with the "ZoZ" and "Z" parameters at the end of the loop, with input still being the original string.
Instead, you can keep updating input and then set the text when you're done:
val konsonanter = "bcdfghjklmnpqrstvwxzBCDFGHJKLMNPQRSTVWXZ"
var input = editText.text.toString()
var emptyString = ""
for (i in konsonanter) {
val find_text = i + "o" + i
val conso = i.toString()
input = input.replace(find_text, conso, false)
}
textView.text = input
If you use the replace function with a Regex and a transform function as parameters you can create a really concise completely self-containing extension function:
fun String.translateBack() = with(Regex("([bcdfghjklmnpqrstvwxz])o\\1", RegexOption.IGNORE_CASE)) {
replace(this) { "${it.value.first()}" }
}
Explanation:
The Regex will match all same consonants (no matter the case) around an "o".
To ensure that the consonant before and after the "o" are the same a backreference to the first group was used.
So, this will also work for cases like "coCatot".
Usage:
println("bob".translateBack()) // b
println("cocatot".translateBack()) // cat
println("coCatot".translateBack()) // cat
I am developing an android application with kotlin in which I need to convert an string character to its ASCII value,
fun tryDiCript(cypher: String) :String {
var cypher = "fs2543i435u#$#g###sagb#!#12416###"
var originalText = ""
var regEx =Regex("[a-z]")
for(char in regEx.findAll(cypher))
{
originalText += (char.value.toInt()).toString()
}
return originalText
}
this tutorial website showed me to use char.toInt() but it gives runtime error saying
Caused by: java.lang.NumberFormatException: Invalid int: "u"
so how if anyone knows hot to convert char to ASCII value please help me.
char.value is a String. When you call String.toInt(), it is expecting a numeric string such as "1", "-123" to be parsed to Int. So, "f".toInt() will give you NumberFormatException since "f" isn't a numeric string.
If you are sure about char.value is a String containing exactly one character only. To get the ascii value of it, you can use:
char.value.first().code
Since Kotlin 1.5
if your variable is of type char for example 'a' you can simply use a.code.
The old methods (e.g. toByte()) are deprecated now.
You said ascii, not unicode. So it's easy.
This is an example that shows you how to convert a char ('A') to it's ascii value.
fun main(vararg args: String) {
println('A'.toByte().toInt())
}
The output is what we expected, 65.
Note this doesn't work with unicode.
Edit 1
I guess this to work.
fun tryDiCript(cypher: String): String {
var cypher = "fs2543i435u#$#g###sagb#!#12416###"
var originalText = ""
var regEx = Regex("[a-z]")
for(char in regEx.findAll(cypher))
originalText += char.value[0].toInt().toString()
return originalText
}
And I recommend you to use StringBuilder.
fun tryDiCript(cypher: String): String {
var cypher = "fs2543i435u#$#g###sagb#!#12416###"
val originalText = StringBuilder()
var regEx = Regex("[a-z]")
for(char in regEx.findAll(cypher))
originalText.append(char.value[0].toInt())
return originalText.toString()
}
I checked #ice1000's answer, I found the block below does not work.
fun main(vararg args: String) {
println('A'.toByte().toInt())
}
As we can see in the Kotlin Documentation String - Kotlin Programming Language,the toByte() function of String "Parses the string as a signed Byte number and returns the result." If the the content of the string is not a number, it will throw a java.lang.NumberFormatException.
But there is another function of String called toByteArray(),this function does no require the content of the string being numbers. My code is as following:
String tempString = "Hello"
val tempArray = tempString.toByteArray()
for (i in tempArray){
println(i.toInt())
}
Attention that toByteArray() function's definition in kotlin's documentaion:
fun String.toByteArray(
charset: Charset = Charsets.UTF_8
): ByteArray
The default charset is UTF-8, if you would like to use other charset, you can modify it with the parameter.