I'm sorry, I can't really google this because I'm not sure how to properly say this in a few words.
But basically I'd like to have something like, when you open your program via dos or via a shortcut looking like this:
"c:\program.exe" value1 value2
that my application would be able to use these values. But also when I don't enter the values, that my application still starts fine.
I hope that made any sense what I'm trying to say here
Any help is appereciated
Those are the args that get passed to your main function:
public static void main (string[] args)
{
// Check to see if at least two args were passed in.
if(args.Length >= 2)
{
Console.WriteLine(args[0]); // value1
Console.WriteLine(args[1]); // value2
}
}
Keep in mind, though, that there's no way to guarantee the order of the args passed in or that they are the values you expect. You should use named arguments and then parse and validate them at the beginning of your application. Your command might look something like:
C:\program.exe /V1 value1 /V2 value2
As for a good list of parsers, I would check out:
.net - Best way to parse command line arguments in C#
Have a peek at the Microsoft tutorial for command line parameters
If a parameter isn't provided then just use some defauls.
public static void Main(string[] args)
{
// The Length property is used to obtain the length of the array.
// Notice that Length is a read-only property:
Console.WriteLine("Number of command line parameters = {0}",
args.Length);
for(int i = 0; i < args.Length; i++)
{
Console.WriteLine("Arg[{0}] = [{1}]", i, args[i]);
}
if(args.length < 2)
{
x = 1;
} else {
{
x = Arg[2];
}
}
When you create a executable you have a Main function that has Main(string[] args), here you can read the params which you used to call the program.
If you want default values, you can make a class variable with a defined value (or use the application properties) and if the program program is called with parameters overwrite them.
Hope it helps you :)
Execute your Program.exe from commandline this way
C:\Program Test1 Test2
To get knowledge on how to this in C# please use the link MSDN
Related
Relative newcomer to c# here.
Let’s say I have 50 different methods a1(), a2(), … a50() and I want to call a random one. One way to do it is of course to generate a random int, nr, between 1 and 50 and then use a lot of if statements like if(nr == 1){
a1()
} and so on. Quite cumbersome - can I do something smarter?
Is it for example possible to do something along the lines of creating a string which is initially only “a” and then adding nr as a string and then calling that string as method? Like this:
Public void RandomMethod()
{
nr = Random.Range(1,51);
string = ‘a’ + nr.tostring();
string();
}
I know this doesn’t work, but something like this instead of my first idea would save me hundreds of lines of code
Any response is appreciated 😊
One option would be to put your functions into a collection, say a List for example. Then you could randomly index into that collection to get a random function to call. You would generate a random index between 0 and the length of the List minus 1. This could apply generally to any number of functions then (50 or otherwise).
To do exactly what you asked (and, I have no clue why you'd want to), consider something like this:
Create a delegate that matches the call signature of all of your methods (they all have to have the same call signature or ... I really can't imagine what you'd want to do if they didn't). You could use an Action or Func declaration, but I'm going to make it clear here:
public delegate void SomeMethod(int i);
Then write your 50 methods. All their call signatures will match the delegate:
public static void Method1(int i) { System.Console.WriteLine($"{nameof(Method1)}: {i}"); }
public static void Method2(int i) { System.Console.WriteLine($"{nameof(Method2)}: {i}"); }
public static void Method3(int i) { System.Console.WriteLine($"{nameof(Method3)}: {i}"); }
public static void Method4(int i) { System.Console.WriteLine($"{nameof(Method4)}: {i}"); }
// ...
public static void Method50(int i) { System.Console.WriteLine($"{nameof(Method50)}: {i}"); }
Then create an array of delegates:
public static SomeMethod[] Methods = new SomeMethod[]
{
Method1,
Method2,
Method3,
Method4,
//...
Method50,
};
And then a method that picks 1 or more from the list at random and runs them:
public void Run5RandomMethods()
{
Random random = new Random();
for(int i = 0; i < 5; i++)
{
var randNumber = random.Next(50);
var method = Methods[randNumber];
method.Invoke(i);
}
}
Note: this is untested, I'm not going to create 50 dummy methods for you. If you find an issue, comment below and I'll fix the code
By the way, what you show in your question (composing the name of the method by concatenating a string and the string representation of a number) is doable using a technology known as Reflection. Let me know if you really want to do that.
So, assuming we have fifty methods that all have a signature like
void SomeMethod()
{
...
}
You could declare an array like below, this is an array of Action delegates
var methods = new Action[]
{
SomeMethod,
SomeOtherMethod,
() => _ = SomeFunctionWithAHardcodedParameter("Wibble"),
...
}
Then you could call a random method by doing,
method[Random.Next(methods.Length)]();
First off, I just want to say something similar to what others have already said: you should readdress whether you need 50 methods named a1(), a2(), ..., a50(), and rethink what the problem you're trying to solve is (which you haven't provided enough information for us to help you with).
If that was hyperbole, try to avoid doing that; it may muddy the responses to solve a perceived problem ("why do you have 50 poorly-named methods?") instead of your actual problem ("can I execute a randomly selected method?" <- still a weird question, but who am I to judge...).
That out of the way, you can use something like Reflection. This can be "dangerous" and expensive when executing, so use with caution... or better yet don't use it, but be aware of it, because it can lead you to think Reflection is the answer to problems you don't actually have.
Anyway, you can:
// have an instance of an object
var obj = new ClassName();
// get all the methods of the object
var methodInfos = typeof(ClassName).GetMethods();
// filter them somehow
var filteredMethodInfos = methodInfos.Where(m => Regex.IsMatch(m.Name, #"\a[\d]{1,2}")).ToArray();
// get a random one and invoke it
var rnd = new Random();
filteredMethodInfos[rnd.Next(filteredMethodInfos.Length)].Invoke(obj, null);
I haven't tested this, but it should in theory work.
But again: don't use reflection if you don't have to. There's probably an issue with your root question (as Tim Schmelter said, this is an "XY-problem") if your answer is "randomly execute 1 of 50 methods".
How do I go about checking the number of command line arguments entered and then printing an error if its less than 3.
static void Main(string[] args)
{
string file1 = args[0];
string file2 = args[1];
string file3 = args[2];
So if args is < 3, I need to print an erorr message and stop the program without running the next lines of code so that it doesnt give an error. Im just confused. Any help would be grealty appreciated
args is an array -- you have access to all methods related to arrays. So a simple implementation of your question could look like this:
if(args.Length < 3)
throw new ArgumentException("Must have three command line arguments");
It's almost always a good idea to ensure your variables aren't null before trying to access values on them (so the code could look like if(args == null || args.Length < 3), but per some commentary on this answer, these applications will never give you a null value for args, so it should be fine to omit that in this one specific case.
This question already has answers here:
Identify if a string is a number
(26 answers)
Closed 6 years ago.
I am writing a small console application in C# and it requires two numeric parameters/arguments to be passed to it. I am checking for no params, more than 2 params, if two params. I am also converting those params if 2 returned to numeric for calculations I'm doing. One thing I'm not doing is verifying what's being passed is a number so assume program will crap out if I pass a letter. Is there a look routing I can just run to verify the params passed are in deed able to be numbers? I can handle the kick out from there but curious how you check if an argument CAN be a number or not.
Thanks.
JR
I would simplify this task as follows:
Create custom Convert method:
static double Convert(string s)
{
double result;
if (!double.TryParse(s, out result))
result = double.NaN;
return result;
}
Use it in Main:
static void Main(string[] args)
{
var doubles = args.Select(a => Convert(a)).ToArray();
var valid = doubles.All(a => !double.IsNaN(a));
}
Here's one way;
static void Main(string[] args)
{
foreach (var arg in args)
{
int asInt;
// Returns "true" if arg can be parsed as an int and false otherwise;
// If you want to allow doubles you can also try double.TryParse in a similar manner
if (int.TryParse(arg, out asInt))
{
// Handle
}
// Failed to parse argument as an int
else
{
throw new ArgumentException("arg not an int");
}
}
}
You could also use a Regex:
static void Main(string[] args)
{
// Make sure this can is either an int or a double
var regex = new Regex(#"^-?(([0-9]+)|([0-9]+\.[0-9]+(e[0-9]+)?))$");
foreach (var arg in args)
{
if (!regex.IsMatch(arg))
throw new ArgumentException("arg " + arg + " is not an int or double");
}
}
Note a few important features of this regex:
- The "#" literal symbol in front of the regex string
- The ^ and $ to mark the beginning and end of lines - i.e. the string must contain only a number or only a double
- This bans empty strings as well
Edit: I edited the Regex to optionally allow for something like "1.0e100" or "-123", which, as pointed out in the comments, are also perfectly valid ints and doubles. Also, as pointed out in the comments, it's probably better to use int.TryParse or double.TryParse rather than reinventing the wheel.
There's also Char.IsDigit which always feels cleaner to me than checking for a failed parsing attempt. If you care about micro-optimizing, char.IsDigit is probably faster than parsing an invalid string too.
Or, if negative numbers or non-whole numbers are your thing, you can use char.IsNumber
See: https://msdn.microsoft.com/en-us/library/7f0ddtxh(v=vs.110).aspx
public static void Main(string[] args)
{
for(int i = 0; i < args.Length; i++)
{
if(args[i].All((c) => char.IsDigit(c))
{
//It's a number.
}
}
}
I have a (hopefully) simple C# question.
I am parsing arguments in a program where a file will be read from command line, I've allowed for both short and long arguments as input (so for my scenario /f and file are both valid)
The value after either of the above arguments should be the file name to be read.
What I want to do is find this file name in the array based off whichever argument is chosen and copy it in to a string while not leaving any loopholes.
I have functioning code, but I'm not really sure it's "efficient" (and secure).
Code (comments and writes removed):
if ( args.Contains("/f") || args.Contains("file"))
{
int pos = Array.IndexOf(args, "/f");
if (pos == -1)
pos = Array.IndexOf(args, "file");
if (pos > -1)
pos++;
inputFile = (args[pos]);
if (File.Exists(inputFile) == false)
{
Environment.Exit(0);
}
}
Is there a more efficient way to do this, perhaps using some nifty logic in the initial if statement to check which parameter is valid and then do a single check on that parameter?
Using 4 ifs and 2 Array.IndexOf's seems horrible just to support 2 different ways to allow someone to say they want to input a file...
Thanks! And I'm sorry if this seems trivial or is not what SO is meant for. I just don't have any real way to get feedback on my coding practises unfortunately.
Your solution won't scale well. Imagine you have two different arguments with a short and long form. How many conditionals and index checks would that be?
You'd be better off using an existing tool (e.g. Command Line Parser Library) for argument parsing.
One problem I see with the code you provided is that, it will fail if the /f or file is the last argument.
If you don't want to write or use complete argument parsing code, the following code will work slightly better.
var fileArguments = new string[] { "/f", "file" };
int fileArgIndex = Array.FindIndex(args,
arg => fileArguments.Contains(arg.ToLowerInvariant()));
if (fileArgIndex != -1 && fileArgIndex < args.Length - 1)
{
inputFile = args[fileArgIndex + 1];
if (!File.Exists(inputFile))
{
Environment.Exit(0);
}
}
You could write a simple argument parser for your specific need and still have support for "new" scenarios. For example, in your entry method have
// The main entry point for the application.
[STAThread]
static void Main(string[] args)
{
// Parse input args
var parser = new InputArgumentsParser();
parser.Parse(args);
....
}
Where your InputArgumentsParser could be something similar to
public class InputArgumentsParser
{
private const char ArgSeparator = ':';
private Dictionary<string[],Action<string>> ArgAction =
new Dictionary<string[],Action<string>>();
public InputArgumentsParser()
{
// Supported actions to take, based on args
ArgAction.Add(new[] { "/f", "/file" }, (param) =>
Console.WriteLine(#"Received file argument '{0}'", param));
}
/// Parse collection, expected format is "<key>:<value>"
public void Parse(ICollection<string> args)
{
if (args == null || !args.Any())
return;
// Iterate over arguments, extract key/value pairs
foreach (string arg in args)
{
string[] parts = arg.Split(ArgSeparator);
if (parts.Length != 2)
continue;
// Find related action and execute if found
var action = ArgAction.Keys.Where(key =>
key.Contains(parts[0].ToLowerInvariant()))
.Select(key => ArgAction[key]).SingleOrDefault();
if (action != null)
action.Invoke(parts[1]);
else
Console.WriteLine(#"No action for argument '{0}'", arg);
}
}
}
In this case /f:myfile.txt or /file:myfile.txt would spit out to console
Received file argument 'myfile.txt'
I am not sure what the problem is but I keep receiving this error when I try to use a while statement in my code.
Invalid token 'while' in class,
struct, or interface member
declaration
I want to use a while loop to have something continuously update while a statement is true.
The rest of my code is rather long but whenever I type in the syntax:
while(a<b)
{
//do whatever i want it to do here
}
It gives me that compiler error right off the bat. Not quite sure what the problem is. I am doing this in a C# windows application under the Form1.cs file with all the other event handlers (for buttons and such).
Thanks!
I was unaware that loops had to be placed within a method (fairly new to c#), but I tried it and no errors were returned. Thanks for your help everybody!
Previously, I just had the loop within the main class of the program.
Based on the error, it sounds like the compiler thinks this code is typed directly in the body of a class/struct/interface declaration. Statements while/if/for/etc ... must appear with in a method.
Try moving this code into a method to fix the problem. If it's in a method, you likely have a mismatched brace problem.
There's nothing wrong with the while, it's something above it that's the problem.
Check for mismatched braces and semicolons in a comment or something like that.
C# is not allowed to write code directly into the classes; it is allowed to write only data members and function members directly into the classes.
You can also get this if you have punctuation issues, I got it today when I missing a simple parentheses:
public static string GetPasswordForEnvironment)
should have been:
public static string GetPasswordForEnvironment()
But the error showed up on the first "if" statement later in the function.
C# does not provide writing the for, while or foreach kind of looping statement directly inside the class. These statements should be within a user defined method, main method or constructors.
class Array
{
public static void main(string[] args)
{
int[] n = new int[10]; /* n is an array of 10 integers */
/* initialize elements of array n */
for (int i = 0; i < 10; i++)
{
n[i] = i + 100;
}
/* output each array element's value */
foreach (int j in n)
{
int i = j - 100;
Console.WriteLine("Element[{0}] = {1}", i, j);
}
}
}