Convert uint16 array to string - go

I have an array of uint16 coming from WinAPI PROCESSENTRY32.szExeFile that I wanna convert to a string.
Here's my var type
var hello [260]uint16
now I need to convert hello to a string. How can I do that?
Edit
Here's what I've tried:
func szExeFileToString(ByteString [260]uint16) string {
b := make([]byte, len(ByteString))
for i, v := range ByteString {
b[i] = byte(v)
}
return string(b)
}
However, this returns pretty weird strings...
result (the function should convert Windows process names in the PROCESSENTRY32.szExeFile (-> [260]uint16) type to string)

package windows
import "golang.org/x/sys/windows"
func UTF16ToString
func UTF16ToString(s []uint16) string
UTF16ToString returns the UTF-8 encoding of the UTF-16 sequence s,
with a terminating NUL removed.
Use windows.UTF16ToString. For example,
package main
import (
"fmt"
"golang.org/x/sys/windows"
)
func main() {
var szExeFile [260]uint16
szExeFile = [260]uint16{'e', 'x', 'e', 'F', 'i', 'l', 'e'}
exeFile := windows.UTF16ToString(szExeFile[:])
fmt.Println(exeFile)
}
Output:
exeFile

Fixed it. Here's the fixed function to help anyone that gets into this question to convert PROCESSENTRY32.szExeFile result to a string.
Note: I've also forgot to use kernel32.NewProc("Process32FirstW") and kernel32.NewProc("Process32NextW") instead of kernel32.NewProc("Process32First")
func szExeFileToString(ByteString [260]uint16) string {
var End = 0
for i, _ := range ByteString {
if ByteString[i] == 0 {
End = i
break
}
}
return syscall.UTF16ToString(ByteString[:End])
}

Related

Unable to convert my string to hex message

Below has x which is my expected string
I am trying to recreate y myself to match my expected string. Basically trying to convert "01" to "\x01" so that I get the same byte when printed.
Now when I print []byte(x) and []byte(y) I want them to be the same but they aren't. Please help me recreate x with "01" as my input.
package main
import (
"fmt"
)
func main() {
//Expected string
x := "\x01"
//Trying to convert my 01 in string form to same as above - Basically recreate above string again
y := "\\x" + "01"
fmt.Println(x)
fmt.Println(y)
fmt.Println([]byte(x))
fmt.Println([]byte(y))
}
This is what i wanted - got my issue resolved ! :) Thanks all
import (
"fmt"
"encoding/hex"
)
func main() {
//Expected string
x := "\x01"
//Trying to convert my 01 in string form to same as above - Basically recreate above string again
y,err := hex.DecodeString("01")
if err != nil {
panic(err)
}
fmt.Println(x)
fmt.Println(y)
fmt.Println([]byte(x))
fmt.Println([]byte(y))
}
You cannot build a string from a byte sequence that way... \x01 is an escaping notation processed by the compiler when reading literal strings, you cannot use that processing at runtime.
To build a string with the bytes you want you can simply use
x := string([]byte{1, 2, 3, 4})

How in golang to remove the last letter from the string?

Let's say I have a string called varString.
varString := "Bob,Mark,"
QUESTION: How to remove the last letter from the string? In my case, it's the second comma.
How to remove the last letter from the string?
In Go, character strings are UTF-8 encoded. Unicode UTF-8 is a variable-length character encoding which uses one to four bytes per Unicode character (code point).
For example,
package main
import (
"fmt"
"unicode/utf8"
)
func trimLastChar(s string) string {
r, size := utf8.DecodeLastRuneInString(s)
if r == utf8.RuneError && (size == 0 || size == 1) {
size = 0
}
return s[:len(s)-size]
}
func main() {
s := "Bob,Mark,"
fmt.Println(s)
s = trimLastChar(s)
fmt.Println(s)
}
Playground: https://play.golang.org/p/qyVYrjmBoVc
Output:
Bob,Mark,
Bob,Mark
Here's a much simpler method that works for unicode strings too:
func removeLastRune(s string) string {
r := []rune(s)
return string(r[:len(r)-1])
}
Playground link: https://play.golang.org/p/ezsGUEz0F-D
Something like this:
s := "Bob,Mark,"
s = s[:len(s)-1]
Note that this does not work if the last character is not represented by just one byte.
newStr := strings.TrimRightFunc(str, func(r rune) bool {
return !unicode.IsLetter(r) // or any other validation can go here
})
This will trim anything that isn't a letter on the right hand side.

Replace a character at a specific location in a string

I know about the method string.Replace(). And it works if you know exactly what to replace and its occurrences. But what can I do if I want to replace a char at only a known position? I'm thinking of something like this:
randLetter := getRandomChar()
myText := "This is my text"
randPos := rand.Intn(len(myText) - 1)
newText := [:randPos] + randLetter + [randPos + 1:]
But this does not replace the char at randPos, just inserts the randLetter at that position. Right?
I've written some code to replace the character found at indexofcharacter with the replacement. I may not be the best method, but it works fine.
https://play.golang.org/p/9CTgHRm6icK
func replaceAtPosition(originaltext string, indexofcharacter int, replacement string) string {
runes := []rune(originaltext )
partOne := string(runes[0:indexofcharacter-1])
partTwo := string(runes[indexofcharacter:len(runes)])
return partOne + replacement + partTwo
}
UTF-8 is a variable-length encoding. For example,
package main
import "fmt"
func insertChar(s string, c rune, i int) string {
if i >= 0 {
r := []rune(s)
if i < len(r) {
r[i] = c
s = string(r)
}
}
return s
}
func main() {
s := "Hello, 世界"
fmt.Println(s)
s = insertChar(s, 'X', len([]rune(s))-1)
fmt.Println(s)
}
Output:
Hello, 世界
Hello, 世X
A string is a read-only slice of bytes. You can't replace anything.
A single Rune can consist of multiple bytes. So you should convert the string to a (intermediate) mutable slice of Runes anyway:
myText := []rune("This is my text")
randPos := rand.Intn(len(myText) - 1)
myText[randPos] = randLetter
fmt.Println(string(myText))

strings - get characters before a digit

I have some strings such E2 9NZ, N29DZ, EW29DZ . I need to extract the chars before the first digit, given the above example : E, N, EW.
Am I supposed to use regex ? The strings package looks really nice but just doesn't seem to handle this case (extract everything before a specific type).
Edit:
To clarify the "question" I'm wondering what method is more idiomatic to go and perhaps likely to provide better performance.
For example,
package main
import (
"fmt"
"unicode"
)
func DigitPrefix(s string) string {
for i, r := range s {
if unicode.IsDigit(r) {
return s[:i]
}
}
return s
}
func main() {
fmt.Println(DigitPrefix("E2 9NZ"))
fmt.Println(DigitPrefix("N29DZ"))
fmt.Println(DigitPrefix("EW29DZ"))
fmt.Println(DigitPrefix("WXYZ"))
}
Output:
E
N
EW
WXYZ
If there is no digit, example "WXYZ", and you don't want anything returned, change return s to return "".
Not sure why almost everyone provided answers in everything but Go. Here is regex-based Go version:
package main
import (
"fmt"
"regexp"
)
func main() {
pattern, err := regexp.Compile("^[^\\d]*")
if err != nil {
panic(err)
}
part := pattern.Find([]byte("EW29DZ"))
if part != nil {
fmt.Printf("Found: %s\n", string(part))
} else {
fmt.Println("Not found")
}
}
Running:
% go run main.go
Found: EW
Go playground
We don't need regex for this problem. You can easily walk through on a slice of rune and check the current character with unicode.IsDigit(), if it's a digit: return. If it isn't: continue the loop. If there are no numbers: return the argument
Code
package main
import (
"fmt"
"unicode"
)
func UntilDigit(r []rune) []rune {
var i int
for _, v := range r {
if unicode.IsDigit(v) {
return r[0:i]
}
i++
}
return r
}
func main() {
fmt.Println(string(UntilDigit([]rune("E2 9NZ"))))
fmt.Println(string(UntilDigit([]rune("N29DZ"))))
fmt.Println(string(UntilDigit([]rune("EW29DZ"))))
}
Playground link
I think the best option is to use the index returned from strings.IndexAny which will return the first index of any character in a string.
func BeforeNumbers(str string) string {
value := strings.IndexAny(str,"0123456789")
if value >= 0 && value <= len(str) {
return str[:value]
}
return str
}
Will slice the string and return the subslice up to (but not including) the first character that's in the string "0123456789" which is any number.
Way later edit:
It would probably be better to use IndexFunc rather than IndexAny:
func BeforeNumbers(str string) string {
indexFunc := func(r rune) bool {
return r >= '0' && r <= '9'
}
value := strings.IndexFunc(str,indexFunc)
if value >= 0 && value <= len(str) {
return str[:value]
}
return str
}
This is more or less equivalent to the loop version, and eliminates a search over a long string to check for a match every character from my previous answer. But I think it looks cleaner than the loop version, which is obviously a manner of taste.
The code below will continue grabbing characters until it reaches a digit.
int i = 0;
String string2test = "EW29DZ";
String stringOutput = "";
while (!Character.isDigit(string2test.charAt(i)))
{
stringOutput = stringOutput + string2test.charAt(i);
i++;
}

How to convert uint8 to string

I want to convert uint8 to string but can't figure out how.
package main
import "fmt"
import "strconv"
func main() {
str := "Hello"
fmt.Println(str[1]) // 101
fmt.Println(strconv.Itoa(str[1]))
}
Example
This gives me prog.go:11: cannot use str[1] (type uint8) as type int in function argument [process exited with non-zero status]
Any idea?
Simply convert it :
fmt.Println(strconv.Itoa(int(str[1])))
There is a difference between converting it or casting it, consider:
var s uint8 = 10
fmt.Print(string(s))
fmt.Print(strconv.Itoa(int(s)))
The string cast prints '\n' (newline), the string conversion prints "10". The difference becomes clear once you regard the []byte conversion of both variants:
[]byte(string(s)) == [10] // the single character represented by 10
[]byte(strconv.Itoa(int(s))) == [49, 48] // character encoding for '1' and '0'
see this code in play.golang.org
You can do it even simpler by using casting, this worked for me:
var c uint8
c = 't'
fmt.Printf(string(c))
There are no automatic conversions of basic types in Go expressions. See https://talks.golang.org/2012/goforc.slide#18. A byte (an alias of uint8) or []byte ([]uint8) has to be set to a bool, number or string.
package main
import (
. "fmt"
)
func main() {
b := []byte{'G', 'o'}
c := []interface{}{b[0], float64(b[0]), int(b[0]), rune(b[0]), string(b[0]), Sprintf("%s", b), b[0] != 0}
checkType(c)
}
func checkType(s []interface{}) {
for k, _ := range s {
// uint8 71, float64 71, int 71, int32 71, string G, string Go, bool true
Printf("%T %v\n", s[k], s[k])
}
}
Sprintf("%s", b) can be used to convert []byte{'G', 'o' } to the string "Go". You can convert any int type to a string with Sprintf. See https://stackoverflow.com/a/41074199/12817546.
But Sprintf uses reflection. See the comment in https://stackoverflow.com/a/22626531/12817546. Using Itoa (Integer to ASCII) is faster. See #DenysSéguret and https://stackoverflow.com/a/38077508/12817546. Quotes edited.
use %c
str := "Hello"
fmt.Println(str[1]) // 101
fmt.Printf("%c\n", str[1])

Resources