在D中解析一个字符串

时间:2011-12-10 18:43:21

标签: string parsing d

我正在努力学习D,但我正在努力缺乏文档(或者我对它的理解),所以我来到这里。我今天早些时候已经问了一个不同但不相关的问题。

无论如何,这里是:

我想为不同的东西解析一个字符串。

字符串格式类似于:

[<label>] <mnemonic> [parameters]

如果没有标签,则有强制性空格。参数可以逗号分隔。参数类型取决于助记符。

我想使用Phobos库中的std.conv: parse来帮助我,但是我无法理解有关如何解析“单词”的文档,例如,在两端用空格分隔的一些字符。它适用于整数等int i = parse!int(line)。但是,如果我要做string s = parse!string(line),那么它将占据整条线。

我手工解析这个问题,使用char**(或ref string)作为数据类型,就像我在C中写的那样。但是我正在学习D不必

我尝试过这样的手动:

string get_word(ref string s)
{
        int i = 0;
        while (i < s.length && isAlphaNum(s[i]))
                i++;

        string word = s[0 .. i];
        s = s[i+1 .. $];
        return word;
}

这是一个很好的方法吗?有更干净的方式吗?更快的方法?或许更安全的方式?我不确定i+1索引是否始终存在。

感谢您的帮助!

我对D的信心已经逐渐减弱,因为我遇到了各种各样的问题。但这条道路肯定是值得的。

2 个答案:

答案 0 :(得分:2)

首先,std.conv.parse用于将事物转换为字符串,而不是在分离和理解字符串的意义上进行解析。您需要的解决方案的复杂程度取决于格式字符串语法的复杂程度。 查看std.string.split,默认情况下,它将在空格上拆分输入并返回单词数组。 如果格式过于复杂,您可以:

  1. 使用带有捕获的正则表达式:http://d-programming-language.org/phobos/std_regex.html#RegexMatch

  2. 编写您自己的解析器,逐个字符地提升并提取您需要的信息。

答案 1 :(得分:1)

代码是即时编写的

import std.string;
import std.stdio;
import std.algorithm;
import std.math;

enum string[] separators = [ " ", "\t", ",", ";", "\n", "\r\n" ];

string get_word( ref string s ){
    string token;
    sizediff_t storePositions[separators.length + 1]; // set size array to the number of separator in array "separators" and latest field for current string lenght 
    foreach( i, separator; separators ){             // compute position for each separator
        sizediff_t position = countUntil( s, separator );
        if( position == -1 ) position = sizediff_t.max;
        storePositions[i] = position;
    }
    storePositions[ $ -1 ] = s.length;
    sizediff_t end    = reduce!min( storePositions );
    token             = s[0 .. end].idup;
    writefln( "%s | %d", s, end );
    return token;
}

void main( string[] args ){
    string s        = "a long;string\tyeah\n strange; ok";
    bool   isRunning= true;
    size_t start    = 0;
    writefln( "parse: %s", s ); 
    while( isRunning ){
        string result = get_word( s[ start .. $] );
        if( result == "" )
            isRunning = false;
        else{
            start  += result.length + 1;
            result = get_word( s[ start .. $] );
        }
        writefln( "token: %s, position: %d", result, start );
        writeln( "----" );
    } 
}

输出:

parse: a long;string yeah
 strange; ok
a long;string yeah
 strange; ok | 1
long;string yeah
 strange; ok | 4
token: long, position: 2
----
long;string yeah
 strange; ok | 4
string yeah
 strange; ok | 6
token: string, position: 7
----
string yeah
 strange; ok | 6
yeah
 strange; ok | 4
token: yeah, position: 14
----
yeah
 strange; ok | 4
 strange; ok | 0
token: , position: 19
----
 strange; ok | 0
token: , position: 19