dongya9346 2019-05-03 07:52
浏览 43
已采纳

替代哈希以处理Go中的混合类型

I'm doing a programming exercise to get familiar with Go. I'm currently writing a parser which parses a string into a command with arguments, e.g:

C w h           Should create a new canvas of width w and height h.
B x y c         Should fill the entire area connected to (x,y) with "colour" c.
Q               Should quit the program.

At first I started using hashes to hold the arguments e.g. w h. But this is inflexible and as you can see c is a colour which will be a string, while the other arguments are integers.

I've started like this:

package main

import (
    "errors"
    "strconv"
    "strings"
)

type command struct {
    id   string
    args map[string]int // Won't work because args can be of mixed types
}

func parseCommand(input string) (command, error) {
    if input == "" {
        return command{}, errors.New("No input")
    }

    commandParts := strings.Split(input, " ")

    switch commandParts[0] {
    case "C":
        if (len(commandParts)) != 3 {
            return command{}, errors.New("C (create) requires 2 arguments")
        }

        w, err := strconv.Atoi(commandParts[1])

        if err != nil {
            return command{}, errors.New("width must be an integer")
        }

        h, err := strconv.Atoi(commandParts[2])

        if err != nil {
            return command{}, errors.New("height must be an integer")
        }

        return command{
            id: "create",
            args: map[string]int{
                "w": w,
                "h": h,
            },
        }, nil
    case "B":
        if (len(commandParts)) != 4 {
            return command{}, errors.New("B (Bucket Fill) requires 3 arguments")
        }

        x, err := strconv.Atoi(commandParts[1])

        if err != nil {
            return command{}, errors.New("x must be an integer")
        }

        y, err := strconv.Atoi(commandParts[2])

        if err != nil {
            return command{}, errors.New("y must be an integer")
        }

        return command{
            id: "bucketFill",
            args: map[string]int{
                "x": x,
                "y": y,
                "c": commandParts[3], // This should be a string!
            },
        }, nil
    case "Q":
        return command{
            id: "quit",
        }, nil
    default:
        return command{}, errors.New("Command not supported")
    }
}

My question is how should I go about parsing an input string into a command, if the arguments I want to return are variable and have mixed types? Thanks.

P.S the commands are free typed in and modify a fake canvas in the terminal e.g:

enter command: C 20 4
----------------------
|                    |
|                    |
|                    |
|                    |
----------------------

// Didn't mention this one but it's a Line if you didn't guess
enter command: L 1 2 6 2
----------------------
|                    |
|xxxxxx              |
|                    |
|                    |
----------------------

展开全部

  • 写回答

1条回答 默认 最新

  • dongzhuo8210 2019-05-03 08:28
    关注

    Your approach to command isn't right. A command is something you can apply to a canvas. So we say so:

    type canvas struct{ ... }
    
    type command interface {
        apply(canvas *canvas)
    }
    

    Now there are several kinds of commands, each with its own arguments. When being used as a command, however, the caller shouldn't have to care what those arguments are.

    type createCommand struct {
        width  int
        height int
    }
    
    func (c createCommand) apply(canvas *canvas) { ... }
    
    type bucketFillCommand struct {
        x     int
        y     int
        color string
    }
    
    func (c bucketFillCommand) apply(canvas *canvas) { ... }
    
    type quitCommand struct{}
    
    func (c quitCommand) apply(canvas *canvas) { ... }
    

    And then you can parse them (I'd probably pull all the parsing into functions, but this is fine).

    func parseCommand(input string) (command, error) {
        if input == "" {
            return nil, errors.New("No input")
        }
    
        commandParts := strings.Split(input, " ")
    
        switch commandParts[0] {
        case "C":
            if (len(commandParts)) != 3 {
                return nil, errors.New("C (create) requires 2 arguments")
            }
    
            w, err := strconv.Atoi(commandParts[1])
    
            if err != nil {
                return nil, errors.New("width must be an integer")
            }
    
            h, err := strconv.Atoi(commandParts[2])
    
            if err != nil {
                return nil, errors.New("height must be an integer")
            }
    
            return createCommand{width: w, height: h}, nil
        case "B":
            if (len(commandParts)) != 4 {
                return nil, errors.New("B (Bucket Fill) requires 3 arguments")
            }
    
            x, err := strconv.Atoi(commandParts[1])
    
            if err != nil {
                return nil, errors.New("x must be an integer")
            }
    
            y, err := strconv.Atoi(commandParts[2])
    
            if err != nil {
                return nil, errors.New("y must be an integer")
            }
    
            return bucketFillCommand{x: x, y: y, color: commandParts[3]}, nil
        case "Q":
            return quitCommand{}, nil
        default:
            return nil, errors.New("Command not supported")
        }
    }
    

    Note that this return nil as the command when something fails, not command{}.

    Playground

    展开全部

    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论
编辑
预览

报告相同问题?

悬赏问题

  • ¥30 数据库软件的安装方法
  • ¥15 一道以太网数据传输题
  • ¥15 python 下载群辉文件
  • ¥50 代码还没怎么运行但是需要代码功能调用数据
  • ¥15 vue请求不到数据,返回状态200,数据为html
  • ¥15 用白鹭引擎开发棋牌游戏的前端为什么这么难找
  • ¥35 哪位专业人士知道这是什么原件吗?哪里可以买到?
  • ¥15 关于#c##的问题:treenode反序列化后获取不到上一节点和下一节点,Fullpath和Handle报错
  • ¥15 一部手机能否同时用不同的app进入不同的直播间?
  • ¥20 输入import torch显示Intel MKL FATAL ERROR,系统驱动1%,: Cannot load mkl_intel_thread.dll.
手机看
程序员都在用的中文IT技术交流社区

程序员都在用的中文IT技术交流社区

专业的中文 IT 技术社区,与千万技术人共成长

专业的中文 IT 技术社区,与千万技术人共成长

关注【CSDN】视频号,行业资讯、技术分享精彩不断,直播好礼送不停!

关注【CSDN】视频号,行业资讯、技术分享精彩不断,直播好礼送不停!

客服 返回
顶部