Caesar cipher - Trouble with negative numbers in the shift key - c#

When I use a negative number for the shift like -1 and use the char 'a', I'm supposed to get 'z' but I get ` instead. How can I fix this?
using System;
using System.IO;
namespace CaesarCipher
{
class Program
{
public static char cipher(char ch, int key)
{
if (!char.IsLetter(ch))
{
return ch;
}
char d = char.IsUpper(ch) ? 'A' : 'a';
return (char)((((ch + key) - d) % 26) + d);
}
public static string Encipher(string input, int key)
{
string output = string.Empty;
foreach (char ch in input)
output += cipher(ch, key);
return output;
}
public static string Decipher(string input, int key)
{
return Encipher(input, 26 - key);
}
static void Main(string[] args)
{
bool Continue = true;
Console.WriteLine(" Ceasar Cipher");
Console.WriteLine("-------------------------\n");
while (Continue)
{
try
{
Console.WriteLine("\nType a string to encrypt:");
string UserString = Console.ReadLine();
Console.Write("\nShift: ");
int key = Convert.ToInt32(Console.ReadLine());
Console.WriteLine("\nEncrypted Data: ");
string cipherText = Encipher(UserString, key);
Console.WriteLine(cipherText);
Console.Write("\n");
Console.WriteLine("Decrypted Data:");
string t = Decipher(cipherText, key);
Console.WriteLine(t);
Console.WriteLine("\nDo you want to continue?");
Console.WriteLine("Type in Yes to continue or press any other key and then press enter to quit:");
string response = Console.ReadLine();
Continue = (response == "Yes");
}
catch (FormatException ex)
{
Console.WriteLine("You entered a bad operation, try another one");
}
}
}
}
}
Ceasar Cipher
Type a string to encrypt:
Hello how are you?
Shift: 1
Encrypted Data:
Ifmmp ipx bsf zpv?
Decrypted Data:
Hello how are you?
Do you want to continue?
Type in Yes to continue or press any other key and then press enter to quit:
Yes
Type a string to encrypt:
Hello how are you?
Shift: -1
Encrypted Data:
Gdkkn gnv `qd xnt?
Decrypted Data:
Hello how `re you?
Do you want to continue?
Type in Yes to continue or press any other key and then press enter to quit:

` is the character that proceeds "a" in the ASCII/Unicode character list. https://unicode-table.com/en/
You'll want to detect if you're trying to shift "a", and instead replace it with "z"

There are many ways you could do this. One way would be to subtract from the last letter the difference if the result is less than the first letter:
public static char cipher(char ch, int key)
{
if (!char.IsLetter(ch))
{
return ch;
}
char firstLetter = char.IsUpper(ch) ? 'A' : 'a';
char lastLetter = char.IsUpper(ch) ? 'Z' : 'z';
int result = ch + key;
if (result < firstLetter) result = lastLetter - (firstLetter - result + 1);
return (char)result;
}

Related

C# How to keep do-while loop asking the same question until enter pressed

I am a beginner in C# programming and trying to code an app that reads the user input using a do-while loop, however, the loop doesn't continue executing when the user answers the question. I only want the loop to stops when enter is pressed
This is what I have done so far
Thanks in advance!
//call method to read a text, calculate and display the num of chars
private void ShowStringLength() {
ConsoleKeyInfo cki;
do
{
Console.WriteLine("Let me calculate the length of strings for you!");
Console.WriteLine("Give me text of any length, or press ENTER to exit!");
Console.Write("Enter a string : ");
String str = Console.ReadLine();
Console.WriteLine(str.ToUpper());
int len = str.Length;
Console.WriteLine("Numer of Chars is : " + len);
//Reads “Enter” from the keyboard to exit the app
cki = Console.ReadKey();
Console.Write("OK. You pressed Enter. See you agian!");
} while (cki.Key != ConsoleKey.Enter);
The cki = Console.ReadKey(); waits for any key input, not just enter. This makes the text "OK. You pressed Enter. See you agian!" show even if you actually pressed another key.
You could instead check the entered string, and exit the loop if it is empty. Example:
while (true)
{
Console.WriteLine("Let me calculate the length of strings for you!");
Console.WriteLine("Give me text of any length, or press ENTER to exit!");
Console.Write("Enter a string : ");
string str = Console.ReadLine();
// If the string is null, empty or only contains white spaces,
// break out of the loop.
if (string.IsNullOrWhiteSpace(str))
{
Console.Write("OK. You pressed Enter. See you agian!");
break;
}
Console.WriteLine(str.ToUpper());
Console.WriteLine("Numer of Chars is : " + str.Length);
};
I would try
if(Console.KeyAvailable)
{
cki = console.ReadKey();
...
}
You were close:
private void ShowStringLength()
{
ConsoleKeyInfo cki;
do
{
Console.WriteLine("Let me calculate the length of strings for you!");
Console.WriteLine("Give me text of any length, or press ENTER to exit!");
Console.Write("Enter a string : ");
String str = Console.ReadLine();
Console.WriteLine(str.ToUpper());
int len = str.Length;
Console.WriteLine("Numer of Chars is : " + len);
//Reads “Enter” from the keyboard to exit the app
cki = Console.ReadKey();
if (cki.Key == ConsoleKey.Enter)
{
Console.Write("OK. You pressed Enter. See you agian!");
}
else
{
Console.WriteLine(); //To start with a clean line
}
} while (cki.Key != ConsoleKey.Enter);
}
I wrote a code to made what you ant and i added a character ;in this sample space;
to determine that the string is finished. then calculated the length of string.
using System;
using System.Collections.Generic;
using System.Linq;
namespace ConsoleApp1
{
class Program
{
static void Main()
{
Console.WriteLine("Press <Enter> to exit... ");
var outPutString = "";
var list = new List<int>();
while (true)
{
Console.WriteLine("Let me calculate the length of strings for you!");
Console.WriteLine("Give me text of any length, or press ENTER to exit!");
Console.Write("Enter a string End with space : ");
var readKey = Console.ReadKey().Key;
if (readKey == ConsoleKey.Enter)
{
Console.WriteLine(
$"Length of {outPutString} is : {(string.IsNullOrWhiteSpace(outPutString) ? 0 : outPutString.Length)}");
break;
}
while (readKey != ConsoleKey.Spacebar)
{
if (readKey == ConsoleKey.Enter)
{
Console.WriteLine(
$"Length of {outPutString} is : {(string.IsNullOrWhiteSpace(outPutString) ? 0 : outPutString.Length)}");
break;
}
var result = ((int) readKey);
list.Add(result);
outPutString = list.Aggregate(outPutString, (current, item) => current + (char) item);
list.Clear();
readKey = Console.ReadKey().Key;
}
Console.WriteLine(
$"Length of {outPutString} is : {(string.IsNullOrWhiteSpace(outPutString) ? 0 : outPutString.Length)}");
outPutString = "";
}
}
}
}

How to delete a character from a string in console

using System;
class Strng {
// Main Method
public static void Main()
{
// define string
String str = "Some_String";
Console.WriteLine("Given String : " + str);
// delete from index 5 to end of string
Console.WriteLine("New String1 : " + str.Remove(5));
// delete character from index 8 to end of string
Console.WriteLine("New String2 : " + str.Remove(8));
}
}
The above works with the given input but I want to give input dynamically and remove a character from given string dynamically
It looks like you're wanting to read dynamically a string and a character to replace.
You can do this with the use of Console.ReadLine() or Console.ReadKey()
Implementing the following into your main method:
Console.WriteLine("Enter a string:");
string s = Console.ReadLine();
Console.WriteLine("Enter a character to remove:");
string rs = Console.ReadLine().ToString();
//Assuming if they enter 'a' you want to remove both 'a' AND 'A':
string rsUpCase = rs.ToUpper();
string rsLoCase = rs.ToLower();
s = s.Replace(rsUpCase,"");
s = s.Replace(rsLoCase,"");
Console.WriteLine(s);
//Input:
//Aardvarks are boring creatures
//Result:
//rdvrks re boring cretures
Will allow a user to enter a string dynamically (not hard-coded) and remove any character taking advantage of the Replace function - also demonstrated is the use of upper/lower case to determine if you want both variants of a character to be removed.
Hope this helps.
I think the correct question is how to read from console.
You can use Console.Read() and Console.ReadLine().
First ask for the string, and then ask for the index to remove, if this is what you mean with dynamically
This is a MSDN Example about Read
using System;
class Sample
{
public static void Main()
{
string m1 = "\nType a string of text then press Enter. " +
"Type '+' anywhere in the text to quit:\n";
string m2 = "Character '{0}' is hexadecimal 0x{1:x4}.";
string m3 = "Character is hexadecimal 0x{0:x4}.";
char ch;
int x;
//
Console.WriteLine(m1);
do
{
x = Console.Read();
try
{
ch = Convert.ToChar(x);
if (Char.IsWhiteSpace(ch))
{
Console.WriteLine(m3, x);
if (ch == 0x0a)
Console.WriteLine(m1);
}
else
Console.WriteLine(m2, ch, x);
}
catch (OverflowException e)
{
Console.WriteLine("{0} Value read = {1}.", e.Message, x);
ch = Char.MinValue;
Console.WriteLine(m1);
}
} while (ch != '+');
}
}

Checking each value of a console output

I would like to read each value one by one, every single one they keep typing until they press a value which ends the "input checking".
I have checked several other posts but none works for me, because I don't want to use arrays or lists, the value must be checked once, and if that happens then work with that.
I have managed to achieve this:
char END = '#', value;
bool found= false;
int count = 0;
Console.WriteLine("Write a line ending in '#'.");
value = Convert.ToChar(Console.Read());
if (value == END)
found = true;
while (!found)
{
count++;
value = Convert.ToChar(Console.Read());
if (value == END)
found = true;
}
}
Console.WriteLine("You have typed " + count);
You should use StringBuilder object, you can add characters one by one to it. I have also simplified your logic a lot.
char END = '#';
var sb = new StringBuilder();
Console.WriteLine("Write a line ending in '#'.");
while (true)
{
var ch = Convert.ToChar(Console.Read());
if (ch == END)
break;
sb.Append(ch)
}
}
Console.WriteLine("You have typed " + sb.ToString());
Something like this.
static void Main(string[] args)
{
StringBuilder sb = new StringBuilder();
Console.WriteLine("Write a line ending in '#'.");
ConsoleKeyInfo keyInfo;
do
{
keyInfo = Console.ReadKey();
// Evaluate Input Key
if (int.TryParse(keyInfo.Key.ToString(), out int i))
{
; // do something with an int
}
else
{
; // do something with char
}
if (keyInfo.KeyChar != '#')
{
sb.Append(keyInfo.KeyChar);
}
}
while (keyInfo.KeyChar != '#');
Console.WriteLine();
Console.WriteLine($"You typed '{sb.ToString()}' which is {sb.Length.ToString()} character(s).");
Console.WriteLine("Press any key to exit.");
Console.ReadLine();
}

Program skips lines of code

I have a small program that changes values of char arrays. But first you need to tell the program in which array you want to change a value; and write a new value and its position into that same array position.
But when I enter the array number, the program skips the code lines allowing the entry of the new value and its position. Then the program throws a FormatException at the end.
Here's the code:
static void addLetters(char[] messageOne, char[] messageTwo)
{
char Mnumber;
char letter;
string pos;
int position;
Console.Write("- Message #: ");
Mnumber = (char)Console.Read();
if (Mnumber == '1')
{
Console.Write("Letter: ");
letter = (char)Console.Read();
Console.Write("\nPosition: ");
pos = Console.ReadLine();
position = Int32.Parse(pos);
messageOne[position - 1] = letter;
}
if (Mnumber == '2')
{
Console.Write("Letter: ");
letter = (char)Console.Read();
Console.Write("\nPosition: ");
pos = Console.ReadLine();
position = Int32.Parse(pos);
messageTwo[position - 1] = letter;
}
}
static void Main(string[] args)
{
char[] array1 = new char[50];
char[] array2 = new char[50];
for (int i = 0; i < 50; i++)
{
array1[i] = '*';
array2[i] = '*';
}
addLetters(array1, array2);
}
}
P.S. Could you please tell me how I can make this code more 'elegant'?
When reading a single character it's reccommended to use Console.ReadKey().KeyChar. I've modified your code to handle exceptions as well:
static void addLetters(char[] messageOne, char[] messageTwo)
{
char Mnumber;
char letter;
string pos;
int position;
try
{
do
{
Console.Write("- Message #: ");
Mnumber = Console.ReadKey().KeyChar;
Console.WriteLine();
}
while (Mnumber != '1' && Mnumber != '2');
Console.Write("\nLetter: ");
letter = Console.ReadKey().KeyChar;
Console.Write("\nPosition: ");
pos = Console.ReadLine();
position = Int32.Parse(pos);
if (Mnumber == '1')
messageOne[position - 1] = letter;
else
messageTwo[position - 1] = letter;
}
catch (FormatException)
{
Console.WriteLine("Invalid input format, position must be an integer");
}
catch (IndexOutOfRangeException)
{
Console.WriteLine("Position out of array bounds");
}
finally
{
Console.Read();
}
}
Try a single function for both messages, and TryParse() your string to integer conversions
static char ReadChar(string prompt)
{
// Screen Prompt
Console.Write(prompt);
// Read a Character
return Console.ReadKey(false).KeyChar;
}
static int ReadNumber(string prompt)
{
// Screen Prompt
Console.Write(prompt);
int result=-1;
// Reads a number and onverts it into an integer
int.TryParse(Console.ReadLine(), out result);
return result;
}
// Caution, this modifies the contents of `messages`
static void addLetters(params char[][] messages)
{
// Read message index (first=1, second=2, etc)
int Mnumber=ReadNumber("- Message #: ");
// Read letter
char letter=ReadChar("Letter: ");
// Read placement position
int position=ReadNumber("\nPosition: ");
// Get the right message
char[] current_message=messages[Mnumber-1];
// Assigns a letter to the message
current_message[position]=letter;
}
static void Main(string[] args)
{
int n=50; //Store the size instead of hard coding it all over your code
char[] array1=new char[n];
char[] array2=new char[n];
for (int i=0; i<n; i++)
{
array1[i]='*';
array2[i]='*';
}
addLetters(array1, array2);
}

Cannot convert system.consolekeyinfo to string

What I'am trying to achieve here is that when you press "1" it will check it against "code_1" and then if it matches it will say "key1 correct" and then check the other codes. But the compiler says
Cannot convert system.consolekeyinfo to string
so I'm wondering how I fix this. Here is the code that I use :
static void Main(string[] args)
{
string first_time = null;
string paktc = "Press any key to continue . . .\r\n";
string code_1 = "1";
string code_2 = "2";
string code_3 = "3";
string code_4 = "4";
if (first_time == null)
{
Console.WriteLine("\r\nYour code is 1234\r\n");
Console.WriteLine(paktc);
Console.ReadKey();
Console.WriteLine("Insert Code Now\r\n");
ConsoleKeyInfo key1 = Console.ReadKey();
if (code_1 = key1)
{
ConsoleKeyInfo key2 = Console.ReadKey();
if (code_2 = key2)
{
ConsoleKeyInfo key3 = Console.ReadKey();
if (code_3 = key3)
{
Console.WriteLine("Key3 Correct\r\n");
ConsoleKeyInfo key4 = Console.ReadKey();
if (code_4 = key4)
{
Console.WriteLine("Key4 Correct\r\n");
Console.ReadKey();
Console.WriteLine(paktc);
}
else
{
}
}
else
{
}
}
else
{
}
}
else
{
}
}
}
}
The error you are currently getting is because you forgot that:
= and == are NOT the same thing. The first is assignment, the second is comparison.
And you can't assign a string to a ConsoleKeyInfo, or vice versa, and definitely not in an if statement. Even if you had fixed that however, you still can't compare a string to a ConsoleKeyInfo. You can get its KeyChar property and compare that to a char though:
if (keyInfo.KeyChar == myString[0])
is valid (as string can be indexed to get its chars). In your case, you can just use a char and make it much simpler:
if (keyInfo.KeyChar == '1')
ToString() would work. Say we have ConsoleKeyInfo j.
It'll look like string k = j.KeyChar.ToString();
This will do exactly what you want.
So the code will look like:
ConsoleKeyInfo key1 = Console.ReadKey();
if (code_1 == key1.KeyChar.ToString())
{
//Other stuff here as follows.
}
You could even do this.
if (key1.KeyChar.ToString() == "1")
{
//Other stuff here as follows
}
Use Console.Read(); instead, it returns a int witch can be typecasted into a char. Also instead of having 4 strings with one character in them, you can have one string with the full code in it and use it as an array, See the example below
static void Main(string[] args)
{
string pw = "123";
Console.WriteLine("Enter the first digit of the password");
char toTest = (char) Console.Read();
Console.Read();
Console.Read();
if (toTest == pw[0])
{
Console.WriteLine("Enter the second digit of the password");
toTest = (char)Console.Read();
Console.Read();
Console.Read();
if (toTest == pw[1])
{
Console.WriteLine("Enter the third digit of the password");
toTest = (char)Console.Read();
Console.Read();
Console.Read();
}
}
}
The extra Console.Read(); commands are to catch the invisible characters that are inputted when pressing enter.

Categories

Resources