1

現在、VB6 プログラムを C# に変換しようとしています。文字列を構造に分割する方法が広く使用されていました。例えば、

Dim Sample AS String
Sample = "John Doe        New York  Test Comment"

Public Type Struct1
    Name As String * 15
    Address As String * 10
    Comment As String * 20
End Type

Dim dataStruct As Struct1

Set dataStruct = Sample

dataStruct が設定されると、自動的に値が 3 つの構造体メンバーに分割されます。C# でこれを行う特別な関数はありますか。これを行う方法を知る唯一の方法は、文字列の長さと開始位置を説明する属性/注釈を使用することです。他の提案はありますか?

4

5 に答える 5

3

これを行うためのメソッドがあるFileHelpersライブラリを見てください。

于 2010-06-10T11:06:29.827 に答える
3

暗黙の演算子を使用してみることができます:

class Program
{
    static void Main(string[] args)
    {
        string sample = "John Doe        New York  Test Comment";
        MyClass c = sample;
    }
}

public class MyClass
{
    public string Name;
    public string Address;
    public string Comment;

    public MyClass(string value)
    {
        //parsing of value and assigning to Name, Adress, Comment comes here
    }

    public static implicit operator MyClass(string value)
    {
        return new MyClass(value);
    }
}

文字列値の解析には、正規表現を使用できます。

于 2010-06-10T11:22:40.913 に答える
2

これを行うための組み込みの方法はわかりませんが、属性を使用することは私にとっては良い方法のように思えます。次に、リフレクションを介して関連するプロパティを設定するコードを記述できます。文字列にギャップがない限り、開始位置ではなく相対的な順序と長さで表現します-そうすれば、すべての属性を見つけて、それらの順序で並べ替えることができます(連続している必要はありません-順序0、10、20、30、40の場合、必要に応じて追加のプロパティを追加しやすくなり、そのように分割を実行できます。

于 2010-06-10T11:04:54.960 に答える
1

このような構造マッピングのトリックは、P/Invoke マーシャラーなしでは機能しません。構造の内部組織は検出できません。JIT コンパイラはこれをすぐに利用し、構造体のメモリ サイズが小さくなる場合はメンバーをスワップします。[StructLayout] だけがそれを突き止めることができます。

Microsoft.VisualBasic 名前空間には、これを簡単に行える便利な機能がもう 1 つあります。TextFieldParser クラスは、このような文字列を 1 回の呼び出しで簡単に変換できます。例えば:

using System;
using System.IO;
using Microsoft.VisualBasic.FileIO;  // NOTE: add reference to Microsoft.VisualBasic

class Program {
    static void Main(string[] args) {
        var strm = new StringReader("John Doe        New York  Test Comment");
        var parse = new TextFieldParser(strm);
        parse.TextFieldType = FieldType.FixedWidth;
        parse.SetFieldWidths(16, 10, 12);
        foreach (var field in parse.ReadFields())
            Console.WriteLine(field.Trim());
        Console.ReadLine();
    }
}

投稿した元の文字列が構造宣言と一致しなかったことに注意してください。フィールド幅を変更する必要がありました。また、TextFieldParser は任意のストリームを取ることに注意してください。StringReader に格納された文字列である必要はありません。ファイルを読み取る StreamReader は、より一般的な用途です。

于 2010-06-10T12:45:56.710 に答える
1

演算子のオーバーロードを使用して、割り当ての動作をエミュレートできます。このように、ターゲット クラスはパーツのサイズも定義するため、各クラスは入力がどのように見えるかを知る必要があります。これは、VB の例よりも少し多くのコードです。

例 (構文が正しくない可能性があります。演算子のオーバーロードはほとんど使用しません):

class DataItem
{
  public String Name {get;set;}
  public String Address {get;set;}
  public String Comment {get;set;}

  public static implicit operator DataItem(string value)
  {
    DataItem item = new DataItem();
    item.Name = string.Substring(0, 10).Trim();
    item.Address = string.Substring(10, 25).Trim();
    item.Comment = string.Substring(25, 45).Trim();
    return item;
  }
}

[...]
DataItem item = sampleString;
[...]

より読みやすい代替手段は、暗黙の作成者パターンです。

class DataItem
{
  public String Name {get;set;}
  public String Address {get;set;}
  public String Comment {get;set;}

  public static DataItem FromString(String string)
  {
    DataItem item = new DataItem();
    item.Name = string.Substring(0, 10).Trim();
    item.Address = string.Substring(10, 25).Trim();
    item.Comment = string.Substring(25, 45).Trim();
    return item;
  }
}

[...]
DataItem item = DataItem.FromString(sampleString);
[...]
于 2010-06-10T11:14:59.803 に答える