Golang приведение типов
Пишу функцию, которая должна на вход принимать число Uint, удалять нечетные цифры и нули(если входящее число 0, то отдавать ответом 100), после чего, выводить измененное число в этом же формате, то есть в Uint
На данный момент код следующий:
fn := func (a uint) uint {
if a == uint(0) { return uint(100) }
newA := []rune(strconv.FormatUint(uint64(a), 10))
var strA string
for _, elem := range newA {
if elem % 2 == 0 && elem != '0' {
strA += string(elem)
}
}
res, err := strconv.ParseUint(strA, 10, 64)
if err != nil {
panic(err)
}
a = uint(res)
return a
}
Почему-то код не всегда отрабатывал корректно, решил проверять по действиям, наткнулся на следующую ошибку, никак не могу понять, с чем она связана. Код:
func main() {
var num uint
fmt.Scan(&num)
fn := func(a uint) uint {
if a == 0 {
return 0
}
newA := []rune(strconv.FormatUint(uint64(a), 10))
fmt.Printf("Type - %T, Num - %c\n", newA, newA)
return 0
}
fn(num)
}
При входных данный 000234 в слайс рун newA записывается некорректное значение:
Output:
000234
Type - []int32, Num - [1 5 6]
Думал, какая-то ошибка в приведении string к []rune, но нет, убрав приведение типа, вывод тот же
newA := strconv.FormatUint(uint64(a), 10)
fmt.Printf("Type - %T, Num - %s\n", newA, newA) //исправленное
Output:
000234
Type - string, Num - 156
Подскажите, почему так получается, и что можно этому противопоставить?
Ответы (2 шт):
Давайте по порядку - у вас на входе строка, в которой есть только цифры, НО строковые цифры (руны) != обычные. Вы строку читаете через fmt.Scan, здесь всё верно.
Дальше согласно описанной вами логике, вам нужно конвертировать строку в число, перед этим удалив нечетные строковые значения.
В итоге код получается следующим:
import (
"fmt"
"strconv"
)
func main() {
var input = ""
fmt.Printf("Введите данные:")
_, errRead := fmt.Scanln(&input)
if errRead != nil {
fmt.Printf("Ошибка чтения данных из строки: %s", errRead.Error())
return
}
value, errGetValue := GetResult(input)
if errGetValue != nil {
fmt.Printf("Ошибка конверсии строки в Uint: %s", errGetValue.Error())
return
}
fmt.Printf("Результат: %d\n", value)
}
func GetResult(num string) (uint64, error) {
var filteredNumbersMap = map[rune]bool{'1': false, '3': false, '5': false, '7': false, '9': false,
'0': true, '2': true, '4': true, '6': true, '8': true}
var cleanedUpInput []rune
// Логика - если руна присутствует в map И её значение = true, то включать её в итоговую строку
for _, numChar := range num {
include, mappingExists := filteredNumbersMap[numChar]
if mappingExists && include {
cleanedUpInput = append(cleanedUpInput, numChar)
}
}
fmt.Printf("Фильтрованный результат (строка): %s\n", string(cleanedUpInput))
convertedResult, errParse := strconv.ParseUint(string(cleanedUpInput), 10, 64)
// Если ошибка во время парсинга - возвращаем её
if errParse != nil {
return 0, errParse
}
if convertedResult == 0 {
return 100, nil
}
return convertedResult, nil
}
У вас не учтен один момент:
если длина строки равно 0. Делайте проверку на длину строки
package main
import (
"fmt"
"strconv"
)
func main() {
var num uint
fmt.Scan(&num)
fn := func(x uint) uint {
if x == uint(0) {
return uint(100)
}
newX := []rune(strconv.FormatUint(uint64(x), 10))
// fmt.Printf("Type - %T, Num - %v\n", newX, newX)
var strX string
for _, value := range newX {
if value%2 == 0 && value != '0' && value != ' ' {
strX = strX + string(value)
}
}
// fmt.Printf("Type - %T, Num - %c\n", strX, strX)
if len(strX) == 0 {
return uint(100)
}
u64, err := strconv.ParseInt(strX, 10, 64)
if err != nil {
panic(err)
}
// fmt.Printf("Type - %T, Num - %v\n", u64, u64)
myUint := uint(u64)
// fmt.Printf("Type - %T, Num - %v\n", myUint, myUint)
return myUint
}
// x := uint(727178)
x := uint(num)
fmt.Println(fn(x))
}
// ....
if len(strX) == 0 {
return uint(100)
}