0

I'm learning how to use structures in C, and I'm not sure how to scanf user input into a structure... Here's the structure:

typedef struct {
    double x,y;
    char name;  // MUST BE SINGLE UPPERCASE LETTER
} pointType;

typedef struct {
    pointType A, B; // line segment defined by two points
    int slopeDefined;   // 1 if slope is defined and 0 in undefined
    double slope;       // rise/run = y2-y1 / x2-x1
}lineSegType;

Here's the code I'm using to try and copy user input into those fields in the structure:

void getPoint (pointType *P){
    printf("Enter your x-coordinate: ");
    scanf("%lf",&P->x);
    printf("Enter your y-coordinate: ");
    scanf("%lf",&P->y);
}
void getLineSeg (lineSegType *lSeg){
    printf("Enter first point name (single uppercase letter): ");
    scanf("%c",&lSeg->A.name);
    getPoint(&lSeg->A);
    printf("Enter second point name (single uppercase letter): ");
    scanf("%c",&lSeg->B.name);
    getPoint(&lSeg->B);
}

The program skips the "printf("Enter first point name (single uppercase letter): ");" and "printf("Enter second point name (single uppercase letter): ");" and doesn't copy the user entered coordinates to the x and y fields in the structure :/

Codingnoob
  • 25
  • 2
  • Can you post your `main()`? – Jack Lilhammers Mar 26 '21 at 00:00
  • Do you want the whole thing or just main because the functions I shared are called from other functions... – Codingnoob Mar 26 '21 at 00:03
  • To have good answers is better to post a [minimal reproducible example](https://stackoverflow.com/help/minimal-reproducible-example) – Jack Lilhammers Mar 26 '21 at 00:08
  • 2
    `scanf(" %c",&lSeg->A.name);` and `scanf(" %c",&lSeg->B.name);` (note the addition of a `space` before `%c`) The `%c` conversion specifier does NOT skip leading whitespace (the `'\n'` left in `stdin` by the user pressing **Enter**) So the `'\n'` left from `scanf("%lf",&P->y);` is taken as input by `scanf("%c",&lSeg->A.name);` as you have it. (note: `%c`, `%[..]` and `%n` are the only conversion specifiers that do NOT discard leading whitespace) – David C. Rankin Mar 26 '21 at 00:10
  • https://onlinegdb.com/ByHqLo9E_ – Jack Lilhammers Mar 26 '21 at 00:11
  • Ok cool it works now :) thank you – Codingnoob Mar 26 '21 at 00:14
  • Additionally, you cannot use any input function correctly unless you ***check the return***. So change your function type from `void` to, e.g. `int` and validate every `if (scanf("%lf",&P->x) != 1) { fputs ("error: invalid numeric input.\n", stderr); return 0; }` That way you communicate the success or failure of the read back to the calling function. (whether you use `0` or `1` to indicate error is up to you) You also need a way to empty `stdin` in case of a *matching-failure*. (search this site `"[c] scanf matching failure"`) – David C. Rankin Mar 26 '21 at 00:15
  • 1
    @ChrisHappy - if you would like to write it up, I'll leave that to you. Feel free to copy/paste from any of my comments. – David C. Rankin Mar 26 '21 at 00:17

1 Answers1

0

Use scanf(" %c", &ptr);

Note the addition of a space.

The %c conversion specifier does NOT skip leading whitespace (the \n remaining in stdin by the user pressing Enter). So the \n remaining from scanf("%lf",&P->y); is taken as input by scanf("%c",&lSeg->A.name); as you have it.

Note: %c, %[..] and %n are the only conversion specifiers that do NOT discard leading whitespace.

Also, you cannot use any input function correctly unless you check the return. So change your function type from void to a value like int and validate every scanf with:

if (scanf("%lf",&P->x) != 1) {
    fputs ("error: invalid numeric input.\n", stderr);
    return 1; // non zero error code. 0 could also work
} 

That way you communicate the success or failure of the read back to the calling function.

You also need a way to empty stdin in case of a matching-failure. (search this site "[c] scanf matching failure")

https://replit.com/@chrishappy/Debug-copy-user-input-into-a-Structure-in-C#main.c

Chris Happy
  • 7,088
  • 2
  • 22
  • 49