masking password input in windows terminal in C - c

I am on Windows and have tried the following code to mask password input:
#include <stdio.h>
#include <conio.h>
int main() {
int i = 0;
char ch, password[13];
printf("\nEnter Password (Upto 12 chars.): ");
while (i < 12) {
ch = getch();
if (ch == ' ') {
--i;
} else if (ch == '\b') {
printf("\b \b");
i -= 2;
} else if (ch == '\r')
break;
else {
password[i] = ch;
printf("*");
}
++i;
}
password[i] = '\0';
printf("\nPassword: %s",password);
return 0;
}
The problem with above code is that when I have inputted no characters and I press backspace then the printed string Enter Password (Upto 12 chars.): gets its characters erased one by one. This I was able to work around by doing this Enter Password (Upto 12 chars.):\n and now it won't delete its characters. But there is another problem and that is whenever I try to close the terminal by pressing Alt+F4 the two keystrokes get considered input by getch() and I get two characters returned and displayed. I know it is my fault as the else part takes anything except \r,\b and white-space but I want help fixing it.
What I want is to be able to mask password input without any of the above problems. I have used MySQL Command-line client before and it asks for password input just fine. Anything like that or close to that would be appreciated.
I should mention this is for a University project.
Any help is appreciated

I fixed my own code. Took some inspiration from some old C++ code (not copy pasta).
It ignores whitespace, Esc key, function and arrow keys, works properly on backspace, and breaks out of the loop on hitting Tab or Enter. And now it doesn't delete characters from printf() string when hitting backspace on empty input.
The trick is to only assign input when all other if and else if conditions are not met and increment the counter in that else block only. And then when the loop ends put a '\0' at the last index of the string.
Here is the code:
#include <conio.h>
#include <stdio.h>
#define PASSWORD_LENGTH 12
int main() {
int i = 0;
char password[PASSWORD_LENGTH + 1];
int ch;
printf("\nEnter Password (Upto 12 chars.): ");
while (i < PASSWORD_LENGTH) {
ch = getch();
if (ch == ' ' || ch == 27) {
continue;
} else if (ch == '\b') {
if (i > 0) {
printf("\b \b");
--i;
} else {
continue;
}
} else if (ch == '\r' || ch == '\t') {
break;
} else if (ch == 0 || ch == 224) {
ch = getch();
continue;
} else {
password[i++] = ch;
printf("*");
}
}
password[i] = '\0';
printf("\n,%s,", password); //this can be removed as it is only for displaying output
return 0;
}

Related

Do while loop continuing to loop after correct input from user

My program is continuing a loop instead of breaking out of it.
After entering the incorrect password, the program will ask the user to re-enter the password (as it should). Although, if the user enters the password correctly, after previously entering the incorrect password, the program will continue to ask them to re-enter the password when it should break out of the loop.
My program will execute if the user enters the correct password on first attempt, although it makes the user click the enter key twice instead of once.
I can't figure out what is wrong. Any help is appreciated.
#define ENTER 13
#define TAB 9
#define BKSP 8
#define SPACE 32
#define PASSWORD "HelloWorld"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main(){
char password[100];
char ch;
int i = 0;
do {
printf("\n\n\t\t\t\t\tPlease enter your password: ");
while (1) {
ch = getch();
if (ch == ENTER) {
password[i] = '\0';
break;
}
else if (ch == BKSP) {
if (i > 0) {
i--;
printf("\b \b");
}
}
else if (ch == TAB || ch == SPACE) {
continue;
}
else {
password[i] = ch;
i++;
printf("*");
}
}
} while((strcmp(password, PASSWORD) != 0));
return 0;
}
The minimal fix would be to move the int i = 0; into the do {} loop so it's reset each each wrong password:
do {
int i = 0;
printf("\n\n\t\t\t\t\tPlease enter your password: ");
As you rely on a fixed sized buffer, you should also check that i < 100. For example:
#define PASSWORD_MAX_LEN 99
char password[PASSWORD_MAX_LEN + 1];
...
while(i < PASSWORD__MAX_LEN) {
ch = getch();
if (ch == ENTER) {
break;
}
...
}
password[i] = '\0';
...

Cursor positioning by using arrow keys for getch in C

I am very beginner in C and would like to code something which gets name from user and rearrange it with backspace, cursor(by using arrow keys).
In the program, when user writes his name and press ESC it has to stop the program and print the name on the screen.
So far, I was able to do ESC and Backspace parts with usign getch() and their ASCII codes, but I'm having problem on moving cursor by using arrow keys when user tries to rewrite or rearrange his name.
Here is my code:
#include<stdio.h>
#include<conio.h>
int main() {
int i, k = 0;
char character;
char samplearray[100];
printf("Enter your name:\n");
while (1) {
character=getch();
if (character != 0x1B && character != 0x8 && character != 0x4B) {
samplearray[k] = character;
k++;
printf("%c", character);
}
else if (character == 0x8) { //Deleting procces in name and it works without any problem.
samplearray[k];
k--;
system("cls");
printf("Enter your name:\n");
for (i = 0; i <= k; i++) {
printf("%c", samplearray[i - 1]);
}
}
else if (character == 0x4B) { //Having a problem on this part.
samplearray[k] = character;
k--;
printf("\b\b", samplearray[k]);
}
else
break;
}
printf("\nYour name is: \n");
for (i = 0; i <= k - 1; i++) {
printf("%c", samplearray[i]);
}
getch();
return 0;
}

Write a program to check given input string have balance brackets

Given a string of parentheses, write a program to find whether its valid or not.
Examples-
input : {{{}}}
output: Valid
input : }{}{}{}}
output: Invalid
I wrote the following code in C and tested that the output were coming correct.
#include <stdio.h>
#include <stdlib.h>
int main()
{
char str[20];
int i=0;
printf("Enter String: ");
gets(str);
int count = 0;
while (str[i] != '\0')
{
if (str[i] == '}')
count--;
if (str[i] == '{')
count++;
if (count < 0)
{
printf("\nInvalid");
break;
}
i++;
}
if (count == 0)
printf("\nValid");
return 0;
}
This program doesn't work for the case where input is {{{}}, what condition(s) am I missing?
Code should state if the final result is not 0 as in the case of "{"
if (count == 0) {
printf("Valid\n");
} else {
printf("Invalid\n");
}
return 0;
Also simple break out of loop.
if (count < 0) {
// printf("\nInvalid");
break;
}
gets() has been depreciated since C99 and eliminated from C (C11), use fgets().
char str[20];
fgets(str, sizeof str, stdin);
There is no need to read the entire string in. Code could use 1 char ar a time.
int ch;
while ((ch = fgetc(stdin)) != '\n' && ch != EOF) {
if (str[i] == '}')
count--;
if (count < 0) {
break;
}
else if (str[i] == '{')
count++;
}
}
You don't really need to input the whole string at once since you're only every sequentially processing the characters. Hence you can avoid using unsafe methods like gets() and even safe-but-complicating methods like fgets().
Instead, just use getchar() to read and process each individual character - that should greatly simplify what you need to do.
As to the logic, you basically have it right. Maintain the bracket level, a value initially set to zero. Then read each character and action it as follows:
If it's {, just add one to the level.
If it's }, subtract one from the level, then check to ensure the level is non-negative. If not, then you've had too many closing brackets and you can exit.
If it's end of line or end of file, stop processing characters. Check to make sure the final level is zero. If not, you haven't closed off all the brackets so it's invalid. If the level is zero, everything is balanced.
Any other character can be considered an error.
See below for one example on how to implement this:
#include <stdio.h>
int main (void) {
int debug = 0; // for debugging purposes.
int ch, level = 0; // character and current level.
// Output prompt, read characters while valid.
printf("Enter string: ");
while (((ch = getchar()) == '{') && (ch == '}')) {
// Select based on '{' or '}'.
if (ch == '{') {
// Open bracket, just add one.
++level;
if (debug) printf("DEBUG: {:%d\n",level);
} else {
// Close bracket, subtract one and check.
if (--level < 0) {
puts ("Level has gone below zero.");
return 1;
}
if (debug) printf("DEbug: }:%d ",level);
}
}
// If not endline/endfile, we have invalid character.
if ((ch != '\n') && (ch != EOF)) {
puts ("Invalid character in input.");
return 1;
}
// Level should be zero.
if (level != 0) {
puts ("Level still positive at end of line.");
return 1;
}
// All checks now passed okay.
puts ("Input was fine.");
return 0;
}
You should never use gets(), the gcc compiler even warns about it being dangerous because there is no way to prevent a buffer overflow, for example
char str[6];
gets(str);
with the following input
iharob
is a problem, because there is no room for the '\0' terminator or the '\n', instead
fgets(str, sizeof(str), stdin);
would be safe with any input, although the input string would be trimmed to fit the buffer, but no buffer overflow will occur.
Previous answers have covered avoiding buffer overflows and potential cases where it will not work - to improve performance I would modify the while loop to avoid checking conditions which we know will always be false. e.g. no point in checking if count is less than 0 unless we just decreased the count; no point in checking for an open bracket if the character was a close bracket:
while (str[i] != '\0')
{
if (str[i] == '}')
{
count--;
if (count < 0)
{
printf("\nInvalid");
break;
}
}
else if (str[i] == '{')
count++;
i++;
}
I hope you find this useful and simple ^-^
#include<iostream>
#include<string.h>
using namespace std;
{
string mathEx ;
cout<<"Please Enter math Expression contain ')' , '(' to
check balance \n"<<"MathExpression = ";
cin>>mathEx ;
int i =0 , count = 0 ;
while (mathEx [i] != '\0'){
if(mathEx[i]=='('){
count++;
}
if(mathEx[i]==')'){
count--;
}
if(count<0){
break ;
}
i++;
}
if(count==0){
cout<<"True !";
}
else {
cout<<"Invalid !"<<endl;
}
return 0;
}

C programming getchar()

I have two problems writing my code. The first problem I have is getting my getchar() to work if the user enters no text and just hits enter. I need to print an error if they do so and prompt the user to reenter the text in a loop until they do enter text. Is there any way to do so because everything I have tried has failed.
Here is the code I have for that section:
printf("Enter a text message: ");
while((c=getchar()) != '\n' && c != EOF)
{
text[i]= c;
i++;
}
I am new to C so I am limited on ideas to fix my dilemma. As you can see I am setting the input equal to an array. This leads to my second problem, I need to limit the input to no more than 100 characters. But, instead of giving the user an error I need to just chop off the extra characters and just read the first 100.
The simplest solution to your problem is to use fgets. We can give limit to the input so that it doesn't read the extra characters after the given limit.
Refer this sample code. Here I am printing the string if the user is not pressing Enter key:
#include <stdio.h>
int main()
{
char str[100];
fgets(str, 100, stdin);
if(str[0] != '\n')
{
puts(str);
}
return 0;
}
#include <stdio.h>
#define MAXSIZE 100
int main() {
char text[MAXSIZE+1]; // one extra for terminating null character
int i = 0;
int c;
while (1) {
printf("Enter a text message: ");
i = 0;
while ((c = getchar()) != '\n' && c != '\r' && c != EOF) {
if (i < MAXSIZE) {
text[i]= c;
i++;
}
}
if (i > 0 || c == EOF)
break;
printf("Empty string not allowed.\n");
}
text[i] = '\0';
printf("You entered: %s\n", text);
return 0;
}
Test code to detect non-compliant system:
#include <stdio.h>
int main() {
int c;
printf("Just hit enter: ");
c = getchar();
if (c == '\r')
printf("\\r detected!!!\n");
else if (c == '\n')
printf("\\n detected.\n");
else
printf("Yikes!!!\n");
return 0;
}
First of all getchar() can take only one character an input. It cannot take more than one character.
char c;
int total_characters_entered = 0;
do
{
printf ("Enter a text message: ");
c = getchar();
if (c != '\n')
{
total_characters_entered++;
}
} while (total_characters_entered <= 100);
I have written some code that will iterate in while loop until user has entered 100 characters excluding "Simple Enter without any text"
Please let me know if it does not satisfy your requirement. We will work on that.

counting the number of sentences in a paragraph in c

As part of my course, I have to learn C using Turbo C (unfortunately).
Our teacher asked us to make a piece of code that counts the number of characters, words and sentences in a paragraph (only using printf, getch() and a while loop.. he doesn't want us to use any other commands yet). Here is the code I wrote:
#include <stdio.h>
#include <conio.h>
void main(void)
{
clrscr();
int count = 0;
int words = 0;
int sentences = 0;
char ch;
while ((ch = getch()) != '\n')
{
printf("%c", ch);
while ((ch = getch()) != '.')
{
printf("%c", ch);
while ((ch = getch()) != ' ')
{
printf("%c", ch);
count++;
}
printf("%c", ch);
words++;
}
sentences++;
}
printf("The number of characters are %d", count);
printf("\nThe number of words are %d", words);
printf("\nThe number of sentences are %d", sentences);
getch();
}
It does work (counts the number of characters and words at least). However when I compile the code and check it out on the console window I can't get the program to stop running. It is supposed to end as soon as I input the enter key. Why is that?
Here you have the solution to your problem:
#include <stdio.h>
#include <conio.h>
void main(void)
{
clrscr();
int count = 0;
int words = 0;
int sentences = 0;
char ch;
ch = getch();
while (ch != '\n')
{
while (ch != '.' && ch != '\n')
{
while (ch != ' ' && ch != '\n' && ch != '.')
{
count++;
ch = getch();
printf("%c", ch);
}
words++;
while(ch == ' ') {
ch = getch();
printf("%c", ch);
}
}
sentences++;
while(ch == '.' && ch == ' ') {
ch = getch();
printf("%c", ch);
}
}
printf("The number of characters are %d", count);
printf("\nThe number of words are %d", words);
printf("\nThe number of sentences are %d", sentences);
getch();
}
The problem with your code is that the innermost while loop was consuming all the characters. Whenever you enter there and you type a dot or a newline it stays inside that loop because ch is different from a blank. However, when you exit from the innermost loop you risk to remain stuck at the second loop because ch will be a blank and so always different from '.' and '\n'. Since in my solution you only acquire a character in the innermost loop, in the other loops you need to "eat" the blank and the dot in order to go on with the other characters.
Checking these conditions in the two inner loops makes the code work.
Notice that I removed some of your prints.
Hope it helps.
Edit: I added the instructions to print what you type and a last check in the while loop after sentences++ to check the blank, otherwise it will count one word more.
int ch;
int flag;
while ((ch = getch()) != '\r'){
++count;
flag = 1;
while(flag && (ch == ' ' || ch == '.')){
++words;//no good E.g Contiguous space, Space at the beginning of the sentence
flag = 0;;
}
flag = 1;
while(flag && ch == '.'){
++sentences;
flag=0;
}
printf("%c", ch);
}
printf("\n");
I think the problem is because of your outer while loop's condition. It checks for a newline character '\n', as soon as it finds one the loop terminates. You can try to include your code in a while loop with the following condition
while((c=getchar())!=EOF)
this will stop taking input when the user presses Ctrl+z
Hope this helps..
You can implement with ease an if statement using while statement:
bool flag = true;
while(IF_COND && flag)
{
//DO SOMETHING
flag = false;
}
just plug it in a simple solution that uses if statements.
For example:
#include <stdio.h>
#include <conio.h>
void main(void)
{
int count = 0;
int words = 1;
int sentences = 1;
char ch;
bool if_flag;
while ((ch = getch()) != '\n')
{
count++;
if_flag = true;
while (ch==' ' && if_flag)
{
words++;
if_flag = false;
}
if_flag = true;
while (ch=='.' && if_flag)
{
sentences++;
if_flag = false;
}
}
printf("The number of characters are %d", count);
printf("\nThe number of words are %d", words);
printf("\nThe number of sentences are %d", sentences);
getch();
}
#include <stdio.h>
#include <ctype.h>
int main(void){
int sentence=0,characters =0,words =0,c=0,inside_word = 0,temp =0;
// while ((c = getchar()) != EOF)
while ((c = getchar()) != '\n') {
//a word is complete when we arrive at a space after we
// are inside a word or when we reach a full stop
while(c == '.'){
sentence++;
temp = c;
c = 0;
}
while (isalnum(c)) {
inside_word = 1;
characters++;
c =0;
}
while ((isspace(c) || temp == '.') && inside_word == 1){
words++;
inside_word = 0;
temp = 0;
c =0;
}
}
printf(" %d %d %d",characters,words,sentence);
return 0;
}
this should do it,
isalnum checks if the letter is alphanumeric, if its an alphabetical letter or a number, I dont expect random ascii characters in my sentences in this program.
isspace as the name says check for space
you need the ctype.h header for this. or you could add in
while(c == ' ') and whie((c>='a' && c<='z') || (c >= 'A' && c<='Z')
if you don't want to use isalpace and isalnum, your choice, but it will be less elegant :)
The trouble with your code is that you consume the characters in each of your loops.
a '\n' will be consumed either by the loop that scans for words of for sentences, so the outer loop will never see it.
Here is a possible solution to your problem:
int sentences = 0;
int words = 0;
int characters = 0;
int in_word = 0; // state of our parser
int ch;
do
{
int end_word = 1; // consider a word wil end by default
ch = getch();
characters++; // count characters
switch (ch)
{
case '.':
sentences++; // any dot is considered end of a sentence and a word
break;
case ' ': // a space is the end of a word
break;
default:
in_word = 1; // any non-space non-dot char is considered part of a word
end_word = 0; // cancel word ending
}
// handle word termination
if (in_word and end_word)
{
in_word = 0;
words++;
}
} while (ch != '\n');
A general approach to these parsing problems is to write a finite-state machine that will read one character at a time and react to all the possible transitions this character can trigger.
In this example, the machine has to remember if it is currently parsing a word, so that one new word is counted only the first time a terminating space or dot is encountered.
This piece of code uses a switch for concision. You can replace it with an if...else if sequence to please your teacher :).
If your teacher forced you to use only while loops, then your teacher has done a stupid thing. The equivalent code without other conditional expressions will be heavier, less understandable and redundant.
Since some people seem to think it's important, here is one possible solution:
int sentences = 0;
int words = 0;
int characters = 0;
int in_word = 0; // state of our parser
int ch;
// read initial character
ch = getch();
// do it with only while loops
while (ch != '\n')
{
// count characters
characters++;
// count words
while (in_word)
{
in_word = 0;
words++;
}
// skip spaces
while (ch == ' ')
{
ch = -1;
}
// detect sentences
while (ch == '.')
{
sentences++;
ch = -1;
}
// detect words
while ((ch != '\n')
{
word_detected = 1;
ch = -1;
}
// read next character
ch = getch();
}
Basically you can replace if (c== xxx) ... with while (c== xxx) { c = -1; ... }, which is an artifical, contrieved way of programming.
An exercise should not promote stupid ways of doing things, IMHO.
That's why I suspect you misunderstood what the teacher asked.
Obviously if you can use while loops you can also use if statements.
Trying to do this exercise with only while loops is futile and results in something that as little or nothing to do with real parser code.
All these solutions are incorrect. The only way you can solve this is by creating an AI program that uses Natural Language Processing which is not very easy to do.
Input:
"This is a paragraph about the Turing machine. Dr. Allan Turing invented the Turing Machine. It solved a problem that has a .1% change of being solved."
Checkout OpenNLP
https://sourceforge.net/projects/opennlp/
http://opennlp.apache.org/

Resources