How to handle the %s format specifier - ios

Objective-C code:
NSString *str = #"hi";
NSString *strDigit = #"1934"; (or #"193" may be a 3 digit or 4 digit value)
[dayText appendFormat:#"%#%4s,str,[strDigit UTF8String]];
The Objective-C code handles the output string with current alignment when it appears with 3 or 4 digits as output. It is correctly aligning to left and doesn't matter how much digits it is. Any one know how to handle this in Swift?
In Swift I tried with below code and the string is not adjusting the alignment according to the number of digits.
textForTrip += "\(str) \(String(format:"%4s", (strDigit.utf8))"

The %s format expects a pointer to a (NULL-terminated) C string
as argument, that can be obtained with the withCString method.
This would produce the same output as your Objective-C code:
let str = "Hi"
let strDigit = "193"
let text = strDigit.withCString {
String(format: "%#%4s", str, $0)
}
print(text)
It becomes easier if you store the number as integer instead of a
string:
let str = "Hi"
let number = 934
let text = String(format: "%#%4d", str, number)
print(text)

Try this below approach, that might help you
let strDigit = "\("1934".utf8)" //(or #"193" may be a 3 digit or 4 digit value)
var dayText = "Hello, good morning."
dayText += "\(strDigit.prefix(3))"

Related

How to convert sequence of ASCII code into string in swift 4?

I have an sequence of ASCII codes in string format like (7297112112121326610511411610410097121). How to convert this into text format.
I tried below code :
func convertAscii(asciiStr: String) {
var asciiString = ""
for asciiChar in asciiStr {
if let number = UInt8(asciiChar, radix: 2) { // Cannot invoke initializer for type 'UInt8' with an argument list of type '(Character, radix: Int)'
print(number)
let character = String(describing: UnicodeScalar(number))
asciiString.append(character)
}
}
}
convertAscii(asciiStr: "7297112112121326610511411610410097121")
But getting error in if let number line.
As already mentioned decimal ASCII values are in range of 0-255 and can be more than 2 digits
Based on Sulthan's answer and assuming there are no characters < 32 (0x20) and > 199 (0xc7) in the text this approach checks the first character of the cropped string. If it's "1" the character is represented by 3 digits otherwise 2.
func convertAscii(asciiStr: String) {
var source = asciiStr
var result = ""
while source.count >= 2 {
let digitsPerCharacter = source.hasPrefix("1") ? 3 : 2
let charBytes = source.prefix(digitsPerCharacter)
source = String(source.dropFirst(digitsPerCharacter))
let number = Int(charBytes)!
let character = UnicodeScalar(number)!
result += String(character)
}
print(result) // "Happy Birthday"
}
convertAscii(asciiStr: "7297112112121326610511411610410097121")
If we consider the string to be composed of characters where every character is represented by 2 decimal letters, then something like this would work (this is just an example, not optimal).
func convertAscii(asciiStr: String) {
var source = asciiStr
var characters: [String] = []
let digitsPerCharacter = 2
while source.count >= digitsPerCharacter {
let charBytes = source.prefix(digitsPerCharacter)
source = String(source.dropFirst(digitsPerCharacter))
let number = Int(charBytes, radix: 10)!
let character = UnicodeScalar(number)!
characters.append(String(character))
}
let result: String = characters.joined()
print(result)
}
convertAscii(asciiStr: "7297112112121326610511411610410097121")
However, the format itself is ambigious because ASCII characters can take from 1 to 3 decimal digits, therefore to parse correctly, you need all characters to have the same length (e.g. 1 should be 001).
Note that I am taking always the same number of letters, then convert them to a number and then create a character the number.

How do i fill up the Textbox input reminder bytes with ascii spaces in Swift 4?

Hi I am trying to use a UITextbox and restrict the number of characters input by the user to 10.
I have looked at using the below link,
Max length UITextField
My Questions,
1.Its not working as characters are depreciated in Swift 4 so the string.characters.count is throwing an error so what would be a workaround in Swift 4?
2.After the user enters his x number of characters, I want to make the reminders that is (limitlength - x) into empty spaces (ascii for space = 32 in decimal) so that reminder of the byte array is equal to dec 32.
I have tried doing this,
if let receivedData = rxCharacteristic?.value
let myByteArray = Array(receivedData) {
let b0 = myByteArray[0]
let b1 = myByteArray[1]
let b2 = myByteArray[2]
let b3 = myByteArray[3]
//Now reading data from textbox input
var userdata = textbox.text
let userdataarray: [UInt8] = Array(userdata!.utf8)
//I tried putting values into myByteArray as below
userdataarray[0] = myByteArray[0]
userdataarray[1] = myByteArray[1]
userdataarray[2] = myByteArray[2]
//The last value in myByteArray will remain unchanged so I'm not overwriting it
So from the question when I try to input textbox data less than its length its throwing an index out of range exception. But I went a little extreme to try the below code.
if(userdataarray[0] != 0 && userdataarray[0] != nil)
{
userdataarray[0] = myByteArray[0]
}
else
{
userdataarray[0] = 32 //Which is space in ascii
userdataarray[0] = myByteArray[0]
}
I don't think it worked but wanted to check on how its properly done?
If I understand your question correctly, then your trials are very much overenginering. In Swift you can just add characters to a String (as long as it is declared as var that is). This just boils down to
let orig = "Hello World"
var copy = orig
while copy.count < 15 {
copy.append(" ")
}
let dta = copy.data(using:.isoLatin1)!
let arr = Array(dta)
Since Swift is using some Unicode-encoding internally it is probably crucial to convert your String to data using a specific encoding if you plan to "directly" transfer it to some device that is limited to a certain character set. Still a lot less code than what you provided.

How to get frequency of line feed in string by swift

Sorry,I'm new of swift. I want to calculate the target char in string.But I don't know how to do.Have any good suggestion to me?Thanks.
let string = "hello\nNice to meet you.\nMy name is Leo.\n" //I want to get 3
If you simply want a count of newline characters then you can use a filter on the string's characters:
let string = "hello\nNice to meet you.\nMy name is Leo.\n"
let count = string.characters.filter { $0 == "\n" }.count
print(count)
This outputs 3 as expected.
An alternative is to split the lines with the components(separatedBy method:
let string = "hello\nNice to meet you.\nMy name is Leo.\n"
let lineCounter = string.components(separatedBy: "\n").count - 1
or more versatile to consider all kinds of newline characters
let lineCounter = string.components(separatedBy: CharacterSet.newlines).count - 1
Due to the trailing newline character the result is 4. To ignore a trailing new line you have to decrement the result.

How to express Strings in Swift using Unicode hexadecimal values (UTF-16)

I want to write a Unicode string using hexadecimal values in Swift. I have read the documentation for String and Character so I know that I can use special Unicode characters directly in strings like the following:
var variableString = "Cat‼🐱" // "Cat" + Double Exclamation + cat emoji
But I would like to do it using the Unicode code points. The docs (and this question) show it for characters, but are not very clear about how to do it for strings.
(Note: Although the answer seems obvious to me now, it wasn't obvious at all just a short time ago. I am answering my own question below as a means of learning how to do this and also to help myself understand Unicode terminology and how Swift Characters and Strings work.)
Character
The Swift syntax for forming a hexadecimal code point is
\u{n}
where n is a hexadecimal number up to 8 digits long. The valid range for a Unicode scalar is U+0 to U+D7FF and U+E000 to U+10FFFF inclusive. (The U+D800 to U+DFFF range is for surrogate pairs, which are not scalars themselves, but are used in UTF-16 for encoding the higher value scalars.)
Examples:
// The following forms are equivalent. They all produce "C".
let char1: Character = "\u{43}"
let char2: Character = "\u{0043}"
let char3: Character = "\u{00000043}"
// Higher value Unicode scalars are done similarly
let char4: Character = "\u{203C}" // ‼ (DOUBLE EXCLAMATION MARK character)
let char5: Character = "\u{1F431}" // 🐱 (cat emoji)
// Characters can be made up of multiple scalars
let char7: Character = "\u{65}\u{301}" // é = "e" + accent mark
let char8: Character = "\u{65}\u{301}\u{20DD}" // é⃝ = "e" + accent mark + circle
Notes:
Leading zeros can be added or omitted
Characters are known as extended grapheme clusters. Even when they are composed of multiple scalars, they are still considered a single character. What is key is that they appear to be a single character (grapheme) to the user.
TODO: How to convert surrogate pair to Unicode scalar in Swift
String
Strings are composed of characters. See the following examples for some ways to form them using hexadecimal code points.
Examples:
var string1 = "\u{0043}\u{0061}\u{0074}\u{203C}\u{1F431}" // Cat‼🐱
// pass an array of characters to a String initializer
let catCharacters: [Character] = ["\u{0043}", "\u{0061}", "\u{0074}", "\u{203C}", "\u{1F431}"] // ["C", "a", "t", "‼", "🐱"]
let string2 = String(catCharacters) // Cat‼🐱
Converting Hex Values at Runtime
At runtime you can convert hexadecimal or Int values into a Character or String by first converting it to a UnicodeScalar.
Examples:
// hex values
let value0: UInt8 = 0x43 // 67
let value1: UInt16 = 0x203C // 8252
let value2: UInt32 = 0x1F431 // 128049
// convert hex to UnicodeScalar
let scalar0 = UnicodeScalar(value0)
// make sure that UInt16 and UInt32 form valid Unicode values
guard
let scalar1 = UnicodeScalar(value1),
let scalar2 = UnicodeScalar(value2) else {
return
}
// convert to Character
let character0 = Character(scalar0) // C
let character1 = Character(scalar1) // ‼
let character2 = Character(scalar2) // 🐱
// convert to String
let string0 = String(scalar0) // C
let string1 = String(scalar1) // ‼
let string2 = String(scalar2) // 🐱
// convert hex array to String
let myHexArray = [0x43, 0x61, 0x74, 0x203C, 0x1F431] // an Int array
var myString = ""
for hexValue in myHexArray {
if let scalar = UnicodeScalar(hexValue) {
myString.append(Character(scalar))
}
}
print(myString) // Cat‼🐱
Further reading
Strings and Characters docs
Glossary of Unicode Terms
Strings in Swift
Working with Unicode code points in Swift
from your Hex "0x1F52D" to actual Emoji
let c = 0x1F602
next step would possibly getting an Uint32 from your Hex
let intEmoji = UnicodeScalar(c!).value
from this you can do something like
titleLabel.text = String(UnicodeScalar(intEmoji)!)
here you have a "😂"
it work with range of hexadecimal too
let emojiRanges = [
0x1F600...0x1F636,
0x1F645...0x1F64F,
0x1F910...0x1F91F,
0x1F30D...0x1F52D
]
for range in emojiRanges {
for i in range {
let c = UnicodeScalar(i)!.value
data.append(c)
}
}
to get multiple UInt32 from your Hex range for exemple

Swift String Manipulation

I have converted a double to a string as I think it would be easier to manipulate. I have a string of: 14.52637472 for example.
How can I split it up into 2 variables, one for before the period, and one for ONLY 2 DECIMALS after?
so it should be: one = 14 and two = 52
This is my code to convert into a string: var str: String = all.bridgeToObjectiveC().stringValue
I don't know objective C, so I wouldn't really be able to do it that way, and I have read over the swift book on strings, but it does not discuss how to do this, or atleast I could not find that part?
Please would you help me out, want to build the app for my father to surprise him.
Start with the double, use NSString's format: initializer coupled with a format specifier to trim all but the tenths and hundredths column, and convert to string. Then use NSString's componentsSeparatedByString() to create a list of items separated by the period.
let theNumber = 14.52637472
let theString = NSString(format: "%.2f", theNumber)
let theList = theString.componentsSeparatedByString(".")
let left = theList[0] as String // Outputs 14
let right = theList[1] as String // Outputs 53
As second option using NSNumberFormatter.
let decimalNumber = NSDecimalNumber(double: 14.52637472)
let numberFormatter = NSNumberFormatter()
numberFormatter.maximumIntegerDigits = 2
numberFormatter.maximumFractionDigits = 2
let stringValue = numberFormatter.stringFromNumber(decimalNumber)
let theList = stringValue.componentsSeparatedByString(".")

Resources