This question already has answers here:
Reading a password from std::cin
(4 answers)
Closed 7 months ago.
I want to mask my password with "*" while the user is inputting it in. I used the getch() function but it accepts backspace and return as characters.
This is the code I have written:
#include <iostream>
#include <conio.h>
using namespace std;
int main()
{
char password[7];
char PASSWORD[7]="abc123";
pass:
cout<<"Enter the 6 character password: "<<endl;
for(int i=0;i<6;i++) {
password[i]=getch();
cout<<"*"; //To mask the user input with '*'
}
cout<<endl;
if(strcmp(password,PASSWORD)==0) {
cout<<"LOGIN SUCCESSFULL..."<<endl<<flush;
system ("PAUSE");
}
else{
cout<<"Incorrect Password;"<<endl;
goto pass; //goes back to "pass:" and asks for password input again.
}
return 0;
}
Please how can I make it accept numbers and alphabets only.
You can check if what is entered are numbers or alphabets, and ignore the input otherwise.
for(int i=0;i<6;) {
password[i]=getch();
if (isalnum(password[i])) {
cout<<"*"; //To mask the user input with '*'
i++;
}
}
You should add #include <cctype> to use isalnum().
First of all, the standard warning: this method of checking a password has essentially no security at all, so don't use it for anything where security actually matters.
You can write a small "editor" that knows how to deal with backspace and carriage return characters.
bool IsAlnum(int ch) {
if (ch < 0 || ch > 255)
return false;
return isalnum(ch);
}
// use getch() to read a keystroke, including possible extended keystroke
int getkey()( {
int ch = getch();
if (ch == 0 || ch == 0xe0) { // if it's an extended key
ch = (ch << 8) + getch(); // return lead byte + extended byte
}
return ch;
}
void readpassword(char *dest, size_t length) {
int pos = 0;
for (;;) {
// when they press return, we're done
if (ch == '\r') {
dest[pos] = '\0';
return;
}
// if it's alphanumeric, add it to password, if there's length
if ((IsAlnum(ch)) && pos < length) {
char[pos++] = ch;
printf("*");
}
// if it's a backspace and there's at least one character entered,
// erase the last character
if (ch == '\b' && pos > 0) {
printf("\b");
--pos;
}
}
}
Note that if you use getch() on its own, you can run into problems, if the user presses something like a cursor key. These are read as two consecutive bytes, and if you don't read them together, the second byte will contain a value you don't want.
Though it's rarely useful for passwords, you can add support for more keys pretty much the same way, if you want (e.g., cursor keys, control-cursor to move by word, and so on). If you're going to support many more, you may want to use a switch statement instead of if statements (but switch doesn't work all that well with a Boolean function like isAlnum).
I want to replace a pair of characters with another pair.
For example if want to replace "ax" with "57" and the string is "vksax", it will give out "vks57".
Tried it this way but get a weird output that is only partially correct:
#include <stdio.h>
#include <stdlib.h>
int main()
{
char dummy;
int i;
char string[16];
scanf("%s", string);
for(i=0;string[i];i++){
if(string[i] == 'a' && string[i+1] == 'x'){
string[i] = '5' ;
string[i+1] = '7';
i=0;
}
printf("%s", string) ;
}
exit(0);
}
I can't figure out why it gives, for example, with an input of 1234ax the output 1234ax1234ax1234ax1234ax123457123457123457123457123457123457
Within the for loop
for(i=0;string[i];i++){
if(string[i] == 'a' && string[i+1] == 'x'){
string[i] = '5' ;
string[i+1] = '7';
i=0;
}
this statement
i=0;
does not make a sense. Remove it. And instead of
string[i+1] = '7';
write
string[++i] = '7';
And move this call
printf("%s", string) ;
outside the for loop.
Pay attention to that the variable dummy is declared but not used.
char dummy;
Remove this declaration.
And there is no great sense to use exit( 0 ); instead of return 0;.
And the call of scanf will be more safer if to write it like
scanf("%15s", string);
Since this question is marked as C++, here is C++ one-line answer:
#include <string>
std::string String = "vksax";
String.replace(String.find("ax"), 2, "57");
Get yourself familiar with std::string
https://www.cplusplus.com/reference/string/string/
Solution as function(it assumes substring to be replaced and replacement have the same length):
std::string FindAndReplace(std::string sInputString, std::string sReplaceThis, std::string sReplacement)
{
size_t iPos = sInputString.find(sReplaceThis);
if(iPos == std::string::npos)
return sInputString;
sInputString.replace(iPos, sReplacement.length(), sReplacement);
return sInputString;
};
I was trying to solve a programming problem of some site and this one had the following statement:
Read a string and parse it as a number, char 'l' can be considered as number 1 and chars 'o' and 'O' can be considered as number 0, commas and spaces will be accepted in the input but ignored, if any other character is found then output error...
So... since there can be spaces in the lines, I used gets (the documentation says it removes the new line and puts a terminator)...
My sequence of IF test if it is a number, then if its an acceptable letter, then checks if it is not a comma or a space... And I found out that it was almost always entering in the last IF even though there wasn't any character that should lead it there so I changed the printf inside it to print the
printf("%d error", st[k]);
And it outputs 13: carriage return... I tried this compiler here
#include <cstdio>
#include <cstring>
#include <cstdlib>
int main()
{
char st[100];
char buf[100];
int k, i;
long long int num;
ops: while(gets(st))
{
for(k = i = 0; st[k]; k++)
if(st[k] >= '0' && st[k] <= '9')
buf[i++] = st[k];
else if(st[k] == 'o' || st[k] == 'O')
buf[i++] = '0';
else if(st[k] == 'l')
buf[i++] = '1';
else if(st[k] != ',' && st[k] != ' ')
{
printf("error\n");
goto ops;
}
// remaining code comes here...
}
The input sample had the following lilnes:
lo6
234,657
hi
,,,,,5,,5, 4
2200000000
00
Should I use other function to read instead?
Any suggestions on how to avoid this damn Carriage Return?
The statemente for the problem can be seen here if you want more detail
Thanks
EDIT:
I'm asking that because there seem to be a difference between the compiler I'm using and the compiler the website was using, once I submitted a code that wasn't generating the correct output on mine but I thought the code was correct... and it passed. Then after it, I tried the code on a linux virtual machine and also correct but my gcc on windows failed... some characters were completely away from where they should be
The thing is:
The preferred method of line input is getline. If you do not know the width of the input beforehand, getline will allocate space for you if you set the buffer pointer to NULL.
Since you indicate you have some experience in C, the following will show you how to step through an input string and parse it in the manner you want. While there are many ways to handle parsing strings, it is hard to beat assigning a pointer to the beginning of the string and then advancing down the string until you reach the null-terminating character (unsigned 0, or char '\0'). If you have any questions after looking it over, just ask:
#include <stdio.h>
#include <stdlib.h>
int main (int argc, char *argv[]) {
char *buffer = NULL;
size_t n = 0;
ssize_t len;
char *ptr = NULL;
char *output = NULL;
int idx = 0;
printf ("\nEnter your string below: ([ctrl + d] on blank line to end)\n");
while ((len = getline (&buffer, &n, stdin)) != -1) {
ptr = buffer;
idx = 0;
output = malloc (sizeof (char) * len);
while (*ptr != 0) {
if (*ptr >= 48 && *ptr <= 57) output [idx++] = *ptr;
if (*ptr == 'I') output [idx++] = '1';
if (*ptr == 'o' || *ptr == 'O') output [idx++] = '0';
ptr++;
}
output [idx] = 0;
printf ("\n valid output: %s\n\n", output);
free (output);
}
return 0;
}
output:
Enter your string below: ([ctrl + d] on blank line to end)
This sting has 12345 aeiou AEIOU,,,,,commas, and 99, to end.
valid output: 123450100990
I try to read a formula full of -,(,),|,&,>,= characters. I want to skip the blanks and end-of-line characters and put the others in an array to use them efficiently.
The code is:
int main()
{
char *array;
int i=0,j;
char c=getchar();
array=(char*)malloc(sizeof(char));
while (c != EOF)
{
if( islower(c) || (c!=' ' && c!='\n'))
{
array[i]=c;
i++;
array=(char*)realloc(array,sizeof(char)*(i+1));
}
}
}
My input is:
-(-(a&k) > ( -((a|-k)
|c ))
but it gives me segmentation fault. What should I do?
The problem is that you are managing memory yourself and that you are never changing the value of c which, if it's originally different from EOF, will cause an infinite loop. Use std::string:
int main() {
std::string array;
char c = getchar();
while (c != EOF) {
if(islower(c) || (c!=' ' && c!='\n'))
array.push_back(c);
c = getchar();
}
}
Live demo
Not only this is easier to read and to write, but it is also much more efficient than keep reallocating memory at every loop.
for C
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
int main(){
char *array;
int ch, i=0, capacity = 16;
array = malloc(capacity);
while(EOF!=(ch = getchar())){//It is necessary to receive an int return value is in order to properly compare EOF.
if(!isspace(ch)){//islower not necessary when OR(||) condition
array[i++]=ch;
if(i==capacity)//Efficiency is not good of character by character
array = realloc(array, capacity += 16);
}
}
array[i] = '\0';
printf("%s\n", array);
free(array);
return 0;
}
I'm looking to make a method like so (which encrypts a message using Caesar Cipher, entered by the user and displays it):
void encrypt(char *message, int shift);
My code:
#include <stdio.h>
#include <conio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#include <string.h>
char num(char c)
{
const char upper_alph[26] = {'A','B','C','D','E','F','G','H','I','J','K','L','M','N','O','P','Q','R','S','T','U','V','W','X','Y','Z'};
const char lower_alph[26] = {'a','b','c','d','e','f','g','h','i','j','k','l','m','n','o','p','q','r','s','t','u','v','w','x','y','z'};
if(isupper(c)) {
for(int i = 0; i < 26; i++)
if(upper_alph[i] == c)
return i;
} else {
for(int i = 0; i < 26; i++)
if(lower_alph[i] == c)
return i;
}
return 0;
}
void encrypt(char *message, int shift)
{
int i = 0;
const char upper_alph[26] = {'A','B','C','D','E','F','G','H','I','J','K','L','M','N','O','P','Q','R','S','T','U','V','W','X','Y','Z'};
const char lower_alph[26] = {'a','b','c','d','e','f','g','h','i','j','k','l','m','n','o','p','q','r','s','t','u','v','w','x','y','z'};
while(message[i] != NULL)
{
if(isalpha(message[i]))
{
if(isupper(message[i])) {
printf("%c", upper_alph[(num(message[i])+shift)%26]);
} else {
printf("%c", lower_alph[(num(message[i])+shift)%26]);
}
} else {
printf("%c", message[i]);
}
i++;
}
}
#define OK 0
#define NO_INPUT 1
#define TOO_LONG 2
static int getLine (char *prmpt, char *buff, size_t sz) {
int ch, extra;
// Get line with buffer overrun protection.
if (prmpt != NULL) {
printf ("%s", prmpt);
fflush (stdout);
}
if (fgets (buff, sz, stdin) == NULL)
return NO_INPUT;
// If it was too long, there'll be no newline. In that case, we flush
// to end of line so that excess doesn't affect the next call.
if (buff[strlen(buff)-1] != '\n') {
extra = 0;
while (((ch = getchar()) != '\n') && (ch != EOF))
extra = 1;
return (extra == 1) ? TOO_LONG : OK;
}
// Otherwise remove newline and give string back to caller.
buff[strlen(buff)-1] = '\0';
return OK;
}
int main()
{
//reverse();
//printf("\n\n");
int rc;
char mes[1024];
int sh = 0;
rc = getLine ("Enter message to be encrypted: ", mes, sizeof(mes));
if (rc == NO_INPUT) {
// Extra NL since my system doesn't output that on EOF.
printf ("\nNo input\n");
return 1;
}
if (rc == TOO_LONG) {
printf ("Input too long [%s]\n", mes);
return 1;
}
encrypt(mes, 1);
fflush(stdin);
getchar();
return 0;
}
Thank you to anyone who helps or tries to help.
:)
EDIT: Made many corrections. Still not working :/
EDIT2: Made a lot more corrections. Getting an access violation # "while(*message != '\0')"
EDIT3: Updated the code above to the working code. Thank you everyone for your help!
One problem is you never wrap-around. Consider if you are passed something like 'Z' or 'z' with any positive shift, then you will just increment outside of the array.
You need to do something like:
upper_alph[(num(message[i])+shift)%26]
and
lower_alph[(num(message[i])+shift)%26]
You also need to allocate memory for mes:
char mes[1024];
I believe your scanf is also incorrect (c is a character, s is a string):
scanf("%s", mes);
Using %s will however only read until it gets white-space, a better option may be to read the entire line with getline().
You'll get an "index out of bounds" error on these lines:
if(isupper(message[i])) {
printf("%c", upper_alph[num(message[i])+shift]);
} else {
printf("%c", lower_alph[num(message[i])+shift]);
}
You need to calculate the index in advance and make sure it is between 0 and 25:
int shiftedIndex = (num(message[i]) + shift) % 26;
You are aware of the fact that your code only works with English as input language?
It doesn't work because you didn't allocate memory for mes:
char mes[512]; // Enough space!
Use std::string is easier:
string mes;
int sh = 0;
cout << "Enter message to be encrypted: " << endl;
getline(cin, mes);
cout << "Enter a shift amount (1-25): " << endl;
cin >> sh;
encrypt(mes, sh);
And change encrypt function to:
void encrypt(const string &message, int shift)
And keep your characters in range:
upper_alph[(num(message[i])+shift)%26]
lower_alph[(num(message[i])+shift)%26]
There is a fundamental problem here that the OP isn't understanding. And that is, to the computer, letters are just numbers. It us us humans that assign meaning to those numbers, and we can't even decide on which numbers mean what (see comments on question re ASCII, EBDIC and Unicode).
Here is a table showing how the ASCII standard maps the numbers to letters.
Notice that the character 'a' is 97, 'b' is 98, 'c' is 99 and so on. The uppercase characters start at 65 and go up from there. Note also that the letter 'a' and 'A' are on the same row! This means the bit patterns of the lower 5 bits for an upper case letter and a lower case letter are the same. Finally, as the computer only ever sees characters as numbers, it can do numeric operations on them:-
'd' - 'a' == 3
100 - 97
The second thing to note is that mathematically the Caeser cipher is just an addition with a modulo:-
encoded character = (plain text character + shift) mod 26
So now the code can written much more efficiently:-
void Encode (char *message, int shift)
{
while (*message)
{
char c = *message;
if (isalpha (c)) // check c is a letter
{
// get the letter index: this maps 'A' to 0, 'B' to 1, etc
// it also maps 'a' to 32 (97 - 65), 'b' to 33, etc
c -= 'A';
// this is 32 for lower case characters and 0 for upper case
char case_of_c = c & 32;
// map 'a' to 'A', 'b' to 'B'
c &= 31;
// the caeser shift!
c = (c + shift) % 26;
// restore the case of the letter
c |= case_of_c;
// remap the character back into the ASCII value
c += 'A';
// save the result of the shift
*message = c;
}
++message;
}
}