0

我在 Visual Studio 2008 中使用 C++/CLI 构建程序,我一直在尝试将默认用户目录设置保存在 txt 文件中。到目前为止,我设法保存它,使其在 txt 文件中看起来像这样。

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

问题是,我的程序如何检测“输入目录=”这个词并且只接受它之后的词?

有没有办法在文本文件中搜索特定单词并在 C++/CLI 中替换它?因此,例如,我可以搜索“C:\Input”并将其替换为“D:\Input”。

4

3 回答 3

1

您可以通过多种方式读取文件。使用 c++\cli 的好处之一是您可以使用非常 convent .net 接口。

所以你可以使用File::ReadAllLines然后扫描每一行的字符串“输入目录”

于 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;
        }
    };
}

您应该添加错误检查,并且可以省略不需要的内容(例如部分和注释)。要“读取”不同的值类型,您可以实现更多GetXYZ()方法来将结果解析GetString()为所需的值(float例如 a )。

另一种解决方案可能是......简单地导入本机函数来解析 INI。他们工作得很好!

于 2012-05-07T15:30:25.083 回答
0

在为寻找简单的解决方案苦苦挣扎了一整天之后,我决定按照@Hans Passant 的建议省略“输入目录=”,并通过将第一行作为输入和第二行作为输出文件夹设置来做一个粗略的解决方法,使用技术类似这样

感谢所有回复的人。

于 2012-05-08T17:06:13.947 回答