Swift 3 method to create utf8 encoded Data from String - string

I know there's a bunch of pre Swift3 questions regarding NSData stuff. I'm curious how to go between a Swift3 String to a utf8 encoded (with or without null termination) to Swift3 Data object.
The best I've come up with so far is:
let input = "Hello World"
let terminatedData = Data(bytes: Array(input.nulTerminatedUTF8))
let unterminatedData = Data(bytes: Array(input.utf8))
Having to do the intermediate Array() construction seems wrong.

It's simple:
let input = "Hello World"
let data = input.data(using: .utf8)!
If you want to terminate data with null, simply append a 0 to it. Or you may call cString(using:)
let cString = input.cString(using: .utf8)! // null-terminated

NSString methods from NSFoundation framework should be dropped in favor for Swift Standard Library equivalents. Data can be initialized with any Sequence which elements are UInt8. String.UTF8View satisfies this requirement.
let input = "Hello World"
let data = Data(input.utf8)
// [72, 101, 108, 108, 111, 32, 87, 111, 114, 108, 100]
String null termination is an implementation detail of C language and it should not leak outside. If you are planning to work with C APIs, please take a look at the utf8CString property of String type:
public var utf8CString: ContiguousArray<CChar> { get }
Data can be obtained after CChar is converted to UInt8:
let input = "Hello World"
let data = Data(input.utf8CString.map { UInt8($0) })
// [72, 101, 108, 108, 111, 32, 87, 111, 114, 108, 100, 0]

Related

Python 3.8: Bytes to a list of hex

I'm currently banging by head bloody over this problem I have:
I have a method where I receive a byte input of a defined length of 8:
def ConvertToHexAndSend(serialnumber):
if len(serialnumber) != 8:
throw a good exception...
Some good converter code here..
The method shall then take the serialnumber and split it into a list with the size 4.
Example:
serialnumber = b'12345678'
Expected output:
[0x12, 0x34, 0x56, 0x78]
What I have tried so far:
new_list = list(serialnumber) # Gives a list of [49, 50, 51, 52, 53, 54, 55, 56] and then:
first byte = new_list[0] << 8 + new_list[1] # gives some riddish value
and
hex(serialnumber[0]) # Gives '0x32' string
and
first_byte = serialnumber[0] + serialnumber[1] # Gives int 99
But no success so far.. any idea?
You want something like:
result = list(bytes.fromhex(serialnumber.decode('ascii')))
Your bytes are represent a hex-string. So use the bytes.fromhex to read that (converting the bytes to str first), and you can use list to get a list of int objects from the new resulting bytes object

Why is my test changing the length of a byte array?

I have the following test:
pub(crate) fn from_byte_slice(packet: &[u8]) -> BackendKeyData {
let mut backend = BackendKeyData::new();
backend.pid = i32::from_be_bytes(pop(&packet[5..9]));
backend.key = i32::from_be_bytes(pop(&packet[9..]));
backend
}
#[test]
fn test_backend_key_data() {
let bytes = b"\x75\x00\x00\x00\x12\x00\x00\x149\x241\x17\x173\x241\x137";
let backend = BackendKeyData::from_byte_slice(bytes);
assert_eq!(backend.pid, 0);
}
When I debug the test the byte array changes and becomes this slice:
[0]:117
[1]:0
[2]:0
[3]:0
[4]:18
[5]:0
[6]:0
[7]:20
[8]:57
[9]:36
[10]:49
[11]:23
[12]:23
[13]:51
[14]:36
[15]:49
[16]:19
[17]:55
What's going on here, why the change?
\x is for 2 digit hexadecimal escapes only. \x137 does not make a byte with value 137, but instead a byte with value 0x13 followed by the byte represented by the ascii character 7. Use an array literal for base 10 values instead:
&[75, 0, 0, 0, 12, 0, 0, 149, 241, 17, 173, 241, 137]

How do I convert a byte array with null terminating character to a String in Kotlin?

When I attempt to retrieve a value from the device via Bluetooth, it comes out in ASCII, as a null terminated big-endian value. The device software is written in C. I want to retrieve the decimal value, i.e. 0 instead of 48, 1 instead of 49, 9 instead of 57, etc.
#Throws(IOException::class)
fun receiveData(socket: BluetoothSocket ? ): Int {
val buffer = ByteArray(4)
val input = ByteArrayInputStream(buffer)
val inputStream = socket!!.inputStream
inputStream.read(buffer)
println("Value: " + input.read().toString()) // Value is 48 instead of 0, for example.
return input.read()
}
How can I retrieve the value I want?
It's easy to do with bufferedReader:
val buffer = ByteArray(4) { index -> (index + 48).toByte() } // 1
val input = ByteArrayInputStream(buffer)
println(input.bufferedReader().use { it.readText() }) // 2
// println(input.bufferedReader().use(BufferedReader::readText)) // 3
Will output "0123".
1. Just stubs the content of a socket using an init function that sets first element of the buffer to 48, second to 49, third to 50 and fourth to 51.
2. The default charset is UTF-8, that is a "superset" of ASCII.
3. It's just another style of calling { it.readText() }.
My function ultimately took the following form. This allowed me to retrieve all 5 digits in decimal form:
#Throws(IOException::class)
fun receiveData(socket: BluetoothSocket ? ): String {
val buffer = ByteArray(5)
(socket!!.inputStream).read(buffer)
println("Value: " + String(buffer))
return String(buffer)
}
For my particular problem, the input variable was being created before reading the data into the buffer. Since the read method is called for every index in the data, I was only getting the first digit.
See the Java method public int read() for an explanation:
Reads the next byte of data from this input stream. The value byte is returned as an int in the range 0 to 255. If no byte is available because the end of the stream has been reached, the value -1 is returned.

How to find the biggest number in a string that contains not just numbers but words?

How to find the biggest number in a string that contains not just numbers but words?
For example:
String naa = "John 19, Reuben 21, sbu 6, Derick 33";
I need to be able to find the highest age no mater the names and ages entered.
I'm not sure what language you are trying to use but one way to do this in ruby for example would be
str = "John 19, Reuben 21, sbu 6, Derick 33;"
str.gsub(/\d+/).map { |i| i.to_i }.max
What this does is the following:
str.gsub(/\d+/)
Returns all the numbers as an enumerator
The map command then changes them all to integers and returns an Array with the integers.
Then we just call max on that array.
Java
String[] ss = "John 19, Reuben 21, sbu 6, Derick 33;".split("[^\\d]");
System.out.println(Arrays.asList(ss));
int max = Integer.MIN_VALUE;
for(String s:ss){
try{
if (Math.max(Integer.valueOf(s), max) != max){
max = Integer.valueOf(s);
}
}catch(NumberFormatException nfe){}
}
System.out.println(max);
Try this in java
Pattern p = Pattern.compile("[0-9]?[0-9]");
Matcher m = p.matcher(naa) ;
List<Integer> listInt = new ArrayList<Integer>();
while (m.find()) {
int age = Integer.parseInt(m.group());
listInt.add(age);
}
int max = Collections.max(listInt);
System.out.println( max);

String unique characters [duplicate]

This question already has answers here:
Determining a string has all unique characters without using additional data structures and without the lowercase characters assumption
(7 answers)
Closed 8 years ago.
Implement an algorithm to determine if a string has all unique characters. What if you can not use additional data structures?
If you can use a little auxiliary memory, then a small array of bits (indexed by the numerical code of the character) is all you need (if your characters are 4-byte Unicode ones you'll probably want a hashmap instead;-). Start with all bits at 0: scan the string from the start -- each time, you've found a duplicate if the bit corresponding to the current character is already 1 -- otherwise, no duplicates yet, set that bit to 1. This is O(N).
If you can't allocate any extra memory, but can alter the string, sorting the string then doing a pass to check for adjacent duplicates is the best you can do, O(N log N).
If you can't allocate extra memory and cannot alter the string, you need an O(N squared) check where each character is checked vs all the following ones.
we can do it by assigning a prime number to every character.. and multiply it for every character found. then on every character check that if the value is divisible by the number assigned to that character or not..
answer in c program
int is_uniq(char *str)
{
int i = 0, flag = 0, value = 0;
for(i = 0; i < strlen(str); i++) {
value = str[i] - 'a';
if(flag & (1 << value)) {
return 0;
}
flag |= (1 << value);
}
return 1;
}
for each character in the string
if any subsequent character matches it
fail
succeed
One possible solution - You could extract the string into an array of characters, sort the array, and then loop over it, checking to see if the next character is equal to the current one.
the prime method described by partik (based on this theorem). It's O(N).
# one prime per letter
primes = [2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47, 53, 59, 61, 67, 71, 73, 79, 83, 89, 97, 101]
starting_byte = ?a.ord
primes_product = 1
ARGV[0].each_byte do |byte|
current_prime = primes[byte - starting_byte]
if primes_product % current_prime == 0
puts "Not unique"
exit
else
primes_product = primes_product * current_prime
end
end
puts "Unique"
I came on this thread for the similar question and ended up with the following solution in C#:
var data = "ABCDEFGADFGHETFASAJUTE";
var hash = new Dictionary<char, int>();
foreach (char c in data)
{
if (hash.ContainsKey(c))
{
hash[c] += 1;
}
else
{
hash.Add(c, 1);
}
}
var Characters = hash.Keys.ToArray();
var Frequencies = hash.Values.ToArray();
import java.io.*;
public class uniqueChar
{
boolean checkUniqueChar(String strin)
{
int m;
char []str=strin.toCharArray();
java.util.Arrays.sort(str);
for(int i=0;i<str.length-1;i++)
{
if(str[i]==str[i+1])
return false;
}
return true;
}
public static void main(String argv[]) throws IOException
{
String str;
System.out.println("enter the string\n");
InputStreamReader in=new InputStreamReader(System.in);
BufferedReader bin=new BufferedReader(in);
str=bin.readLine();
System.out.println(new uniqueChar().checkUniqueChar(str));
}
}
public static boolean isUniqueChars(String str) {
int checker = 0;
for (int i = 0; i < str.length(); ++i) {
int val = str.charAt(i) - 'a';
if ((checker & (1 << val)) > 0)
return false;
checker |= (1 << val);
}
return true;
}

Resources