-1

Please look at the following code:

#include <stdio.h>
#include <graphics.h>
#include <conio.h>
using namespace std;
void drawrect()
{
    int gdriver = IBM8514, gmode;
    initgraph(&gdriver, &gmode, "");
    rectangle(500, 500, 700, 700);
    getch();
    cleardevice();
    closegraph();
}
int main()
{
    int f=1;
    while(f)
    {
        char c;
        printf("Press \"e\" to end, and any other character to draw a rectangle");
        scanf("%c",&c);
        c=='e' ? f=0:f=1;
        drawrect();
        fflush(stdin);
    }
}

at the first time when I run this program, It works correctly and draws a rectangle, but after the first time, the rectangle function doesn't work and the GUI screen is completely blank, While I've cleared and closed previous graphic

So why it doesn't work at second time?

Spektre
  • 49,595
  • 11
  • 110
  • 380
  • 2
    The `` header and that library have its beginning in the DOS age, and has been outdated for a very long time. Drawing in modern UIs is, unfortunately, much more complicated but there are also many libraries which can simplify it quite a lot. Look forward instead of backward, it will give you better experiences and prepare you better for the future. – Some programmer dude Jan 21 '19 at 17:24
  • 2
    There are also a few other things that you need to learn. For example that the C specification explicitly mention calling `fflush` on an input-only stream (like `stdin`) as *undefined behavior*. And `c=='e' ? f=0:f=1;` would be better as `f = (c == 'e' ? 0 : 1);` – Some programmer dude Jan 21 '19 at 17:25
  • @Someprogrammerdude Thank you very much, But I don't need very advanced and high quality graphic features, It is a simple program and according to my limited time, I prefer using graphics.h, but you are correct, It is an out dated library, But now is the best choice for me because of my limited time. – Sania Sadian Jan 21 '19 at 17:27
  • 1
    If you have limited time, don't waste it on something that's been obsolete for 25 years. – Shawn Jan 21 '19 at 17:33
  • @Shawn It is a homework :| – Sania Sadian Jan 21 '19 at 17:34
  • @Shawn I mean I have a limited time to do this homework. I think you had a misunderstand. – Sania Sadian Jan 21 '19 at 17:41
  • regarding: `#include ` `conio.h` is a non portable header file, found only on windows. Strongly suggest using the C library functions – user3629249 Jan 21 '19 at 17:51
  • regarding: `drawrect();` 1) doesn't that require some parameters? similar to: `rectangle(int left, int top, int right, int bottom);` 2) shouldn't it be followed by `refresh()` 3) isn't there the function: ` char *grapherrormsg( int errorcode );` that should be very helpful when something goes wrong – user3629249 Jan 21 '19 at 17:52
  • @user3629249 Thanks, But how to refresh? – Sania Sadian Jan 21 '19 at 17:57
  • forget about `refresh` Rather read the documentation for `graphics.h` found at [drawrectangle](https://www.geeksforgeeks.org/draw-rectangle-c-graphics/) Note the details that the posted code skipped – user3629249 Jan 21 '19 at 18:07
  • regarding: `using namespace std;` this is a C++ statement and should not be in a C program – user3629249 Jan 21 '19 at 18:11
  • @user3629249 You made me more confuse, Would mind saying explicitly what is the problem of my code? – Sania Sadian Jan 21 '19 at 18:23
  • 2
    using `graphics.h` is the main problem. That library was written for MS-DOS, not windows – user3629249 Jan 21 '19 at 21:50

2 Answers2

1

You code has undefined behaviour. The call to initgraph

int gdriver = IBM8514, gmode;
initgraph(&gdriver, &gmode, "");

should pass a pointer to the graphics mode you want to use. This page describes the function and its arguments, and about the mode it says:

*graphmode is an integer that specifies the initial graphics mode (unless *graphdriver equals DETECT; in which case, *graphmode is set by initgraph to the highest resolution available for the detected driver). You can give *graphmode a value using a constant of the graphics_modes enumeration type, which is defined in graphics.h and listed below.

graphdriver and graphmode must be set to valid values from the following tables, or you will get unpredictable results. The exception is graphdriver = DETECT.

But you have not set the mode, and as the second paragraph quoted says, the result is unpredictable. This can be: working how you intended, not working, working strangely, or frying the processor.

So set the graphics mode you want to use with say

int gdriver = IBM8514, gmode = 0;

or whatever mode you need to use. Alternatively you can tell the system to detect for itself, in which case you can use

int gdriver = DETECT, gmode;
Weather Vane
  • 33,872
  • 7
  • 36
  • 56
  • Thanks but It doesn't change anything – Sania Sadian Jan 21 '19 at 18:53
  • So what was the error status from calling `initgraph`? As described in the [above link](https://www.cs.colorado.edu/~main/bgi/doc/initgraph.html) and [here](https://www.cs.colorado.edu/~main/bgi/doc/graphresult.html). – Weather Vane Jan 21 '19 at 19:20
  • It returns grOk but the windows is blank and there is no rectangle – Sania Sadian Jan 21 '19 at 19:27
  • Perhaps unrelated to the graphics function, please see [scanf() leaves the newline char in the buffer](https://stackoverflow.com/questions/5240789/scanf-leaves-the-new-line-char-in-the-buffer). The `getch()` in `void drawrect()` will read the newline left in the buffer, after `scanf("%c",&c);` Function `fflush(stdin)` is defined in your system (but not by the C standard), but it is in the wrong place. – Weather Vane Jan 21 '19 at 19:29
  • I've added a `fflush(stdin);` after scanf but still there is no change. – Sania Sadian Jan 21 '19 at 19:31
  • I wish you luck in finding someone who can actually run your code. – Weather Vane Jan 21 '19 at 19:33
  • OT: rather than calling `fflush( stdin );` Much more portable to use: `int ch; while( ( ch = getchar() ) != EOF && ch != '\n' ){;}` – user3629249 Jan 21 '19 at 21:56
0

Init and close should be called just once and not be called in the drawrect but usually in the main instead ... also having getch in rendering routine makes no sense too...

I will not touch other issues here of your code as I am not coding console stuff for years and BGI even longer but I would start with reordering the code to this:

#include <stdio.h>
#include <graphics.h>
#include <conio.h>
using namespace std;
void drawrect()
{
    rectangle(500, 500, 700, 700);
}
int main()
{
    int f=1;

    int gdriver = IBM8514, gmode;
    initgraph(&gdriver, &gmode, "");

    while(f)
    {
        char c;
        printf("Press \"e\" to end, and any other character to draw a rectangle");
        scanf("%c",&c);
        c=='e' ? f=0:f=1;
        drawrect();
        getch();
        fflush(stdin);
    }

    cleardevice();
    closegraph();
}

Also in future address the library by its real name BGI because graphics.h has no meaning as almost all gfx api/libs got a file with that name ...

Spektre
  • 49,595
  • 11
  • 110
  • 380