使用 fgets 的输出调用 fopen

Calling fopen with an output from fgets

我正在尝试从另一个文本文件中打开带有 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] = '[=11=]';
    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

failure

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

我也试过了

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

它工作正常,所以我确信这里的相对路径没有问题...

正在将评论复制到答案中。

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

You could improve the printing by enclosing the name in, for example, square brackets:

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

This would show whether there is a newline, or perhaps a carriage return, in the string addr. And that, I suspect, is the cause of your problem. You'd probably see the ] on a different line from the [. Alternatively, you might see the ] at the start of the line and not see the [ at all.

Also, are you compiling and running on a Unix derivative or on Windows? Was the data file ever on a Windows machine? (I guess you're using Linux and the data file came from Windows.)

回应是:

Wow, you are right. [%s]\n shows "]./tst/f/ak/1237743.txt". And yes, I am using Ubuntu but the list.txt file was created from a Windows machine. Is this the source of the problem?

答案是:

That's a carriage return before the newline that you zap. […] Yes — the configuration information you give is the source of your trouble; Windows data on a Unix (Linux, Ubuntu) machine.

The trick of surrounding text strings with marker characters can often diagnose problems like this quite quickly. It's worth remembering.

再一次:

Thank you! So I guess I have to create a whole new list.txt file?

回应是:

You have a couple of options. One would be to create a new file. You could use a conversion utility such as dos2unix to convert the file. Or you could strip newlines or CRLF by using strcspn() instead of strlen(), like this:

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

That will put the null byte at the first CR or LF it encounters, or overwrite the null byte with a null byte if there are no CR or LF characters (so it is safe, even with degenerate data).