【问题标题】:Run getline every time a file is modified每次修改文件时运行 getline
【发布时间】:2015-06-09 10:17:25
【问题描述】:

我的程序目前正在做的是读取一个文本文件,然后在屏幕上显示内容。我想要它做什么,每次更改文件时读取文件,然后刷新屏幕并显示新文件内容。我试图实现一个循环,但在尝试运行时出现异常错误。这是我当前的循环设置:

    void number(HWND hwnd){
    HANDLE dwChangeHandles[2];
    char path[250];
    ExpandEnvironmentStrings("%AppData%\\\ECDisplay\\", path, 250);
    char versionpath[250];
    ExpandEnvironmentStrings("%AppData%\\\ECDisplay\\nursery.txt", 
    versionpath, 250);
    std::ifstream file(versionpath);
    std::string str;
    while (std::getline(file, str)){
        nurserynumber = str;
        file.close();
    }
    dwChangeHandles[0] = FindFirstChangeNotification(
        path,                         // directory to watch 
        FALSE,                         // do not watch subtree 
        FILE_NOTIFY_CHANGE_LAST_WRITE); // watch file name changes 

    if (dwChangeHandles[0] == INVALID_HANDLE_VALUE)
    {

    }
    else{
        number(hwnd);
    }
}

编辑 我最初收到的错误: EC Display.exe 中 0x7789EA0B (ntdll.dll) 处未处理的异常:0xC0000374:堆已损坏(参数:0x778D4270)。

编辑 2 这是我当前的代码:

void number(HWND hwnd){
    HANDLE dwChangeHandles[2];
    char path[250];
    ExpandEnvironmentStrings("%AppData%\\\ECDisplay\\", path, 250);
    char versionpath[250];
    ExpandEnvironmentStrings("%AppData%\\\ECDisplay\\nursery.txt", 
    versionpath, 250);
    std::ifstream file(versionpath);
    std::string str;
    dwChangeHandles[0] = FindFirstChangeNotification(
        path,                         // directory to watch 
        FALSE,                         // do not watch subtree 
        FILE_NOTIFY_CHANGE_LAST_WRITE); // watch file name changes 
    do{
    while (std::getline(file, str)){
        nurserynumber = str;    
    }

    } while (dwChangeHandles[0] != INVALID_HANDLE_VALUE);
}

【问题讨论】:

  • 没有足够的信息来帮助找到崩溃,但是在while(getline) 循环中关闭文件对你没有多大好处。
  • 如果你阅读FindFirstChangeNotification documentation,你会发现你需要在返回的句柄上使用“等待函数”来获得任何类型的实用程序。

标签: c++


【解决方案1】:

至少有两件事可能导致您的崩溃,但没有额外信息我们只能猜测。

你在一个循环中关闭文件描述符:

while (std::getline(file, str)) {
    ...
    file.close();
}

这在很多方面似乎确实是错误的。

您似乎更有可能想要

if (!file.good()) {
    // handle error
    return;
}
if (!std::getline(file, str)) {
    // didn't read anything, if we care:
    return;
}

其次,您似乎在使用递归。

在函数接近尾声时,您调用函数时调用的参数相同,而不是仅仅执行循环:

if (dwChangeHandles[0] == INVALID_HANDLE_VALUE) {
}
else{
    number(hwnd);
}

如果文件没有打开,你会做一些错误处理,否则,你会再次调用该函数。每次调用都会使用额外的堆栈,最终您将耗尽堆栈并崩溃。

您可能应该重构代码以使用循环。例如,您可以将其设为

do {
    // ...
} while (dwChangeHandles[0] != INVALID_HANDLE_VALUE);

在整个函数内部循环。

您在函数中声明的所有变量每次调用都需要堆栈空间,因此每次调用自身时都会使用越来越多的堆栈。在其中一个调用返回并且堆栈展开之前,之前调用中的变量不会超出范围。

【讨论】:

  • 之后我的窗口打不开。没有任何错误,但是我在程序启动时调用了这个函数,现在程序继续运行,但没有窗口显示。
  • "after doing that" 实际上并没有告诉我您做了什么,我建议您在最初的问题末尾发布修改后的代码(添加“--- EDIT ---”然后发布代码)。如果您需要快速帮助,您应该发布一个 MVCE stackoverflow.com/help/mcve
  • "getline 返回对字符串的引用" - 不是这样 - 它返回对 (if) 流参数的引用:检查是否字符串已成功读取:您已在 std::getline(file, str); if (str.empty()) { 重写中删除了该字符串。不过,你说得对,file.close() 不应该在那里——这意味着只有第一行被读取,如果这是我们想要的,那么没有理由使用while 循环。
  • @dogger20011 好的,不确定您要发布多少代码,但 FindFirstChangeNotification 所做的只是创建一个侦听器。您实际上必须等待并检索通知。见msdn.microsoft.com/en-us/library/windows/desktop/…
【解决方案2】:

您在阅读 1 行后关闭文件:

while (std::getline(file, str)){
    nurserynumber = str;
    file.close();  // ?????
}

因此,当您再次使用 getline 时,文件不再是有效的文件流。 我想你想要file.close() 之外的while,不是吗?

【讨论】:

  • ...但它以nurserynumberstr 中的文件的最后一行结束,这可能也不需要:代码太糟糕了,无法推理。
  • 那个也是。但要解决异常,这是他们需要的修复。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2019-12-24
  • 2021-09-17
  • 1970-01-01
  • 2019-04-27
  • 2020-02-03
  • 1970-01-01
  • 2016-11-04
相关资源
最近更新 更多