When I'm using getch() function and run my code, I don't see the characters that I'm inputting.
It is like they are hidden from what reason.
Does anyone know how can I make them appear while inputting them?
You need to use getche() or better _getche() instead of getch() to echo the input.
getch() and _getch() only fetch characters without displaying them to the console.
The e in getche() stands for echo.
From the Microsoft docs:
The _getche and _getwche functions read a single character from the console with echo, meaning that the character is displayed at the console.
Source: https://learn.microsoft.com/en-us/cpp/c-runtime-library/reference/getche-getwche?view=vs-2019
Furthermore, the use of getche() and getch() is deprecated by Microsoft. Use the versions with the preceding underscore instead:
The Microsoft-specific function name getche is a deprecated alias for the _getche function. By default, it generates Compiler warning (level 3) C4996. The name is deprecated because it doesn't follow the Standard C rules for implementation-specific names. However, the function is still supported.
Source: https://learn.microsoft.com/en-us/cpp/c-runtime-library/reference/getche?view=vs-2019
you should use function getche() ,it will display the character also.
Related
I'm trying that a C console application can read (using the keyboard) special Spanish characters such as accents, 'ñ', etc in a scanf or gets and then, print it too with printf.
I have achieved to show these characters correctly (stored in a variable or, directly, from printf) thanks to the package locale.h. I show an example:
#include <stdio.h>
// Add languaje package
#include <locale.h>
int main(void)
{
char string[254];
// Set languaje to Spanish
setlocale(LC_ALL, "spanish");
// Show correctly spanish special chars
printf("¡Success!. It is shown special chars like 'ñ' or 'á'.\n\n\n");
// Gets special chars by keyboard
printf("Input spanish special chars (such 'ñ'): ");
gets(string);
printf("Your string is: %s", string);
return 0;
}
but I have not yet achieved to pick them up correctly with the functions mentioned above.
Does anyone know how to do it?
Thank you.
EDIT 1:
In testing, I observed that:
setlocale(LC_ALL, "spanish"); It shows the characters of the Spanish correctly, but it does not collect them from the keyboard.
setlocale(LC_ALL, "es_ES"); It picks up the Spanish characters correctly from the keyboard, but it does not show them well.
EDIT 2:
I have tryed too setlocale(LC_ALL, "");, setlocale(LC_ALL, "es_ES.UTF-8"); and setlocale(LC_ALL, "es_ES.ISO_8859-15"); with the same results as EDIT 1 (or catch well characters from keyboard or show them well in console, but never both at the same time).
Microsoft's C runtime library (CRT) does not support UTF-8 as the locale encoding. It only supports Windows codepages. Also, "es_ES" isn't a valid CRT locale string, so setlocale would fail, leaving you in the default C locale. Newer versions of Microsoft's CRT support Windows locale names such as "es-ES" (hyphen, not underscore). Otherwise the CRT uses the full names or the old 3-letter abbreviations, e.g. "spanish_spain", "esp_esp" or "esp_esp.1252".
But that's not the end of the story. When reading from and writing to the console using legacy text encodings instead of Unicode, there's another layer of translation in the console itself. To avoid mojibake, you have to set the console input and output codepages (i.e. SetConsoleCP and SetConsoleOutputCP) to match the locale codepage. If you're limited to Spanish or Latin-1, then it should work to set the locale to "spanish" and set the console codepages via SetConsoleCP(1252) and SetConsoleOutputCP(1252). More generally you could look up the ANSI codepage for a given locale name, set the console codepages, and save them in order to reset the console at exit. For example:
wchar_t *locale_name = L"es-ES";
if (_wsetlocale(LC_ALL, locale_name)) {
int codepage;
gPrevConsoleCP = GetConsoleCP();
if (gPrevConsoleCP) { // The process is attached to a console.
gPrevConsoleOutputCP = GetConsoleOutputCP();
if (GetLocaleInfoEx(locale_name,
LOCALE_IDEFAULTANSICODEPAGE |
LOCALE_RETURN_NUMBER,
(LPWSTR)&codepage,
sizeof(codepage) / sizeof(wchar_t))) {
if (!codepage) { // The locale doesn't have an ANSI codepage.
codepage = GetACP();
}
SetConsoleCP(codepage);
SetConsoleOutputCP(codepage);
atexit(reset_console);
}
}
}
That said, when working with the console you will be better off in general if you set stdin and stdout to use _O_U16TEXT mode and use wide-character functions such as fgetws and wprintf. Ultimately, if supported by the C runtime library, this should use the wide-character console I/O functions ReadConsoleW and WriteConsoleW. The downside of using UTF-16 wide-character mode is that it would entail a complete rewrite of your code to use wchar_t strings and wide-character functions and also would require implementing adapters for libraries that work with multibyte encoded strings (preferably UTF-8).
I wonder why non-ASCII localed input-output fails:
setlocale(LC_ALL,"");
scanf("%s",buffer); // I type "příšerně"
printf("%s",buffer); // I get "pýˇçernŘ"
The locale is Czech_Czech Republic.1250 and all the non-ASCII chars (říšě) are in CP1250. Why it fails? The reference says
In <cstdio> (<stdio.h>), formatted input/output operations are
affected by character transformation rules.
Using the default "C" locale gives correct output. How to fix it? On Windows I can't use UTF-8 in setlocale
If you provide a code page value of UTF-7 or UTF-8, setlocale will
fail, returning NULL.
In my project I use setlocale to read UTF8 text file and to display it on console using WinAPI MultiByteToWideChar function, but that requires system default locale, so I need to set the locale.
edit: I just found the input is in CP852, which is the default in "C". I suppose I could use iconv, but I'd rather convince scanf not to stay with CP852.
After 3 hours of testing, I finaly got the working solution. It might not work for everybody since there is still a little mystery behind it. So this helped:
setlocale(LC_CTYPE,"Czech_Czech Republic.852");
CP852 was the default console codepage for Central Europe since DOS times. There is also chcp DOS command and SetConsoleCP and SetconsoleOutputCP winAPI functions. For some reason, this still messes the output:
setlocale(LC_CTYPE,"Czech_Czech Republic.1250");
SetConsoleCP(1250);
SetConsoleOutputCP(1250);
...but this is OK
setlocale(LC_CTYPE,"Czech_Czech Republic.852");
SetConsoleCP(852); // default in CE win console
SetConsoleOutputCP(852); // default in CE win console
Note that UTF-8 can't be set in setlocale, see the original question.
I note the question Colorful text using printf in C gives a good example of setting coloured text on the standard console output in Windows. Is there something similar that allows output to be underlined? Or possibly even bolded or italicised?
EDIT: I tried Lundin's answer on using COMMON_LVB_UNDERSCORE with no luck. Attempting to use AddFontResource() to add arial italic font to try italics gives an error that there is an undefined reference to __imp_AddFontResourceA
It is not possible to do so using any standard C functions, as the C language doesn't even recognize the presence of a screen.
With Windows API console functions you can change colors, underline and some other things. The particular function you are looking for is called SetConsoleTextAttribute just as in the post you linked. Change its attributes to include COMMON_LVB_UNDERSCORE.
You might run your program in some environment with a terminal accepting ANSI escape codes.
(I never used Windows - since I am using Linux only -, so I don't know how to set up such environment in Windows; but I heard that it is possible)
With ANSI escape codes, underlining is "\e[4m" with \e being the ASCII ESCAPE character.
Perhaps try using termcaps. Something like this (after initializing termcaps) :
printf(tgetstr("us", NULL)); /* underline on */
printf(""/* your string */);
printf(tgetstr("ue", NULL)); /* underline off */
or more concise :
printf("%s/* your text here */%s", tgetstr("us", NULL), tgetstr("ue", NULL));
https://www.gnu.org/software/termutils/manual/termcap-1.3/html_node/termcap_34.html
The '\r' sequence differs from the newline ('\n') in that it moves the cursor to the
beginning of the current line of output, not to the beginning of the next line. Using
'\r' gives a program the ability to create a file containing more than one character
in one line position.
This prints an underlined text
printf("\f\t\t\tFinal Report\r\t\t\t____________\n");
Is there a way to make getopt() or getopt_long() recognise double character option?
example: ./a.out -my argument where my is single command.
You can use getopt_long_only, which will try to process options as long ones even if there is only one - sign before them.
This function is GNU extension, as well as getopt_long.
I have a wchar_t array with English and Hebrew characters and when I print it with wprintf() it prints to console the English characters only. When I'm using _wsetlocale( LC_ALL, L"Hebrew" ) I get the Hebrew characters as "????".
The machine I'm working on supports Hebrew of course.
BTW - using c:\windows\system32\cmd.exe and 'dir' on a directory with Hebrew characters, also shows "???" instead of Hebrew.
Any idea?
Have you confirmed that your console font can handle unicode characters? Most don't. You might try the Consolas font.
When I've run into this before, I've found this article by Michael Kaplan to be extremely helpful.
Basically Microsoft's C runtime library isn't implemented very well to allow this.
You can do _setmode(_fileno(stdout), _O_U16TEXT); and then writing with wcout or wprintf will work. However trying to use cout or printf, or anything that doesn't write UTF-16 will then cause the program to crash.