D中3D字符阵列的问题

Max*_*Max 3 d

我正在学习D,我有一个简单的程序,它逐行读取文本文件,将每一行分成不同的单词,并将整个内容打印到stdout.

import std.stdio;
import std.string;

void main(string args[])
{
    char[][][] lines;
    auto input = File(args[1], "r");
    foreach(line; input.byLine())
    {
        auto words = split(strip(line));
        lines ~= words;
    }

    foreach(line; lines)
    {
        writeln(line);
    }
}
Run Code Online (Sandbox Code Playgroud)

创作words作品的代码.如果我只是writeln在每次分配时调用单词,我会得到我想要的输出.但是,如果我添加wordslines输出lines,然后奇怪的事情发生. lines在源文件中有每行的条目,但每行都是最后一行读取的损坏版本.例如,如果文件的最后一行如下所示:

END    START        * End of routine
Run Code Online (Sandbox Code Playgroud)

我得到的输出看起来像这样:

[       , END, ST, *, End , f rout, ne,    ,     , e other]
[     , END, ST, *, End of, rout, ne,      ,   , e othe]
[    , END, STAR, *, End of, rout, ne.,        
e]
[    , END, START  , *, End of, rout, ne.,        
e]
[END , STAR]
[     , END, START     , *, End , f , out, ne.  ]
[END, START, *, End, of ro, tine. ,  ,   ,  
]
[END, STA, *, o,  r, ut]
[  , END , S, *, End, o,  r, utine.,  ,   ,  , 
,  o]
[END, START    , *, of routi, e.,   ]
Run Code Online (Sandbox Code Playgroud)

知道我做错了什么吗?

he_*_*eat 8

您的主要问题是byLine使用相同的缓冲区,您需要复制它,以便它不会覆盖您的数据

auto words = split(strip(line).dup);
Run Code Online (Sandbox Code Playgroud)

除非您打算修改实际字符,否则更合适的存储类是字符串而不是char [].但是,您将在v 2.0中遇到编译器错误,因为行将是char [].这只是将其复制为不可变字符串的问题.

auto words = split(strip(line).idup);
Run Code Online (Sandbox Code Playgroud)

这样你的程序看起来就像

import std.stdio;
import std.string;

void main(string[] args)
{
    string[][] lines;
    auto input = File(args[1], "r");
    foreach(line; input.byLine())
    {
        auto words = split(strip(line).idup);
        lines ~= words;
    }

    foreach(line; lines)
    {
        writeln(line);
    }
}
Run Code Online (Sandbox Code Playgroud)


Fee*_*ure 5

答案是双重的.

首先,byLine如上所述使用内部缓冲区(用于速度),在后续循环迭代中会被覆盖.

其次,看一下操作words.split(strip(line)).strip仅修改数组的开始和结束(这是一个引用),split将数组拆分为引用相同底层数据的较小子数组.两者都不具有破坏性 ; 因此,既不需要重新分配.因此,最终string[] words仍然指向原始缓冲区,在下一次迭代时会被覆盖.

解决方案是通过写入确保复制数据,如果您希望它通过循环范围转义auto words = split(strip(line).dup);.需要注意的是dupping words无法正常工作,因为这只会复制数组的数组,而不是数组本身.

另外,你应该使用string[] args.仅支持类似C语法的遗留原因,不建议使用.