【问题标题】:Calling fopen with an output from fgets使用 fgets 的输出调用 fopen
【发布时间】:2017-12-05 04:54:12
【问题描述】:

我正在尝试用来自另一个文本文件的fgets 的输出打开文件。

具体来说,我的“./list.txt”包含我要打开的文件的所有相对路径。

例如,list.txt 是这样的:

./tst/f/ak/1237743.txt
./tst/f/ak/1393387.txt
./tst/f/ak/276317o.txt
./tst/f/ak/44z5938.txt
.
.
.

等等。

我试图从这个“list.txt”中获取一行并将该输出用作另一个 fopen 调用的参数,从而导致打开“./tst/f/ak/1237743.txt”和以此类推。

我做了一个非常简单的代码,看看能不能做到。

这就是我的代码的样子:

int main()
{
    FILE *f;
    f = fopen("./list.txt", "r");
    if(f==NULL){

        printf("failed\n");
        return 1;
    }

    char tmp[255];
    char *addr;
    addr = fgets(tmp, sizeof(tmp), f);
    addr[strlen(addr)-1] = '\0';
    fclose(f);
    printf("%s\n", addr);

    FILE *x;
    x = fopen(addr, "r");
    if(x==NULL){

        printf("failure\n");
        return 1;
    }

    printf("Success\n");

    fclose(x);
}

这是我得到的:

./tst/f/ak/1237743.txt

失败

对我做错的地方有什么帮助吗?

我也试过了

fopen("./tst/f/ak/1237743.txt", "r)

它运行良好,所以我确信这里的相对路径没有任何问题......

【问题讨论】:

  • 您可以通过将名称括在方括号中来改进打印:printf("[%s]\n", addr); 这将显示字符串addr 中是否有换行符或回车符。我怀疑,这就是你的问题的原因。您可能会在与[ 不同的行上看到]。或者,您可能会在行首看到],而根本看不到[。另外,您是在 Unix 衍生版本还是在 Windows 上编译和运行?数据文件曾经在 Windows 机器上吗? (我猜你使用的是 Linux,数据文件来自 Windows。)
  • 哇,你是对的。 [%s]\n 显示“]./tst/f/ak/1237743.txt”。是的,我使用的是 Ubuntu,但 list.txt 文件是从 Windows 机器创建的。这是问题的根源吗?
  • 那是在您切换的换行符之前的回车。您的文件名列表花费了足够长的时间接近 Windows 机器以感染 CRLF 行尾,但您的机器在读取文本文件时不会将 CRLF 行尾转换为换行符。这与您在基于 Unix 的机器上运行是一致的。所以是的——你提供的配置信息是你麻烦的根源; Unix(Linux、Ubuntu)机器上的 Windows 数据。用标记字符包围文本字符串的技巧通常可以很快诊断出这样的问题。值得记住。
  • 谢谢!所以我想我必须创建一个全新的 list.txt 文件...
  • 您有几个选择。一种是创建一个新文件。您可以使用转换实用程序,例如 dos2unix 来转换文件。或者您可以使用addr[strcspn(addr, "\r\n")] = '\0'; 去除换行符或CRLF。这会将空字节放在它遇到的第一个 CR 或 LF 处,或者如果没有 CR 或 LF 字符,则用空字节覆盖空字节(因此它是安全的,即使是退化的数据)。

标签: c fopen fgets


【解决方案1】:

将 cmets 复制到答案中。

基本问题是您的数据文件具有 CRLF(DOS 样式)行结尾,但您在 Unix 机器上工作,它不会将 CRLF 映射到换行符,这与 Windows 机器不同。

您可以通过将名称括在方括号中来改进打印:

printf("[%s]\n", addr);

这将显示字符串 addr 中是否有换行符或回车符。我怀疑,这就是你的问题的原因。您可能会在与[ 不同的行上看到]。或者,您可能会在行首看到 ] 而根本看不到 [

另外,您是在 Unix 衍生版本还是在 Windows 上编译和运行?数据文件曾经在 Windows 机器上吗? (我猜你使用的是 Linux,数据文件来自 Windows。)

回复的是:

哇,你是对的。 [%s]\n 显示“]./tst/f/ak/1237743.txt”。是的,我使用的是 Ubuntu,但 list.txt 文件是从 Windows 机器创建的。这是问题的根源吗?

答案是:

那是在您切换的换行符之前的回车。 […] 是的 — 您提供的配置信息是您的麻烦之源; Unix(Linux、Ubuntu)机器上的 Windows 数据。

用标记字符包围文本字符串的技巧通常可以很快诊断出此类问题。值得记住。

再说一遍:

谢谢!所以我想我必须创建一个全新的list.txt 文件?

回复的对象是:

您有几个选择。一种是创建一个新文件。您可以使用转换实用程序,例如 dos2unix 来转换文件。或者您可以使用strcspn() 而不是strlen() 去除换行符或CRLF,如下所示:

addr[strcspn(addr, "\r\n")] = '\0';`

这会将空字节放在它遇到的第一个 CR 或 LF 处,或者如果没有 CR 或 LF 字符,则用空字节覆盖空字节(因此它是安全的,即使是退化的数据)。

【讨论】:

    猜你喜欢
    • 2014-09-18
    • 1970-01-01
    • 1970-01-01
    • 2018-07-03
    • 1970-01-01
    • 1970-01-01
    • 2011-02-07
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多