Freopen c ошибка

I started C++ not so long and searched so hard for different ways to read and write from/to files with no result until i tried it out on CodeBlocks which worked.. Images are attached below to point out possible errors in code though the same code were used on both applications.

Error Code: Severity Code Description Project File Line Suppression State Suppression State
Error C4996 'freopen': This function or variable may be unsafe. Consider using freopen_s instead. To disable deprecation, use _CRT_SECURE_NO_WARNINGS. See online help for details. Codeforces C:\Users\owamoyo\source\repos\Codeforces\Codeforces.cpp 6

Code Blocks

#include<bits/stdc++.h>

using namespace std;

int main() {
    freopen("input.txt", "r", stdin);
    freopen("output.txt", "w", stdout);
    int n; cin >> n;
    while (n--) {
        int x; cin >> x;
        cout << x << " ";
    }
    return 0;
}

MS Visual Studio

#include<bits/stdc++.h>

using namespace std;

int main() {
    freopen("input.txt", "r", stdin);
    freopen("output.txt", "w", stdout);
    int n; cin >> n;
    while (n--) {
        int x; cin >> x;
        cout << x << " ";
    }
    return 0;
}

#include <stdio.h>
#include <string.h>
#define MAXN 15
char forbid[MAXN][MAXN];
int dp[2][1<<MAXN],c[1<<MAXN],*dp1,*dp2;
int cnt_one(int x)
{
    int s=0;
    while(x)
    {
        s++;
        x&=x-1;
    }
    return s;
}
int main()
{
    int t,n,s,a,b,i,j,k;
/*This is my use of freopen function*
************************************/
    freopen("datain.txt","r",stdin);
    freopen("dataout.txt","w",stdout);
/*This is just a dynamic program to solve a mathematical problem*
****************************************************************/
    for(i=0;i<(1<<MAXN);i++) c[i]=cnt_one(i);
    scanf("%d",&t);
    while(t--)
    {
        memset(forbid,0,sizeof(forbid));
        memset(dp[0],0,sizeof(int)*(1<<MAXN));
        dp[0][0]=1;
        scanf("%d%d",&n,&s);
        while(s--)
        {
            scanf("%d%d",&a,&b);
            forbid[a][b]=1;
        }
        for(i=1;i<=n;i++)
        {
            if(i%2)
            {
                dp1=dp[0];
                dp2=dp[1];
            }
            else
            {
                dp1=dp[1];
                dp2=dp[0];
            }
            memset(dp2,0,sizeof(int)*(1<<MAXN));
            for(j=0;j<(1<<n);j++)
            {
                if(c[j]!=i-1) continue;
                for(k=0;k<n;k++)
                {
                    if(!(j>>k&1)&&!forbid[i][n-k]) dp2[j^(1<<k)]+=dp1[j];
                }
            }
        }
        printf("%d\n",dp2[(1<<n)-1]);
    }
    return 0;
}

This is my program.I used a dynamic program method to solve a mathematical problem.
But when I used the «freopen» function to redirect the «stdout» stream to the file of «dataout.txt»,it failed and the file had no data in it.
Could you tell me why I can get the data from «datain.txt» but I can’t output data into «dataout.txt»?Is there something wrong with my «freopen» function for «stdout» stream?

plf_colony_test_suite.cpp(236): warning C4996: 'freopen': This function or variable may be unsafe. Consider using freopen_s instead. To disable deprecation, use _CRT_SECURE_NO_WARNINGS. See online help for details.
C:\Program Files (x86)\Windows Kits\10\include\10.0.17763.0\ucrt\stdio.h(243): note: see declaration of 'freopen'

I’m not totally sure if replacing the call by freopen_s would be the best solution here, in particular if that line is supposed to compile on several platforms. Maybe making a local version would work?

TL;DR: Why does freopen(NULL, "rb", stdin) always fail on Windows?

I’m trying to re-implement a base64 encoder in C that takes input from stdin and outputs the encoded equivalent into stdout. I had a problem in my previous post where fread was signalling EOF prematurely. Here is what my main method looks like:

int main(void)
{
    unsigned char buffer[BUFFER_SIZE];
    unsigned char base64_buffer[BASE64_BUFFER];

    while (1)
    {
        TRACE_PUTS("Reading in data from stdin...");
        size_t read = fread(buffer, 1, sizeof(buffer), stdin); /* Read the data in using fread(3) */

        /* Process the buffer */

        TRACE_PRINTF("Amount read: %zu\n", read);
        TRACE_PUTS("Beginning base64 encode of buffer");
        size_t encoded = base64_encode(buffer, read, base64_buffer, sizeof(base64_buffer));

        /* Write the data to stdout */
        TRACE_PUTS("Writing data to standard output");
        ...

        if (read < sizeof(buffer))
        {
            break; /* We reached EOF or had an error during the read */
        }
    }

    if (ferror(stdin))
    {
        /* Handle errors */
        fprintf(stderr, "%s\n", "There was a problem reading from the file.");
        exit(1);
    }

    puts(""); /* Output a newline before finishing */

    return 0;
}

Essentially, it reads in data from stdin using fread, encodes to base64, writes it to stdout, then checks if EOF has been reached at the end of the loop.

When I piped the contents of a binary file to this app’s stdin, it would only read a fraction of the total bytes in the file. For example:

$ cat /bin/echo | my_base64_program >/dev/null # only view the trace output
TRACE: C:/Users/James/Code/c/base64/main.c:23: Reading in data from stdin...
TRACE: C:/Users/James/Code/c/base64/main.c:28: Amount read: 600
TRACE: C:/Users/James/Code/c/base64/main.c:29: Beginning base64 encode of buffer
TRACE: C:/Users/James/Code/c/base64/main.c:43: Writing data to standard output
TRACE: C:/Users/James/Code/c/base64/main.c:23: Reading in data from stdin...
TRACE: C:/Users/James/Code/c/base64/main.c:28: Amount read: 600
TRACE: C:/Users/James/Code/c/base64/main.c:29: Beginning base64 encode of buffer
TRACE: C:/Users/James/Code/c/base64/main.c:43: Writing data to standard output
TRACE: C:/Users/James/Code/c/base64/main.c:23: Reading in data from stdin...
TRACE: C:/Users/James/Code/c/base64/main.c:28: Amount read: 600
TRACE: C:/Users/James/Code/c/base64/main.c:29: Beginning base64 encode of buffer
TRACE: C:/Users/James/Code/c/base64/main.c:43: Writing data to standard output
TRACE: C:/Users/James/Code/c/base64/main.c:23: Reading in data from stdin...
TRACE: C:/Users/James/Code/c/base64/main.c:28: Amount read: 569
TRACE: C:/Users/James/Code/c/base64/main.c:29: Beginning base64 encode of buffer
TRACE: C:/Users/James/Code/c/base64/main.c:43: Writing data to standard output

$ cat /bin/echo | wc -c
28352

As you can see /bin/echo is 28352 bytes long, but only ~2400 of them are being processed. I believe the reason is because stdin is not being considered a binary file, so certain control characters (like Control-Z as mentioned in the linked post’s answer) were prematurely signalling EOF.

I took a look at the base64 source code and it looks like they’re using xfreopen (which is just a wrapper for freopen) to tell fread to interpret stdin as binary. So I went ahead and did that before the while-loop:

if (!freopen(NULL, "rb", stdin))
{
    fprintf(stderr, "freopen failed. error: %s\n", strerror(errno));
    exit(1);
}

However, now my app always exits at that point with:

$ cat /bin/echo | my_base64_program
freopen failed. error: Invalid argument

So why is freopen at that point failing, when it works for base64? I’m using MinGW-w64 with GCC on Windows if that’s relevant.

Why freopen() might fail in general

The C standard says:

If filename is a null pointer, the freopen function attempts to change the mode of
the stream to that specified by mode, as if the name of the file currently associated with
the stream had been used. It is implementation-defined which changes of mode are
permitted (if any), and under what circumstances.

Presumably, your implementation doesn’t allow the changes you’re trying to make. On Mac OS X, for example, the man page for freopen() adds:

The new mode must be compatible with the mode that the stream was originally opened with:

  • Streams originally opened with mode «r» can only be reopened with that same mode.
  • Streams originally opened with mode «a» can be reopened with the same mode, or mode «w».
  • Streams originally opened with mode «w» can be reopened with the same mode, or mode «a».
  • Streams originally opened with mode «r+», «w+», or «a+» can be reopened with any mode.

With that said, on Mac OS X (where b is a no-op anyway), you’d be OK.

Why freopen() fails on Windows specifically

However, you’re on Windows. You need to learn how to find and read the documentation. I use a Google search with the term ‘site:msdn.microsoft.com freopen’ for whatever function I’m looking for. That specific search yields the manual for freopen() where it says:

If path, mode, or stream is a null pointer, or if filename is an empty string, these functions invoke the invalid parameter handler, as described in Parameter Validation. If execution is allowed to continue, these functions set errno to EINVAL and return NULL.

That’s the documented behaviour: it is also the behaviour you are seeing. The manual for your system is helpful. It basically says «thou shalt not».

How to fix the input mode of standard input on Windows

I note that in my answer to your previous question, I pointed to _setmode():

However, it is more likely that you need _setmode():

_setmode(_fileno(stdin), O_BINARY);

This is the advice that is given in the answers to the question that deamentiaemundi pointed to.

I note in passing that the Microsoft manual page for setmode() says:

This POSIX function is deprecated. Use the ISO C++ conformant _setmode instead.

This is a curious comment because POSIX does not standardize a function setmode() in the first place.

You can find Microsoft’s documentation for fileno(). It too has the spiel about POSIX (but this time it is accurate; POSIX does specify fileno()) and refers you to _fileno().

The freopen function in C++ is a powerful tool for redirecting standard input and output to files, but it can sometimes lead to errors when reading and writing to those files. In this article, we will explore the common errors that can occur when using freopen and how to resolve them.

Understanding freopen

Before diving into the errors that may occur with freopen, it is important to first understand what the function does. freopen is a C++ function that redirects standard input and output streams to specified files. It takes three parameters: the filename, the mode, and the stream.

The filename parameter is the name of the file to which the stream will be redirected. The mode parameter specifies whether the file will be opened for reading or writing. Finally, the stream parameter is the standard input or output stream that will be redirected.

Here is an example of how to use freopen to redirect standard input to a file named input.txt:

freopen("input.txt", "r", stdin);

Errors That Can Occur with freopen

While freopen is a powerful tool, it is important to use it correctly to avoid errors. The most common errors that can occur when using freopen include:

File Not Found Error

One common error that can occur when using freopen is the «file not found» error. This occurs when the specified file does not exist or cannot be opened. To resolve this error, make sure that the file exists and that you have the correct file path.

Read/Write Errors

Another common error that can occur with freopen is a read/write error. This occurs when there is an issue with reading or writing to the file.

To resolve this error, make sure that you have the correct permissions to read and write to the file. Additionally, ensure that the file is not already opened by another process and that the file is not being read or written to simultaneously by multiple threads.

Memory Leak Error

Finally, one less common but still important error that can occur when using freopen is a memory leak error. This occurs when memory is allocated for the file stream but is never deallocated.

To resolve this error, make sure that you manually deallocate the file stream using the fclose function when you are finished with it. This will free up the memory that was allocated for the stream.

Conclusion

freopen is a powerful function that can be used to redirect standard input and output to files, but it is important to use it correctly to avoid errors. The most common errors that can occur when using freopen include file not found errors, read/write errors, and memory leak errors. By understanding the potential errors and how to resolve them, you can use freopen effectively and avoid any issues with reading and writing to files in C++.

Понравилась статья? Поделить с друзьями:
  • Frenic eco ошибки
  • Frenic 5000g11 ошибка ou2
  • Frenic 5000g11 коды ошибок
  • Freightliner ошибка ecu 128
  • Freestyle libre коды ошибок