0

次のコードは、ファイルの各行を読み取り、それを操作する必要があります。ただし、最初の行のみを読み取ります。forループがないと、ファイル全体が読み取られます。正直なところ、なぜ全部を読んでいないのかわかりません。

StreamReader sr = new StreamReader(gridPath);

string line;
char[] lineCh;
char current;
int x, y;
bool north, east, south, west;

x = y = 0;

while ((line = sr.ReadLine()) != null)
{
    lineCh = line.ToCharArray();
    for (int i = 0; i < lineCh.Length; i++)
    {
        current = lineCh[i];
        north = CheckInput(current);
        current = lineCh[++i];
        east = CheckInput(current);
        current = lineCh[++i];
        south = CheckInput(current);
        current = lineCh[++i];
        west = CheckInput(current);
        i++; // Hop over space
        grid[x, y] = new GridSquare(north, east, south, west);
        x++; // Start next column
    }
    Console.WriteLine(line);
    y++;
}

forループがないと、次のように機能し、ファイル全体が出力されます。

StreamReader sr = new StreamReader(gridPath);

string line;
char[] lineCh;
char current;
int x, y;
bool north, east, south, west;

x = y = 0;

while ((line = sr.ReadLine()) != null)
{
    lineCh = line.ToCharArray();

    Console.WriteLine(line);
    y++;
}

sr.Close();     

CheckInputは次のとおりです。

private bool CheckInput(char c)
{
    switch (c)
    {
        case 'y':
            return true;
        case 'n':
            return false;
        default:
            return true;
    }
}

サンプル入力ファイル:

nyyn nyyy nyyy nyyy nyyy nnyy
yyyn yyyy yyyy yyyy yyyy ynny
yyyn yyyy yyyy yyyy ynyy nnnn
yyyn yyyy yyyy yyyy ynyy nnnn
yyyn yyyy yyyy yyyy yyyy nnyy
yynn yyny yyny yyny yyny ynny
4

7 に答える 7

6

for ループで例外が発生していますか? i をインクリメントしています。おそらく、ある時点で間違ったインデックスを作成しようとしていますlineCh

EDIT : 不適切なインデックス付けの別の候補はgrid配列です。初期化コードが表示されず、ファイルの読み取り後に と の値が決定されますxyどうやって初期化するの?

于 2010-03-05T11:23:59.453 に答える
3

ループの本体内でループ制御変数を変更しています。これは、ループの予期しない実行につながるため、避ける必要があります。

処理しようとしている行のサンプルを見せてください。for ループのより良い実装を提案できるかもしれません。

行全体を一度に処理する必要がありますか、それとも 4 文字のチャンクに分割し、これら 4 文字を処理してから次の行に移動する必要がありますか?

行の処理方法を変更してみてください。

        while ((line = sr.ReadLine()) != null)
        {
            string[] segments = line.Split(' ');

            foreach(string segment in segments)
            {
                char[] arr = segment.ToCharArray();
                north = CheckInput(arr[0]);
                east = CheckInput(arr[1]);
                west = CheckInput(arr[2]);
                south = CheckInput(arr[3]);
                grid[x, y] = new GridSquare(north, east, south, west);
            }


            Console.WriteLine(line);
            y++;
        }

ここでは、スペースに基づいて行を分割し、文字配列に分割して特定の文字にアクセスすることで、個々のセグメントを操作できます。

このコードは、各セグメントに常に 4 文字があることも前提としていますが、これは常に当てはまりますか? 行が期待どおりであることを確認するための検証も追加する必要があります。

于 2010-03-05T11:28:46.960 に答える
1

あなたの問題は...

for (int i = 0; i < lineCh.Length; i++)

多くの++iステートメントと組み合わせる。

コメントがたくさんあるコードは次のとおりです...各行が「1234」であると想定しています。

        StreamReader sr = new StreamReader(gridPath);

        string line;
        char[] lineCh;
        char current;
        int x, y;
        bool north, east, south, west;

        x = y = 0;

        while ((line = sr.ReadLine()) != null)
        // line is "yyyy"
        {
            lineCh = line.ToCharArray();
            // lineCh.Length is 4
            for (int i = 0; i < lineCh.Length; i++)
            {
                current = lineCh[i]; // i is zero
                north = CheckInput(current);
                current = lineCh[++i]; // i is 1
                east = CheckInput(current);
                current = lineCh[++i]; // i is 2
                south = CheckInput(current);
                current = lineCh[++i];  // i is 3
                west = CheckInput(current);
                i++; // Hop over space // i is 4
                grid[x, y] = new GridSquare(north, east, south, west);
                // (true,true,true,true)
                // So essentially the loop ends if there are four,
                // or goes round again for multiples of 4 - of course,
                // it will error if there is ever 3, or 5 or any other non multiple of 4

                x++; // Start next column
            }
于 2010-03-05T11:22:11.360 に答える
1

これらの行のいずれかで配列の境界を取得できるため、コードは例外をスローします。

current = lineCh[++i];
于 2010-03-05T11:25:37.440 に答える
1

ループ自体の中でループ変数をインクリメントするのは危険です。北、東などの変数のカスタム タイプを作成し、各行を最後まで使用することをお勧めします。または、次の GridSquare オブジェクトを返す方がよいかもしれません。

これは、GridSquares の反復子を返すメソッドで実行できます。

StreamReader sr = new StreamReader("input.txt");

string line;
char[] lineCh;
char current;
int x, y;
bool north, east, south, west;

x = y = 0;

while ((line = sr.ReadLine()) != null)
{
    foreach (var gs in GetGridSquares(line))
    {
        // grid[x, y] = gs;
    }

     Console.WriteLine(line);
     y++;
 }

GetGridSquares は次のとおりです。

 private IEnumerable<GridSquare> GetGridSquares(string line)
    {
        var splittedLine = line.Split(' ');
        foreach (var gsStr in splittedLine)
        {
            if (gsStr.Length != 4)
            {
                continue;
            }

            yield return new GridSquare(gsStr[0], gsStr[1], gsStr[2], gsStr[3]);
        }
    }
于 2010-03-05T11:31:28.090 に答える
1

コードをきれいにした後に見つけた実際の答えは、 x がゼロに戻されることは決してないということでした。グリッド [,] の次の行に移動することはありません。私の例からこれを解決するのは難しいと思います。申し訳ありません。

于 2010-03-05T17:29:08.707 に答える
1
StreamReader sr = new StreamReader(gridPath);

var line;       
var y = 0;  

while ((line = sr.ReadLine()) != null)
{
    for(var i =0; i<line.length;i+=2)
    {
        grid[i,y]=new GridSquare(GetBits(line[i],i));
        grid[i+1,y]=new GridSquare(GetBits(line[i],i+1));


    }
    ++y;

}

bool [] GetBits(char bBytes, int n)
{
    var returned = new bool[4];
    bBytes = bBytes << ((n%2)*4);
    for(var i =0; i < 4; ++i)
        returned[i]=(bBytes & (1<<i ) > 0;

}
于 2010-03-05T12:32:26.603 に答える