Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/go/7.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Go相当于C';s否定扫描集_Go_Scanf_Gofmt - Fatal编程技术网

Go相当于C';s否定扫描集

Go相当于C';s否定扫描集,go,scanf,gofmt,Go,Scanf,Gofmt,模仿C语言中存在的否定扫描集的方法是什么 例如,输入字符串:aaaa,bbbb 在go中使用: fmt.Sscanf(input, "%s, %s", &str1, &str2) 结果只有str1被设置为:aaaa, 在C语言中,可以使用格式字符串,如%[^,],%s“为了避免这个问题,有什么方法可以在go中实现吗?您可以一直使用正则表达式 re := regexp.MustCompile(`(\w+), (\w+)`) input := "aaaa, bbbb" fmt.Pr

模仿C语言中存在的否定扫描集的方法是什么

例如,输入字符串:
aaaa,bbbb

在go中使用:

fmt.Sscanf(input, "%s, %s", &str1, &str2)
结果只有
str1
被设置为:
aaaa,


在C语言中,可以使用格式字符串,如%[^,],%s“为了避免这个问题,有什么方法可以在go中实现吗?

您可以一直使用正则表达式

re := regexp.MustCompile(`(\w+), (\w+)`)
input := "aaaa, bbbb"
fmt.Printf("%#v\n", re.FindStringSubmatch(input))
// Prints []string{"aaaa, bbbb", "aaaa", "bbbb"}

Go不像C那样直接支持这一点,部分原因是您应该读取一行并使用类似
strings.FieldsFunc
的内容。但这自然是一个非常简单的观点。对于以同质方式格式化的数据,可以使用
bufio.Scanner
对任何
io.Reader
执行基本相同的操作。但是,如果您必须处理类似于此格式的内容:

// Name; email@domain
//
// Anything other than ';' is valid for name.
// Anything before '@' is valid for email.
// For domain, only A-Z, a-z, and 0-9, as well as '-' and '.' are valid.
sscanf("%[^;]; %[^@]@%[-." ALNUM "]", name, email, domain);
然后你会遇到麻烦,因为你现在正在处理一个特定的状态。在这种情况下,您可能更喜欢使用
bufio.Reader
手动解析内容。还可以选择实现
fmt.Scanner
。下面是一些示例代码,让您了解实现
fmt.Scanner
有多容易:

// Scanset acts as a filter when scanning strings.
// The zero value of a Scanset will discard all non-whitespace characters.
type Scanset struct {
    ps        *string
    delimFunc func(rune) bool
}

// Create a new Scanset to filter delimiter characters.
// Once f(delimChar) returns false, scanning will end.
// If s is nil, characters for which f(delimChar) returns true are discarded.
// If f is nil, !unicode.IsSpace(delimChar) is used
// (i.e. read until unicode.IsSpace(delimChar) returns true).
func NewScanset(s *string, f func(r rune) bool) *Scanset {
    return &Scanset{
        ps:        s,
        delimFunc: f,
    }
}

// Scan implements the fmt.Scanner interface for the Scanset type.
func (s *Scanset) Scan(state fmt.ScanState, verb rune) error {
    if verb != 'v' && verb != 's' {
        return errors.New("scansets only work with %v and %s verbs")
    }
    tok, err := state.Token(false, s.delimFunc)
    if err != nil {
        return err
    }
    if s.ps != nil {
        *s.ps = string(tok)
    }
    return nil
}

这不是C的扫描集,但足够近了。如前所述,即使使用格式化输入,您也应该验证数据,因为格式化缺少上下文(并且在处理格式化时添加它违反了KISS原则,并恶化了代码的可读性)

例如,像
[a-Za-z]([a-Za-z0-9-]?)[a-Za-z0-9]
这样的短正则表达式不足以验证域名,而简单的扫描集只相当于
[a-Za-z0-9.-]
。然而,扫描集足以从文件或您可能使用的任何其他读取器中扫描字符串,但它不足以单独验证字符串。因此,一个正则表达式甚至一个合适的库将是一个更好的选择