0

VisualStudio2008でC++/ CLIを使用してプログラムを構築していますが、デフォルトのユーザーディレクトリ設定をtxtファイルに保存しようとしています。これまでのところ、txtファイル内で次のように保存できるように保存しました。

Input Directory=C:\Input
Output Directory=C:\Output

問題は、私のプログラムが「Input Directory = "」という単語をどのように検出し、その後の単語のみを取得できるかということです。

また、テキストファイルで特定の単語を検索してC ++ / CLIで置き換える方法はありますか?たとえば、「C:\ Input」を検索して、「D:\Input」に置き換えることができます。

4

3 に答える 3

1

さまざまな方法でファイルから読み取ることができます。c++\cli を使用する利点の 1 つは、非常に便利な .net インターフェイスを利用できることです。

したがって、File::ReadAllLinesを使用して、各行をスキャンして文字列 "Input Directory" を見つけることができます。

于 2012-05-07T15:17:42.183 に答える
1

INI に似た構文だと思いますが、セクションがないため、解析するには次のようにします。

ファイルの解析に使用するクラスのコンストラクター (たとえば) では、次のようにします。

  • を作成しDictionary<string, string>、そこに解析された値を保持します (キーの大文字と小文字を区別しない比較子を指定します)。
  • ファイルの各行を読み、空白行をスキップします (サポートしたい場合はコメント行)。
  • 各文字列行で最初の「=」文字を検索します。その左側の部分がオプションの名前で、右側の部分が値です。
  • それらを辞書に保存します。

GetValue()メソッドでこれを行います:

  • 指定されたキーの辞書を検索して返します。
  • 指定された値を持つキーがない場合は、単にデフォルト値を返します。

これは、単純な INI パーサーの可能な実装です (セクション名が必要ない場合は、空の文字列を渡すだけです)。

using namespace System;
using namespace System::Text;
using namespace System::IO;
using namespace System::Globalization;
using namespace System::Collections::Generic;

namespace Testy
{
    ref class IniParser
    {
    public:
        IniParser()
        {
            _values = gcnew Dictionary<String^, Dictionary<String^, String^>^>(
                StringComparer::InvariantCultureIgnoreCase);
        }

        IniParser(String^ path) 
        {
            _values = gcnew Dictionary<String^, Dictionary<String^, String^>^>(
                StringComparer::InvariantCultureIgnoreCase);

            Load(path);
        }

        void Load(String^ path)
        {
            String^ currentSection = "";
            for each (String^ line in File::ReadAllLines(path))
            {
                if (String::IsNullOrWhiteSpace(line))
                    continue;

                if (line->StartsWith(L";", StringComparison::InvariantCultureIgnoreCase))
                    continue;

                if (line->StartsWith(L"[", StringComparison::InvariantCultureIgnoreCase) && line->EndsWith(L"]", StringComparison::InvariantCultureIgnoreCase))
                {
                    String^ sectionName = line->Substring(1, line->Length - 2);
                    if (String::IsNullOrWhiteSpace(sectionName))
                        continue;

                    currentSection = sectionName;
                }

                array<String^>^ parts = line->Split(gcnew array<wchar_t>(2) { '=' }, 2);
                if (parts->Length == 1)
                    SetString(currentSection, parts[0]->Trim(), "");
                else
                    SetString(currentSection, parts[0]->Trim(), parts[1]->Trim());
            }
        }

        bool ContainsSection(String^ sectionName)
        {
            return _values->ContainsKey(sectionName);
        }

        bool ContainsValue(String^ sectionName, String^ valueName)
        {
            Dictionary<String^, String^>^ values = GetSection(sectionName);
            if (values == nullptr)
                return false;

            return values->ContainsKey(valueName);
        }

        void Clear()
        {
            _values->Clear();
        }

        void SetString(String^ sectionName, String^ valueName, String^ value)
        {
            Dictionary<String^, String^>^ values = GetSection(sectionName);
            if (values == nullptr)
            {
                values = gcnew Dictionary<String^, String^>(StringComparer::InvariantCultureIgnoreCase);
                _values->Add(sectionName, values);
            }

            if (values->ContainsKey(valueName))
                values[valueName] = value;
            else
                values->Add(valueName, value);
        }

        String^ GetString(String^ sectionName, String^ valueName, String^ defaultValue)
        {
            Dictionary<String^, String^>^ values = GetSection(sectionName);
            if (values == nullptr)
                return defaultValue;

            if (values->ContainsKey(valueName))
                return values[valueName];

            return defaultValue;
        }

    private:
        Dictionary<String^, Dictionary<String^, String^>^>^ _values;

        Dictionary<String^, String^>^ GetSection(String^ sectionName)
        {
            if (_values->ContainsKey(sectionName))
                return _values[sectionName];

            return nullptr;
        }
    };
}

エラーチェックを追加する必要があり、不要なもの (セクションやコメントなど) を省略できます。さまざまな値の型を「読み取る」ために、結果を目的の値 (たとえば a )GetXYZ()に解析するためのメソッドをさらに実装できます。GetString()float

もう 1 つの解決策は、ネイティブ関数をインポートして INI を解析することです。彼らは非常にうまく機能します!

于 2012-05-07T15:30:25.083 に答える
0

一日中簡単な解決策を見つけるのに苦労した後、@ Hans Passantによって提案された「InputDirectory=」を省略し、テクニックを使用して、最初の行を入力として、2番目の行を出力フォルダー設定として読み取ることで大まかな回避策を実行することにしました。これに似ています

返信してくれたすべての人に感謝します。

于 2012-05-08T17:06:13.947 に答える