【问题标题】:Trying to read from ini file in C++ [closed]尝试从 C++ 中的 ini 文件中读取 [关闭]
【发布时间】:2019-11-02 22:00:30
【问题描述】:

所以我决定培养一个新的爱好,因为我负担不起制造 PC 的费用,但到目前为止,我正在尝试创建一个简单的基于控制台的程序,该程序可以从 ini 文件中读取信息,但它似乎无法读取它根本没有,而是只输出默认值。和随机整数。

char* ReadINI(const char* sSection, const char* sSub, const char* sDefaultValue)
{
    char* sResult = new char[255];
    memset(szResult, 0x00, 255);
    GetPrivateProfileString(  sSection, sSub, sDefaultValue, sResult, 255, ".\\config.ini");
    return sResult;
}

int s_width = (int)ReadINI("CONFIGURATION", "WIN_WIDTH", 0);
int s_height = (int)ReadINI("CONFIGURATION", "WIN_HEIGHT", 0);
const char* value = ReadINI("CONFIGURATION", "WIN_NAME", "null");

这是我作为调试方式的输出,因此用户知道应用程序已正确读取那里的设置。

std::cout << "Width: " << s_width << "\n"; // Displays random integer
std::cout << "Height: " << s_height << "\n"; // Displays random integer
std::cout << "Name: " << value << "\n "; // Displays null

这是我的 .ini 文件

[CONFIGURATION]
WIN_NAME="Notepad"
WIN_WIDTH="800"
WIN_HEIGHT="600"

【问题讨论】:

  • 我没有意识到 GetPrivateProfileString 仍然受支持。哇!在 Windows 中真的没有任何东西会消失吗?
  • int s_width = (int)ReadINI("CONFIGURATION", "WIN_WIDTH", 0); 不对。您可能想使用atoi
  • @user4581301 这是使 Windows 成功的原因之一:可靠地确保旧代码不会损坏。

标签: c++ winapi ini


【解决方案1】:

变量 sResult 在函数范围内,它将在堆栈中 一旦你从函数返回,它就会被销毁。

使用 malloc 或从堆分配内存以获取函数外部的值。

这个可以,把ini放到当前工作目录下就可以了。

    char* sResult = new char[255];
    char* ReadINI(const char* sSection, const char* sSub, const char* sDefaultValue)
    {
        memset(sResult, 0x00, 255);
        GetPrivateProfileString(sSection, sSub, sDefaultValue, sResult, 255, ".\\config.ini");
        return sResult;
    }

...

    char pwd[MAX_PATH];
    GetCurrentDirectory(MAX_PATH, pwd);
    MessageBox(NULL, pwd, pwd, 0);
    int s_width = atoi(ReadINI("CONFIGURATION", "WIN_WIDTH", 0));
    int s_height = atoi(ReadINI("CONFIGURATION", "WIN_HEIGHT", 0));
    const char* value = ReadINI("CONFIGURATION", "WIN_NAME", "null");
    std::cout << "Width: " << s_width << "\n"; 
    std::cout << "Height: " << s_height << "\n";
    std::cout << "Name: " << value << "\n "; 

【讨论】:

  • 这正是帖子作者正在做的事情:见 line char* sResult = new char[255];
  • @Rajaganesh 如果sResult 被声明为堆栈上的固定数组,您所说的将是正确的,但事实并非如此。它是通过new[] 在堆上动态分配的
  • 我在测试的时候发现堆空间在函数内外都能正确输出。 OP 的主要问题是强制转换是错误的。其他都很好。
【解决方案2】:

不要将相对路径传递给(Get|Write)PrivateProfile... 函数,您需要传递绝对路径。 PrivateProfile API 将相对路径解释为相对于 Windows 安装文件夹,而不是像您期望的那样与调用进程的当前工作目录相关。这是documented behavior

lp文件名

初始化文件的名称。如果该参数不包含文件的完整路径,则系统在Windows目录中搜索该文件。

您实际上并没有从您的 .ini 文件中读取数据,因此您会返回指定的默认值。

您不能将 char* 指针类型转换为 int 以获取您要查找的数值。您正在打印出char* 指向的内存地址,而不是字符串表示的整数值。您需要解析字符串,例如使用 Win32 StrToInt()、或 C sscanf()、或标准 C++ 库 std::atoi()std::stoi()std::istringstream。在这种情况下,更好的解决方案是改用GetPrivateProfileInt(),让API为您解析。

您还泄漏了您分配的char* 字符串。您应该改用std::string,并让标准 C++ 库为您处理内存管理。

话虽如此,请尝试更多类似的东西:

std::string configFile;

std::string ReadINI_String(const std::string &sSection, const std::string &sSub, const std::string &sDefaultValue)
{
    char sResult[256] = {};
    GetPrivateProfileString( sSection.c_str(), sSub.c_str(), sDefaultValue.c_str(), sResult, 255, configFile.c_str() );
    return sResult;
}

int ReadINI_Int(const std::string &sSection, const std::string &sSub, int iDefaultValue)
{
    return GetPrivateProfileInt( sSection.c_str(), sSub.c_str(), iDefaultValue, configFile.c_str() );
}

...

char path[MAX_PATH] = {};
GetModuleFileNameA(NULL, path, MAX_PATH);
PathRemoveFileSpecA(path);
PathCombineA(path, path, "config.ini");
configFile = path;

...

int i_width = ReadINI_Int("CONFIGURATION", "WIN_WIDTH", 0);
int i_height = ReadINI_Int("CONFIGURATION", "WIN_HEIGHT", 0);
std::string s_value = ReadINI_String("CONFIGURATION", "WIN_NAME", "null");

std::cout << "Width: " << i_width << "\n";
std::cout << "Height: " << i_height << "\n";
std::cout << "Name: " << s_value << "\n";

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2012-06-29
    • 1970-01-01
    • 2020-01-09
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-02-20
    • 2015-10-01
    相关资源
    最近更新 更多