I am having fun with a couple of errors I am getting in a C# application I am writing.
The error I keep getting is:
encrypt and decrypt calls must have a return type
Console.WriteLine being used as a method
static void encrypt(string[] args) expected class, delegate, interface or struct
namespace ConsoleApplication1
{
class Program
{
static void Main(string[] args)
{
string pw ="", hash =""; //Declare an intialise variables
if (args.Length < 4) // Test to see if correct number of arguments have been passed
{
Console.WriteLine("Please use command line arguments in this format: encrypt -e (or -d) password-to-encrypt-with input-file output-file");
Environment.Exit(0);
}
if (args[1].Length < 10 || args[1].Length > 40) // Test to see if the password is between 10 and 40 characters
{
Console.WriteLine("Please use a password between 10 and 40 characters");
Environment.Exit(0);
}
switch (args[0]) //Uses first argument value to drive switch statement (-e or -d)
{
case "-e":
encrypt(string[] args);
break;
case "-d":
decrypt(string[] args);
break;
default:
Console.WriteLine("When using the program please use -e to encrypt and -d to decrypt");
break;
}
} //End of MAIN
static void encrypt(string[] args) //Function to encrypt
{
string inputtext =""; //Initialise Varible (Ensure it is empty)
inputtext=System.IO.File.ReadAllText(args[2]); //Read file in an assign to input text
return;
}
static void decrypt(string[] args) //Function to decrypt
{
string inputtext =""; //Initialise Varible (Ensure it is empty)
inputtext=System.IO.File.ReadAllText(args[2]); //Read file in an assign to input text
return;
}
}
}
Any help would be much appreciated!
Alistair
When calling a method, you must not specify the types of the arguments. So:
case "-e":
encrypt(args);
break;
Along with what Hans has said, you mentioned an error about return types in your methods.
Your encrypt and decrypt methods have return statements, but they are void methods meaning they don't have any return types.
Either give it a type you want to return (presumably the string you are manipulating) or just remove the return statement altogether. You do not need to explicitly put return at the end of a method to get it to exit out of the method. It will do that anyway.
Two small pro-tips, I would declare your fields on different lines, not all bunched together (with the way you have declared pw and hash) and also add a using directive for System.IO, so you don't have to call System.IO.File.ReadAllText, you can just call File.ReadAllText.
Related
Today I came across a problem: I was trying to check the errors of a software in order to provide the right behavior of the program when it incurs in the error.
I had to check if a user already exists in the database.
The problem is that the back-end doesn't provide an errorId so I have to check the errors by the text.
Errors are displayed as this:
The user Name already Exists!
The Switch statement is this:
switch (error.text)
{
case "User Test already exists":
Console.WriteLine("The user already Exists"); //this is a test behaviour.
break;
default:
Console.WriteLine("I couldn't behave in any way :<");
}
As you can imagine the names are all different (it's a unique field in the DB), so the word "Test" in the case statement should be the name of the user.
Can I dynamically change the string?
Seems like a Regex would do the trick. I've built this Regex based off the pattern:
The user Name already Exists!
where Name can be any value. The Regex is:
(the user .* already exists)
To use it you'll do something like this:
Regex.IsMatch(error.text, "(the user .* already exists)", RegexOptions.IgnoreCase)
Which would return a true or false based on the match. Now, this can't be done in the switch, but you could just run the value through a number of Regexes to determine which it matched. One thing you might consider is an extension method. Consider this one:
public static class RegexExtensions
{
private static readonly Regex UserNameAlreadyExists = new Regex("(the user .* already exists)", RegexOptions.IgnoreCase | RegexOptions.Compiled);
public static bool IsUserNameAlreadyExists(this string inputValue)
{
return UserNameAlreadyExists.IsMatch(inputValue);
}
}
The usage for this would be really nice:
if (error.text.IsUserNameAlreadyExists())
{
// do something
}
The extension method is a really nice way of working through it. It's fully encapsulated and would keep the usage really clean. Furthermore, it's easier to define the Regex in one place and thus set it to Compiled making it faster.
Preferably change the back-end or have it changed (it definitely should return some sort of error code instead of an already localized message obviously meant to be shown to the user - that's clearly a front-end task).
To answer the question, no; consider using something like this instead (original phrasing, be aware that these string comparisons are case sensitive):
if(error.text.StartsWith("User ") && error.text.EndsWith(" already Exists"))
{
Console.WriteLine("The user already Exists"); //this is a test behaviour.
}
else
{
Console.WriteLine("I couldn't behave in any way :<");
}
I suppose this would be a fairly simple solution:
class Program
{
int errorIndex = 5; //Based on error expected text. Can add more criteria here.
private static bool testResponse = false;
static void Main(string[] args)
{
string text = "The user already exists";
getErrorMessage(text);
}
private static void getErrorMessage(string message)
{
var user = message.Substring(4, 4);
var exists = message.Substring(17, 6);
if (user == "user" && exists == "exists")
//Write the error message.
Console.WriteLine(message.ToString());
var errorMessage = message;
if (errorMessage != null)
{
testResponse = true;
}
Console.ReadLine();
}
}
This is if you know the exact location of the length and index of certain words of the error message. You could use that information to further narrow down the errors you expect. This is assuming that there is no errorId.
just to be sure: The back-end doesn't provide any errorID? If you use C# for the database connection (i.e. ADO.Net) you have possibilitys for efficent error handling.
Is it possible to just check if error.text is empty or not?
if(error.text=="")Console.WriteLine("The User already exists");
else Console.WriteLine("I couldn't behave in any way");
If you want to check if there are duplicates in the "user" column you could check the database directly via SQL.
Greeting fellow programmers!
I am currently studying software development (I started not a month ago) and I have a problem that needs a solution. Underneath you can find the code and as you can see, the method WriteNumber needs help. I need to write the code in a way that when I run the program, on the console screen the following two lines will be shown:
Hello World!
81
The Main method code cannot be changed and also I cannot add more methods to the class Calculator so the code needs to be done only within the WriteNumbers method. I have tried a lot of things but I am still grasping how everything works so any help is welcome! Thank you in advance for your time.
Namespace CalculatorTest
{
class Calculator
{
public static string WriteText (string input)
{
return "" + input;
}
public static string WriteNumber()
{
}
}
class Program
{
static void Main(string[] args)
{
string s = Calculator.WriteText("Hello World!");
Console.WriteLine(s);
string n = Calculator.WriteNumber(53 + 28);
Console.WriteLine(n);
Console.Read();
}
}
Not to do your homework for you to just be copied/pasted, hopefully I can give you some hints...
Notice how the method is being invoked:
Calculator.WriteNumber(53 + 28)
The 53 + 28 part happens first, then the result of that operation is passed to the method. That result, naturally, is 81. What's important about that is its type, which is an integer.
So, reasonably, the method signature needs to accept an int as a parameter. This would be done very similarly to how the other method accepts a string as a parameter:
public static string WriteText(string input)
What, then, does that method need to do with that input? Well, it's only a single value, so there aren't any calculations to be performed on it. It would appear that the method simply needs to return the value as a string. (It's your homework so you tell me, is that correct?)
This can be done with exactly two things:
Calling .ToString() on the value
Using the return keyword to return the result of that operation
(Note: The .ToString() operation does something very intuitive on value types, such as int or double or bool. As you progress into using reference types, you're going to find that it does something very different. Any time you have a custom class on which you want to call .ToString(), you'll need to override the .ToString() method on that class first.)
Please read David's answer, it's important that you make the effort to understand why this works the way it does. That being said:
public static string WriteNumber(int number)
{
return number.ToString();
}
Thank you all for your valuable input but special thanks to David because he showed where I made my error. I forgot that the two numbers in the main function will be summed up FIRST and THEN forwarded to the method in the class Calculator. After that got cleared up, it was easy to understand what to do (basically adjust the type of the input parameter to int).
namespace CalculatorTest
{
class Calculator
{
public static string WriteText (string input)
{
return "" + input;
}
public static string WriteNumber(int sumOfNumbers)
{
return "" + sumOfNumbers;
}
}
class Program
{
static void Main(string[] args)
{
string s = Calculator.WriteText("Hello World!");
Console.WriteLine(s);
string n = Calculator.WriteNumber(53 + 28);
Console.WriteLine(n);
Console.Read();
}
}
}
I am currently studying C# and am trying to prepare for next weeks lessons which will be the introduction of classes and methods. To that end i have attempted to build a class called MaxBox which is meant to be a general utility class that I can store some general functions in like 'Displaying a String' or 'Play Again'. I've built my main file (Program) and my class file (MaxBox) and lines #23, #28 and #59 return the same general error 'An object reference is required for the non-static field, method, or property 'program.MaxBox.DisplayStr(string)'. #57 returns a similar error 'An object reference is required for the non-static field, method, or property 'program.MaxBox.PlayAgain()'
I'm a total newb really, and i'm wrestling with objects, I've done some research to get myself this far but I don't understand the language enough yet to be able to understand what the resources I've read are saying I guess to solve this error. Help and guidance is greatly appreciated. I'm still in my first weeks and really I know nothing.
Program:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading; // needed for close
using System.Threading.Tasks;
namespace a020_Breakcase_MeaningOfNames_C
{
class Program
{
public void Play()
{
/*
* Conditionals - Use switch/Case statement too:
* Evaluate user data (name)
* Return meaning of name evaluated
* OR
* Return 'Name not found' error message
* Say goodbye
*/
MaxBox.DisplayStr("What's in a name? Let's find out!");
Console.Write("\n\n");
do
{
MaxBox.DisplayStr("Enter Name: ");
string uName = Console.ReadLine().ToLower();
switch (uName)
{
case "doyle":
Console.WriteLine("Doyle means descendant of Dubhghalle");
break;
case "fiona":
Console.WriteLine("Fiona is considered to be a Latinised form of the Gaelic word fionn, meaning \"white\", \"fair\".");
break;
case "hunter":
Console.WriteLine("Hunter means to search with purpose");
break;
case "liam":
Console.WriteLine("This name is a short form of the Irish name Uilliam (William) which is now use independently as a given name. As a Hebrew name, Liam means \"my people; I have a nation\".");
break;
case "max":
Console.WriteLine("Short for of Maximilian, Maxwell, and the various name using it as a first syllable.");
break;
case "portia":
Console.WriteLine("It is of Latin origin. Feminine form of a Roman clan name. Portia was used by Shakespeare as the name of a clever, determined young heroine in \"The Merchant of Venice\" who disguises herself as a lawyer to save her husband's life.");
break;
default:
Console.WriteLine("I'm sorry but I don't know the meaning of the name " + uName + ".");
break;
}
} while (MaxBox.PlayAgain());
MaxBox.DisplayStr("C#eers!");
}
static void Main(string[] args)
{
Program myProgram = new Program();
myProgram.Play();
Console.Read();
}
}
}
My Class:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace a020_Breakcase_MeaningOfNames_C
{
class MaxBox
{
/*
* MaxBox is my general functions class
* Contains
* DisplayStr() - Display the string given
* PlayAgain() - If True, runs program again
*/
public String uName;
public String command;
public void DisplayStr(String StrTxt)
{ Console.Write(StrTxt); }
public Boolean PlayAgain()
{
Console.Write("\n\nDo you want to play again? (y)es or (n)o: ");
String command = Console.ReadLine().ToLower().Trim();
if (command == "y" || command == "yes") return true;
return false;
}
}
}
MaxBox's methods are not static, you need an instance of it.
MaxBox maxBox = new MaxBox();
at the beginning of your main class. Then
maxBox.DisplayStr(....)
also, just to get you thinking, you can replace:
if (command == "y" || command == "yes") return true;
return false;
with
return (command == "y" || command == "yes");
The methods PlayAgain and DisplayStr are instance methods on the type MaxBox. In order to call them you need an instance of MaxBox on which to call them. Right now you are trying to call them via the type name which only works for static methods
MaxBox.DisplayStr("hello world"); // wrong
MaxBox mb = new MaxBox();
mb.DisplayStr("hello world"); // right
It is possible to define methods such that you can invoke them from the type name. But doing so requires that they be marked as static
class MaxBox {
public static void DisplayStr2(string str){ ... }
}
MaxBox.DisplayStr2("hello world"); // right
Evening guys,
This may seem like a stupid question but im having some issues figuring out where i should be placing my user input verification checks. I have checks, for the following:
file exists
Correct extension
Access to the file
Input in 2 NumericUpDown controls
One numericUpDown is always greater than the other.
Assignment to static properties.
Im assuming each one of these should at least be a single method but i then have a single method which has a large number of lines which solely check the result of the method calls to the list above. ie
public void VerifyData()
{
if(VerifyNumber1OnTheList != true)
{
LogError("The file specified is incorrect")
return;
}
if(VerifyNumber2OnTheList != ......
Any suggestions on how i should actually be laying this out would be appreciated.
Thanks
Putting a series of validation methods is ok.
This is user input, so you're doing defensive programming here, not looking for exceptional errors. It seems like you'd want to know why the user input is bad. If so, a simple approach is to use a collecting object to visit each validation method
public void VerifyData(ValidationErrors errors)
{
ValidateFileExists(errors);
ValidateExtension(errors);
ValidateFileAccess(errors);
...
}
private void ValidateFileExists(ValidationErrors errors)
{
if(!File.Exists...)
{
errors.Add("File does not exists.");
}
}
public void CallingMethod(UserInput input)
{
_dataToVerify = input;
var errors = new ValidationErrors();
VerifyData(errors);
if(errors.Count > 0)
ShowErrors(errors);
else
ShowSuccess();
}
I just put the data in an instance variable for purposes of simplicity, you could pass that into your validation method. This approach is simple but allows you to tell the user something about the input and how to correct it.
All right here is a quick sample I wrote up for you. Architecture obviously is your choice here. Modify as needed. I believe this should be a great jumping off point for you.
Cheers
Matt
using System.Collections.Generic;
namespace ConsoleApplication1
{
class Program
{
static void Main(string[] args)
{
//This would simulate the event handler that calls your validation event
List<string> errorList = Validation.VerifyData();
if (errorList.Count != 0)
{
ErrorHandler.HandleError(errorList);
return;
}
//Do stuff if validation actually passed here.
}
}
public static class Validation
{
public static List<string> VerifyData()
{
List<string> errorList = new List<string>();
//File exists
if (true)
errorList.Add("File doesn't exist.");
//File has correct extension
if (true)
errorList.Add("File doesn't exist.");
//Has access to the file
if (true)
errorList.Add("File doesn't exist.");
//INput in 2 NumericUpDownControls
if (true)
errorList.Add("File doesn't exist.");
//One NumericUpDown is always greater than the other
if (true)
errorList.Add("File doesn't exist.");
//Assignment to static properties
if (true)
errorList.Add("File doesn't exist.");
return errorList;
}
}
public static class ErrorHandler
{
public static void HandleError(List<string> errorMessageList )
{
//Display your message here. This could return a dialog result as well for further processing.
}
}
}
Your method above seems like a perfectly fine way of laying out your code.
My only change would be in how you handle your checking. Use well-named methods rather than booleans during your check:
public void VerifyData()
{
if(FileExists())
{
LogError("The file specified is incorrect")
return;
}
if(CorrectExtension())
I need to write something that will get the start-up arguments and then do something for those start-up args, and I was thinking that switch would be good but it only accepts for ints and it has to be for a string
This isn't the actual code but I want to know how to make something like this work
namespace Simtho
{
class Program
{
static void Main(string[] args)
{
switch (Environment.GetCommandLineArgs())
{
case "-i":
Console.WriteLine("Command Executed Successfully");
Console.Read;
break;
}
}
}
}
Environment.GetCommandLineArgs() returns an array of strings. Arrays cannot be switched on. Try iterating over the members of the array, like this:
namespace Simtho
{
class Program
{
static void Main(string[] args)
{
foreach (string arg in Environment.GetCommandLineArgs())
{
switch (arg)
{
case "-i":
Console.WriteLine("Command Executed Successfully");
Console.Read();
break;
}
}
}
}
}
What about something like this?
string[] args = Environment.GetCommandLineArgs();
if (args.Contains("-i"))
{
// Do something
}
Environment.GetCommandLineArgs() returns array of strings?
And maybe i'm wrong but internally switch on strings converted to if-else sequence...
Environment.GetCommandLineArgs() returns a string[]
You can't switch on a string array. You probably want to test if the array contains certain values though.