How to break an input statement with KEY_ESCAPE ? in 'C'

Oct 16, 2020 at 11:31am
How to check if user pressed KEY_ESCAPE ? If user type something and change his mind and wana return to prev. menu I want to add ESC key from keyboard and anytime if that ESC is pressed, it breaks the input statement.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
void adaugaInfoApa(struct INFO* info, struct TIMP* timp)
{
    BOOL found = FALSE;
    FILE *file;
    char fname[MAX] = "apa.c";
    char temp[MAX];
    file = fopen(fname, "a+");

    system("cls");
    printf("\n\t\t\t\tCENTRU INDEX\n\t\t\t\t------------");
    printf("\n\n\n\tSectiunea Adauga Info apa\n\t-------------------------\n\n");
    printf("\n\n   Introduceti Metri cubi:  ");
    scanf("%30s", temp);

    fseek(file, 0, SEEK_END);
    long size = ftell(file);

    do
    {
        rewind(file);
        while(fscanf(file, "%15s", info->apa) == 1)
        {
            if(strcmp(temp, info->apa) == 0)
            {
                found = TRUE;
                printf("\n\n   Indexul introdus exista deja");
                Sleep(1500);
                system("cls");
                fclose(file);
                AdaugaInfo();
            }
        }
        if(!found)
        {
            rewind(file);
            printf("\n\n\n\tData\n\t----");
            printf("\n\n   Ziua:  ");
            scanf("%30s", timp->zi);
            printf("\n\n   Luna:  ");
            scanf("%30s", timp->luna);
            printf("\n\n   Anul:  ");
            scanf("%30s", timp->an);

            fprintf(file, "%s   |   %s   |   %s   | %s\n", temp, timp->zi, timp->luna, timp->an);

            fclose(file);

            system("attrib +h +s apa.c");

            printf("\n\n\n\tIndexul au fost salvate in baza de date");
            Sleep(2000);
            system("cls");
            AdaugaInfo();
        }
    }while(size != 0);
}
Last edited on Oct 16, 2020 at 11:39am
Oct 16, 2020 at 11:33am
The input is on line 13 from there I wanna check if KEY_ESCAPE was pressed while scanf().
Last edited on Oct 16, 2020 at 11:36am
Oct 16, 2020 at 11:51am
Hello Mif,

I tried to compile your program to do some tests, but what you left out just leaves the code full of errors and I do not know what to put to correct them.

Please provide enough code that can be compiled and tested.

On line 13 you do a "scanf()", but if you press "Esc" what do you get in the string?

Hard to check for what you do not know.

The "Esc" like other special keys are made up of 2 characters. The first character is something you need to account for, but not something that you need to use. The second character is what defines the key that was pressed.

That is what I wanted to check for to see what is put in the variable "temp", but can not.

Andy
Oct 16, 2020 at 12:05pm
Oct 16, 2020 at 12:09pm
Ohh I see , well the code has like 1700 lines.. duno if I can put it all together, but if I press the ESC key while the scanf is running it's deleting all I have typed.

But I'll try to make it short and reedit that function in the main().. to make that properly work for anywho wants to check it
Oct 16, 2020 at 12:11pm
Ohh okay Thomas, I understand your point, I'll try to use _kbhit().. thank you for your answer.
Last edited on Oct 16, 2020 at 12:12pm
Oct 16, 2020 at 3:04pm
Okay I change a bit my example, with this:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
#include <stdio.h>
#include <conio.h>
#include <windows.h>

#define ARRAYSIZE(sel) (sizeof(sel) / sizeof(sel[0]))
#define MAX         1000
#define SELECT_END  2
#define KEY_UP      72
#define KEY_DOWN    80
#define KEY_ENTER   13
#define KEY_ESCAPE  27

void regName();
void hideCursor();
void selector(unsigned int  select);

int main()
{
    hideCursor();

    int select = 0;
    int x;

    selector(select);

    while((x = _getch()))
    {
        if(x == KEY_UP)
        {
            select -= 2;
            if(select < 0)
                select = 0;
            selector(select);
        }
        else if(x == KEY_DOWN)
        {
            select += 2;
            if(select > SELECT_END)
                select = SELECT_END;
            selector(select);
        }
        else if(x == KEY_ENTER)
        {
            if(select <= 1)
            {
                regName();
                selector(select);
            }
            else if(select <= 2)
            {
                printf("\n\n\n\n\t    Exit program");
                Sleep(1500);
                exit(0);
            }
        }
    }
}

void selector(unsigned int select)
{
    const char *selection[] =
    {
        "\n\n\t  [REGISTER  NAME]",
        "\n\n\t   register  name",
        "\n\t       [EXIT]",
        "\n\t        exit",
    };

    unsigned int i;

    system("cls");
    printf("\n\n\t\tMENU\n\t\t----\n\n");

    for(i = 0; i < ARRAYSIZE(selection); i += 2)
    {
        if(i == select)
            printf("%s\n", selection[i]);
        else
            printf("%s\n", selection[i + 1]);
    }

}

void hideCursor()
{
    HANDLE cursorHandle = GetStdHandle(STD_OUTPUT_HANDLE);
    CONSOLE_CURSOR_INFO info;
    info.dwSize = 100;
    info.bVisible = FALSE;
    SetConsoleCursorInfo(cursorHandle, &info);
}

void regName()
{
    BOOL found = FALSE;
    FILE *file;
    char fname[MAX] = "Name.txt";
    char name[MAX];
    char temp[MAX];
    file = fopen(fname, "a+");

    system("cls");
    printf("\n\n\tEnter name: ");
    scanf("%20s", temp);

    fseek(file, 0, SEEK_END);
    long size = ftell(file);

    do
    {
        rewind(file);
        while(fscanf(file, "%20s", name) == 1)
        {
            if(strcmp(temp, name) == 0)
            {
                found = TRUE;
                printf("\n\n\t   Name already exists.");
                Sleep(1500);
                system("cls");
                fclose(file);
                return;
            }
        }
        if(!found)
        {
            rewind(file);
            fprintf(file, "%s\n", temp);
            printf("\n\n\t   Name registered.");
            Sleep(1500);
            system("cls");
            fclose(file);
            return;
        }
    }while(size != 0);
}


Now the void regName() take place of void adaugaInfoApa(struct INFO* info, struct TIMP* timp), and if you compile works.

My point was how to skip enter a name at line 104 , if I hit ESC ?
Last edited on Oct 16, 2020 at 3:05pm
Oct 16, 2020 at 3:07pm
I mean.. if user change his mind and wanna go back to menu when scanf() is runing.
Oct 16, 2020 at 3:16pm
NOT TRIED, but something like:

1
2
3
4
5
6
7
8
9
10
11
printf("\n\n\tEnter name: ");

const char inp = _getch();

if (inp == KEY_ESCAPE)
    return;

temp[0] = inp;
putchar(inp);

scanf("%19s", temp + 1);

Last edited on Oct 16, 2020 at 4:48pm
Oct 16, 2020 at 5:16pm
Your idea works seeplus, but not 100%. The first time
Enter name:
appears you can hit ESC and it returns to the menu, BUT if you hit ONE single key instead of ESC you cannot turn back. If the user hits ESC after a key pressed the effect is that... all your input erase, but not the first char
Last edited on Oct 16, 2020 at 5:17pm
Oct 16, 2020 at 5:55pm
That's by design........ If you want ESC to work anywhere in the input, then something like this [NOT TRIED - for array of 20 chars]

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
	char temp[20];

	printf("\n\n\tenter name: ");

	for (int t = 0; t < 19; ) {
		const char inp = _getch();

		if (inp == KEY_ESCAPE) {
			temp[0] = 0;
			break;
		}

		if (inp == '\n' || inp == '\r') {
			temp[t] = 0;
			putchar('\n');
			break;
		}

		putchar(inp);

		if (inp == '\b') {    // backspace
			if (t > 0) {
				putchar(' ');
				putchar('\b');
				--t;
				temp[t] = 0;
			}
			continue;
		}

		temp[t++] = inp;
	}

	temp[19] = 0;

	printf("!%s!\n", temp);


You may need to change this about a bit to get it to work as you want......
Last edited on Oct 16, 2020 at 6:14pm
Oct 17, 2020 at 8:19am
Consider this. I've now a chance to try it and changed it a bit and made it into a function. str will always be null-terminated (even when input exceeds size) and the return value is the number of entered chars (excludes the terminating null). sz is the total size of the str memory (including the terminating null). I've also added CTR_X which clears the line. ESC will now terminate if entered anywhere. Note that CTRL_C no longer works to terminate the program. The advantage of doing input like this, of course, is that you can make your own line editor. The next things you may want to add are left/right arrow, delete, home/end etc etc. These aren't that difficult to add.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
#define KEY_ESCAPE 27
#define CTR_X 24

#include <conio.h>
#include <stdio.h>

int getstr(char* str, int sz)
{
	const int szl = sz - 1;
	int t = 0;

	while (t < szl) {
		char inp = _getch();

		if (inp == KEY_ESCAPE) {
			inp = '\n';
			t = 0;
		}

		if (inp == '\n' || inp == '\r') {
			str[t] = 0;
			putchar('\n');
			break;
		}

		if (inp == CTR_X) {
			for (; t > 0; --t)
				printf("\b \b");

			str[0] = 0;
			continue;
		}

		if (inp == '\b') {    // backspace
			if (t > 0) {
				printf("\b \b");
				str[--t] = 0;
			}

			continue;
		}

		if (inp >= ' ')
			putchar(str[t++] = inp);
	}

	str[szl] = 0;

	if (t == szl)
		putchar('\n');

	return t;
}

int main() {
	char temp[20];

	printf("enter name: ");

	int l = getstr(temp, 20);

	printf("%d  !%s!\n", l, temp);
}

Last edited on Oct 17, 2020 at 8:22am
Oct 17, 2020 at 12:21pm
I've now developed this into a fairly fully featured line editor. The code is too long to include here, but see http://coliru.stacked-crooked.com/a/a0e362009902631e It won't run there as it needs Microsoft windows (for _getch() and the cursor functions).

getstr() is the main function to obtain a string. It recognises left, right, home, end, insert, delete, <ESC>, <CTR_X>, <BS> str will always be null-terminated (even when input exceeds size) and the return value is the number of entered chars (excludes the terminating null). sz is the total size of the str memory (including the terminating null).

KeyConv() obtains a key and converts it to a standard form. If a key generates 2 chars (such as left) then this is all dealt with.
Last edited on Oct 17, 2020 at 1:17pm
Topic archived. No new replies allowed.