0

I have a while loop in my main function which calls a user defined function which calls another user defined function which calls scanf to read a pair of double values. I want my program to end when a non-numeric is entered. I have my functions returning structures, and not 0/1. Is there a way to pass a false scanf return all the way through to break my while loop?

Can I declare a global variable and assign it to the scanf statement and then make an if statement about that variable in the main function? Or will I have to change my functions to return int (0/1) and pass in my structures by reference?

This is probably a really bad explanation so here's my code for the parts involved in my question... The program is meant to read in a rectangle (by bottom left point and top right point) and a circle and say if their areas overlap. And I'm looking to put a break in the while loop in the main function...

typedef struct{double x,y;} point;
typedef struct{point a,b,c,d;} rectangle;
typedef struct{point o; double r;} circle;

point readPoint(){
    point p;
    scanf("%lf%lf", &p.x, &p.y);     //type "quit"
    return p;
}

rectangle readRectangle(){
    rectangle r;
    r.c=readPoint();
    r.b=readPoint();
    r.a.x=r.c.x;
    r.a.y=r.b.y;
    r.d.x=r.b.x;
    r.d.y=r.c.y;
    return r;
}

int main(void) {
    int a=0;
    rectangle r;
    circle c;

    while(1){
        printf("Enter rectangle:");
        r=readRectangle();            //break loop here if quit is entered
        printf("Enter circle:");
        c=readCircle();
        a=overlap(r, c);
        if (a==1)
            printf("The rectangle and the circle overlap.\n\n");
        else
            printf("The rectangle and the circle do not overlap.\n\n");
    }
    printf("Program completed normally.");
    return EXIT_SUCCESS;
}
5
  • 1
    You have already listed some of the main options. Just go ahead and pick one of them. I personally would not recommend using a global but would go with the return value approach. Commented Mar 17, 2016 at 2:58
  • Using global variable is not good unless it is necessary. Commented Mar 17, 2016 at 2:59
  • another option add one more item in the structure. Commented Mar 17, 2016 at 3:01
  • bansai, can you elaborate on this a little bit? do you mean adding another item into the point structure? like a string to read quit? would that not affect the rest of the times i use that structure? Commented Mar 17, 2016 at 3:12
  • I'd make point *readPoint(point *p), then check the return of scanf and if (scanf("%lf%lf", &p->x, &p->y) < 2) return NULL; return p; and continue that logic back up the chain. Commented Mar 17, 2016 at 3:18

4 Answers 4

2

Redefine your readPoint() and readRectangle() functions more like this:

#include <stdbool.h>
#include <stdio.h>

typedef struct { double x, y; } point;
typedef struct { point a, b, c, d; } rectangle;   

bool readPoint(point *p)
{
    if (scanf("%lf%lf", &p->x, &p->y) != 2)
        return false;
    return true;
}

bool readRectangle(rectangle *r)
{
    if (!readPoint(&r->c) || !readPoint(&r->b))
        return false;
    r->a.x = r->c.x;
    r->a.y = r->b.y;
    r->d.x = r->b.x;
    r->d.y = r->c.y;
    return true;
}

int main(void)
{
    while (1)
    {
        rectangle r;
        printf("Enter rectangle: ");
        if (!readRectangle(&r))
            break;   
        …
    }
    return 0;
}

This is one of the strategies you outlined — it is probably the best. You could continue to return the structures and pass a status variable in via a pointer (point readPoint(int *status)) — it would work, though it isn't the conventional way to do it.

A more outré technique would use setjmp() and longjmp() from <setjmp.h>; you'd call setjmp() in the main() function, and call longjmp() when your input code detected a problem. I'd not recommend this — just outlining an alternative.

Yes, you could abbreviate readPoint() to:

bool readPoint(point *p)
{
    return scanf("%lf%lf", &p->x, &p->y) == 2;
}
Sign up to request clarification or add additional context in comments.

3 Comments

Much less modification than handling pointers back up from readPoint.
r.a.x=r.c.x; r.a.y=r.b.y; r.d.x=r.b.x; r.d.y=r.c.y; the compiler doesnt realize these are part of a structure.... do they have to be pointers too?... pointers confuse me still
I had to fix my version of your code to use r->a.x, etc. because r is now a rectangle * instead of a rectangle structure. I did that a while ago, though.
1

So as bad of an idea this is, I'm going to provide the literal answer to this question. Yes, you can do this. You had better have a darn good reason to do this because or others will scream in horror at the code you have created.

#include <stdio.h>
#include <setjmp.h>

typedef struct{double x,y;} point;
typedef struct{point a,b,c,d;} rectangle;
typedef struct{point o; double r;} circle;

point readPoint(jmp_buf jmp){
    point p;
    if (scanf("%lf%lf", &p.x, &p.y) != 2)     /*type "quit"*/
        longjmp(jmp, 1); /* returns to setjmp() call with 1 */
    return p;
}

rectangle readRectangle(jmp_buf jmp){
    rectangle r;
    r.c=readPoint(jmp);
    r.b=readPoint(jmp);
    r.a.x=r.c.x;
    r.a.y=r.b.y;
    r.d.x=r.b.x;
    r.d.y=r.c.y;
    return r;
}

int main(void) {
    jmp_buf jmp;
    if (setjmp(jmp) == 0) {
        while(1){
            int a=0;
            rectangle r;
            circle c;
            printf("Enter rectangle:");
            r=readRectangle(jmp);
            printf("Enter circle:");
            c=readCircle(jmp);
            a=overlap(r, c);
            if (a==1)
                printf("The rectangle and the circle overlap.\n\n");
            else
                printf("The rectangle and the circle do not overlap.\n\n");
        }
    }
    printf("Program completed normally.");
    return EXIT_SUCCESS;
}

1 Comment

Learning by counter-example, priceless!
0

I would have your readPoint method return 0/1 to indicate a success or fail reading then pass your result back by reference.

This keeps your data clean, as opposed to passing an isBadData flag with every result.

Comments

0

You'll need a little modification in readPoint().

point readPoint(){
int s;
point p;
s=scanf("%lf%lf", &p.x, &p.y);
if(s==0) exit(EXIT_FAILURE);
return p;
}

If the values are not entered or if they are not as per the format then s=0 as it is the value returned by scanf(). For more information visit http://www.cplusplus.com/reference/cstdio/scanf/

Include stdlib.h header file to use exit function.

2 Comments

Unilaterally exiting from in a library function is seldom a good idea.
yepp it's not a good idea, anyways it works in case of this program.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.