1

我在Lubuntu上使用 Oracle 的VirtualBox在虚拟机上运行它。我认为这不会影响任何事情,但我只是认为值得一提。

似乎错误出现在以下函数返回的字符串末尾附加的奇怪符号中:

inline std::string f_settings_get(std::string val){
    int index=0;
    while(strcmp(val.c_str(),f_settings[0][index].c_str())!=0){
        index++;
    };
    // For debugging purposes - printf("\n%s\t%s",f_settings[0][index].c_str(),f_settings[1][index].c_str());
    return f_settings[1][index];
}

我看不出这个函数有问题,因此相信它可能是由存储在变量中的数据引起的。

我一直在尝试使用在我的程序中打开一个文件,fopen并且遇到了标题中所述的错误。该代码在 Windows 中完美运行(我已经考虑了每个操作系统的/和);\但是,在 Linux 上运行时,虽然它编译得很好,但我得到文件不存在的错误。我在网上查了一下,发现其他人有几个问题,例如:

  1. 文件名不是真正正确的文件名

  2. 没有访问文件的权限

  3. 只需调用“file.txt”而不是整个目录即可访问文件

我使用提供的Python脚本检查了第一个,并使用新名称重新创建文件。那没有用(并且 Python 脚本显示文件名很好)。

我将所有权限设置为 777 usingchmod -R 777 clesis但这不起作用(尽管我没想到它是权限问题,因为它说该文件不存在)。

我已经调用了完整路径并仔细检查了路径。它是正确的。

最后,我在代码中运行了以下代码以仔细检查:(a) 文件存在,(b) 我试图打开正确的文件。

    tmp_s="";
    tmp_s = homeDir+binP+f_settings_get("xxxxx"); // Note, you can easily get whatever variable you want using either f_settings_get or num_settings_get
    tmp_file = fopen(tmp_s.c_str(), "r+");
    printf("\n Running the following command: /home/xxxxx/programming/xxxxx/bin\n");
    std::system("ls -l /home/xxxxx/programming/xxxxx/bin");
    getWait();
    printf("\n Tried to open: %s", tmp_s.c_str());
    if (tmp_file == NULL){
        printf("\n");
        perror("Error loading dimensions.sim");
        printf("Press enter to exit...");
        getWait();
        exit(1);
    }

以下是输出的外观(抱歉审查内容。我向您保证用户名和文件夹的拼写相同):

输出显示以下内容:

Filenames Loaded...

Loading Settings from sim file...
++++++++++++++++++++++++++++++++++++++++++++++++++ Settings Loaded...

Loading System Dimensions from sys file...
--------------------------------------------------
 Running the following command: /home/xxxxx/programming/xxxxx/bin
total 636
-rwxrwxrwx 1 xxxxx xxxxx    958 Jul 25 20:59 dimensions.sim

Tried to open: /home/xxxxx/programming/xxxxx/bin/dimensions.sim

Error loading dimensions.sim: No such file or directory
Press enter to exit...

如果文件路径直接指定为“bin/dimensions.sim”或“/home/xxxxx/programming/xxxxx/bin/dimensions.sim”,那么它可以正常工作。这使我得出一个令人困惑的结论。tmp_s在从 a转换为 a 的某个地方std::string存在c_str导致错误目录路径的问题。但是,我正在使用的任何其他文件都不会发生这种情况,而且我在 Windows 机器上从未遇到过这个问题。因此,我对可能导致它的原因感到困惑。

最后一个观察结果 - 无论如何都使用printf("tmps = %s",tmp_s.c_str());. 可以清楚地看出这并不“奇怪”。

4

1 回答 1

4

您的问题很可能来自杂散回车(十六进制0D,通常用\rC 编写),这在使用 unix-y 库读取 windows-y 文件时很常见。Windows 文件的行以 CR-LF, hex 结尾0D0A,而 unix 只使用单个 LF, hex 0A\n对于未以二进制模式打开的文件,Windows C stdio 会将 CRLF 映射到单个 LF ( ) 上。在 Unix 中,文件是以二进制还是 ASCII 模式打开并不重要,因为不会发生重新映射。

结果就是同样的程序在Windows上编译的程序可以读取Windows文件,而在Unix上编译可以读取Unix文件;在这两种情况下,行终止符都会看起来像一个\n. Windows 程序通常也可以读取 Unix 文件。但是读取 Windows 文件的 Unix 程序会在每行的末尾看到一个杂散的 CR, \r, hex 。0D

这尤其困扰配置实用程序。假设您有一个如下形式的配置文件:

some_setting=27
some_file=dimensions.sim

等等

现在,配置读取器读取每一行,将其拆分为=,并将第一部分用作键,将第二部分用作值。它甚至可能将一些值转换为数字。

现在,如果文件是在 Windows 上创建的(不管它当前是在 Windows 上还是在您的笔记本电脑上),Unix 配置阅读器将看到as的值和some_settingas27\r的值。除非配置系统偏执,否则第一个不会引起任何问题,因为and转换为第一个非数字字符,只要至少有一个数字就不要抱怨。但是该字符串不能用作文件名,因为文件名不太可能以 a结尾。some_filedimensions.sim\ratoistrtod\r

使这个问题特别阴险的是,当您尝试打印有问题的字符串时,\r实际上充当回车符;也就是说,它将光标返回到行首。如果下一个输出字符是\n,则\r完全不可见。如果下一个输出是一些消息,它将被套印在行上,这非常令人困惑。

于 2013-07-26T02:53:49.370 回答