I made a code to "translate" paths or texts in general to the Git Bash syntax, at the time I didn't know that I could just put them inside '', in the code I use the $ special character on a couple of strings, compile the code via csc filename.cs on cmd, it gives me the .exe and its all great, today I go make some minor changes on the code and when I run the same code to compile it gives me:
GiTranslator.cs(59,62): error CS1056: Unexpected character '$'
GiTranslator.cs(71,25): error CS1056: Unexpected character '$'
GiTranslator.cs(72,25): error CS1056: Unexpected character '$'
GiTranslator.cs(73,25): error CS1056: Unexpected character '$'
so, why? And what can I do to fix it?
note: the minor changes were literally just some spelling on comments.
edit 1: as asked, the code(it is probably terrible, sorry):
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
namespace Git_Path_Translator
{
class Program
{
#region Functions
static void actuallyResetColors()
{
Console.BackgroundColor = ConsoleColor.Black;
Console.ForegroundColor = ConsoleColor.White;
Console.Clear();
Console.Write(".");
Console.Clear();
}
#endregion
#region Global Variables
static string path;
static bool repetTranslation;
static bool repetAfterExcep;
#endregion
[STAThread] // don't know what it does, but its needed, classic right?
static void Main(string[] args)
{
Console.BackgroundColor = ConsoleColor.DarkCyan;
Console.ForegroundColor = ConsoleColor.Yellow;
Console.Title = "Path Translator for Git Bash - by Tom Zamataro"; // just some credit to me, that no one is going to see, classic right?
Console.Clear();
// set up for the API loop
do
{
repetTranslation = false;
path = "";
Console.WriteLine("\n Inform the path you would like to translate to Git Bash syntax:");
Console.Write("\n "); // just for aesthetics, class... sory, no more classic joke tho, right? yes, I've a lot of shit in my head
// set up for the exception handling loop
do
{
repetAfterExcep = false;
try
{
if (path == "")
{
path = Console.ReadLine();
}
#region The Translation
string[] metaChars = new string[] { #"\", " ", "<", ">", "&", ";","*",
"?", "#", ".", "~", "|", "!", "$", "(", ")", "[", "]", "{", "}", "'", "\"" }; // the meta characters that I've to deal with
foreach (string meta in metaChars)
{
// backslash is the special case in this contex
if (meta == #"\") { path = path.Replace(meta, "/"); }
// the rest
else { path = path.Replace(meta, $#"\{meta}"); }
}
path = path.Trim(new char[] { '\'', '"' }); // jusr making sure, ..., what? I didn't say anything
/*
* the fist way I did, yes, much worse, you know alredy, right?
* path = path.Trim().Replace(#"\", "/").Replace(" ", #"\ ").Replace("(", #"\(").Replace(")", #"\)"); // taking of the spaces and putting '\' where its needed
* path = path.Replace("[", #"\[").Replace("]", #"\]").Replace("{", #"\{").Replace("}", #"}]").Trim('"'); // nor sure if
*/
#endregion
Clipboard.SetText(path); // coping it to the user's clipboard
Console.WriteLine
(
$"\n The path was translated to:" +
$"\n\n {path}" +
$"\n\n and it is alredy copied to your clipbord."
); // just a bit more of aestheticness, yeah, ..., go on continue throught the code
}
catch (ArgumentNullException)
{
Console.Clear();
Console.WriteLine("\n Please inform a non-null value so the translation is possible," +
"\n if you would like to finish the solution, press enter:");
Console.Write("\n "); // same thing as before, just for aesthetics
if ((path = Console.ReadLine()) == "")
{
// didn't want to a valid translation
actuallyResetColors(); // Console.ResetColor() isn't all that great on doing its job, so, yeah
Console.Write("\n "); // aesthetic for VS console
Environment.Exit(0);
}
else { repetAfterExcep = true; } // did want to do a valid translation
}
} while (repetAfterExcep); // exception handling loop
Console.Write
(
"\n Type anything and press enter to make another translation,\n" +
" or press enter to finish the solution: "
); // asking for the loop
if (Console.ReadLine() == "")
{
// didn't want to do another translation
actuallyResetColors(); // Console.ResetColor() isn't that great on doing its job, so, yeah
Console.Write("\n "); // aesthetics for VS console
Environment.Exit(0);
}
// did want to do another translation
repetTranslation = true;
Console.Clear();
} while (repetTranslation); // API loop
}
}
}
edit 2: maybe useful information, I can normally run the code on VS, but when I try to compile it via csc filename.exe it gives me that error.
edit 3: so,
well, I don't know what to think or say about that.
Related
Let me start off saying that I'm new to C#.
I'm currently in the making of my first command-line application that in it's current state can do two things. One of them is a calculator, for which I need more learning to actually make it work, and the other is a string capitalizer.
I have a string nameCapInput = Console.Readline() that takes in the user input, which then gets analyzed to make sure that no digits are allowed:
using System;
using System.Linq;
namespace First_Console_Project
{
class Program
{
static void Main(string[] args)
{
Console.WriteLine("My first ever console application - 2020/2/26\n\n\n");
programSel:
Console.WriteLine("What do you want to do?\n");
Console.WriteLine("1. Calculate Numbers \n2. Capitalize Letters/Strings");
Console.WriteLine("Input your desired action:");
var inputVar = Console.ReadLine();
switch (inputVar)
{
case "1":
//Calculator code goes here
Console.WriteLine("Number 1 succeeded, opening calculator... Stand by");
Console.WriteLine("Calulator Loaded.");
Console.WriteLine("Doesn't work right now. Type \"exit\" to get back to the \"what do you want to do\" page.");
//Code goes here when I have learned the proper methods
calcInput:
var calcInput = Console.ReadLine();
if (calcInput == "exit")
{
goto programSel;
} else
{
Console.WriteLine("Unknown command. Type \"exit\" to get back to the \"what do you want to do\" page.");
goto calcInput;
}
case "2":
Console.WriteLine("Loading string capitalizer...");
Console.WriteLine("Type any string made of letters only without spaces, because if you use spaces, the program will exit. The output will make them all uppercase. Type \"exit\" to get back to the \"what do you want to do\" page.");
inputCap:
string nameCapInput = Console.ReadLine();
bool containsInt = nameCapInput.Any(char.IsDigit);
bool isMadeOfLettersOnly = nameCapInput.All(char.IsLetter);
if (nameCapInput == "exit")
{
goto programSel;
}
else if (containsInt)
{
Console.WriteLine("You can't capitalize numbers. Use letters only. Try again.");
goto inputCap;
}
else if (isMadeOfLettersOnly)
{
string upper = nameCapInput.ToUpper();
Console.WriteLine($"The uppercase version of your entered text is: {upper}");
goto inputCap;
}
break;
}
}
}
}
Now, everything works fine and it capializes everything I put into it except strings with spaces in them. When I type in a string with spaces in it, the program just exits with code 0. I'm not very good at C# yet, so I don't really know where to go from here. Any help is appreciated.
Every time I learn something new in C#, I try to implement it into my projects, so I can actually learn how to implement it to know when and how to use what I learned. This is an example for that.
EDIT: Added the rest of the code.
Thank you all very much. There's two things I have learned here:
goto is a bad habit
I absolutely need to start learning to debug my own code.
The crux of your problem is that you are only checking if the input contains letters (not spaces). An easy fix is to change your LINQ a bit.
bool isMadeOfLettersOnly = nameCapInput.All(c => char.IsLetter(c) || char.IsWhiteSpace(c));
So now input with letters or spaces will be considered valid.
In addition, your use of goto is a very bad idea. Generally there should never be any reason to use goto.
To fix this, use a while loop and a method:
public static void Main()
{
bool exit = false;
do {
exit = ProcessInput();
}
while(!exit);
}
private static bool ProcessInput()
{
string nameCapInput = Console.ReadLine();
bool containsInt = nameCapInput.Any(char.IsDigit);
bool isMadeOfLettersOnly = nameCapInput.All(c => char.IsLetter(c) || char.IsWhiteSpace(c));
if (nameCapInput.Equals("exit", StringComparison.CurrentCultureIgnoreCase))
{
return true; //exiting so return true
}
else if (containsInt)
{
Console.WriteLine("You can't capitalize numbers. Use letters only. Try again.");
}
else if (isMadeOfLettersOnly)
{
string upper = nameCapInput.ToUpper();
Console.WriteLine("The uppercase version of your entered text is: {0}", upper);
}
return false; //no exit, so return false
}
This is just a quick refactor, you could make it better.
Fiddle here
Check the documentation: https://learn.microsoft.com/en-us/dotnet/api/system.char.isletter?view=netframework-4.8
Based on the documentation of the IsLetter function, the space is not included in the return true cases.
I would suggest that you use regular expressions for this or change your last case to
else if (!containsInt)
{
var upper = nameCapInput.ToUpper();
Console.WriteLine($"The uppercase version of your entered text is: {upper}");
goto inputCap;
}
Also check the documentation of goto: https://learn.microsoft.com/en-us/dotnet/csharp/language-reference/keywords/goto
The goto statement transfers the program control directly to a labeled statement.
A common use of goto is to transfer control to a specific switch-case label or the default label in a switch statement.
The goto statement is also useful to get out of deeply nested loops.
You are not in any such case, so you shouldn't use it.
I am reading strings from command line. But end of stream can not be detected by my program. How do I reconstruct this or is there a way to explicitly set EndOfStream to true?
List<String> str = new List<String>();
using (StreamReader reader = new StreamReader(Console.OpenStandardInput()))
while (!reader.EndOfStream)
{
string line = reader.ReadLine();
if (line != string.Empty)
{
str.Add(line);
}
}
That cannot work out by design. The stdin/stdout console streams are opened as long as the program is active. The EndOfStream is executed just before you close the application in this case.
A good solution for your issue is.
using System;
public class Example
{
public static void Main()
{
string line;
do {
line = Console.ReadLine();
if (line != null)
Console.WriteLine("Now I have detected the end of stream.... " + line);
} while (line != null);
}
}
Your code is fine.
When reading from the console, EOF is indicated by entering:
^z then ENTER.
This is a standard as old as DOS. Unix has a similar standard, but it is ^d.
Bill Gates either didn't know Unix or chose to be different but not better. This is why it is ^z not ^d
Likewise, DOS and Windows treat "/" as a command line option delimiter, even though "/" and "" are handled by windows internals as path delimiters.
I'm trying to pass command-line arguments to a C# application, but I have problem passing something like this
"C:\Documents and Settings\All Users\Start Menu\Programs\App name"
even if I add " " to the argument.
Here is my code:
public ObjectModel(String[] args)
{
if (args.Length == 0) return; //no command line arg.
//System.Windows.Forms.MessageBox.Show(args.Length.ToString());
//System.Windows.Forms.MessageBox.Show(args[0]);
//System.Windows.Forms.MessageBox.Show(args[1]);
//System.Windows.Forms.MessageBox.Show(args[2]);
//System.Windows.Forms.MessageBox.Show(args[3]);
if (args.Length == 3)
{
try
{
RemoveInstalledFolder(args[0]);
RemoveUserAccount(args[1]);
RemoveShortCutFolder(args[2]);
RemoveRegistryEntry();
}
catch (Exception e)
{
}
}
}
And here is what I'm passing:
C:\WINDOWS\Uninstaller.exe "C:\Program Files\Application name\" "username" "C:\Documents and Settings\All Users\Start Menu\Programs\application name"
The problem is I can get the first and the second args correctly, but the last one it gets as C:\Documents.
Any help?
I just ran a check and verified the problem. It surprised me, but it is the last \ in the first argument.
"C:\Program Files\Application name\" <== remove the last '\'
This needs more explanation, does anybody have an idea? I'm inclined to call it a bug.
Part 2, I ran a few more tests and
"X:\\aa aa\\" "X:\\aa aa\" next
becomes
X:\\aa aa\
X:\\aa aa" next
A little Google action gives some insight from a blog by Jon Galloway, the basic rules are:
the backslash is the escape character
always escape quotes
only escape backslashes when they precede a quote.
To add Ian Kemp's answer
If you assembly is called "myProg.exe" and you pass in the string "C:\Documents and Settings\All Users\Start Menu\Programs\App name" link so
C:\>myprog.exe "C:\Documents and Settings\All Users\Start Menu\Programs\App name"
the string "C:\Documents and Settings\All Users\Start Menu\Programs\App name"
will be at args[0].
To add to what everyone else has already said, It might be an escaping problem. You should escape your backslashes by another backslash.
Should be something like:
C:\>myprog.exe "C:\\Documents and Settings\\All Users\\Start Menu\\Programs\\App name"
I noticed the same annoying issue recently, and decided to write a parser to parse the command line arguments array out myself.
Note: the issue is that the .NET CommandLine Arguments passed to the static void Main(string[] args) function escapes \" and \\. This is by design, since you may actually want to pass an argument that has a quote or backslash in it. One example:
say you wanted to pass the following as a single argument:
-msg:Hey, "Where you at?"
eg.
sampleapp -msg:"Hey, \"Where you
at?\""
Would be how to send it with the default behavior.
If you don't see a reason for anyone to have to escape quotes or backslashes for your program, you could utilize your own parser to parse the command line, as below.
IE.
[program].exe "C:\test\" arg1 arg2
would have a args[0] = c:\test" arg1 arg2
What you would expect is args[0]=c:\test\ and then args[1]=arg1 and args[2]=arg2.
The below function parses the arguments into a list with this simplified behavior.
Note, arg[0] is the program name using the below code. (You call List.ToArray() to convert the resulting list to a string array.)
protected enum enumParseState : int { StartToken, InQuote, InToken };
public static List<String> ManuallyParseCommandLine()
{
String CommandLineArgs = Environment.CommandLine.ToString();
Console.WriteLine("Command entered: " + CommandLineArgs);
List<String> listArgs = new List<String>();
Regex rWhiteSpace = new Regex("[\\s]");
StringBuilder token = new StringBuilder();
enumParseState eps = enumParseState.StartToken;
for (int i = 0; i < CommandLineArgs.Length; i++)
{
char c = CommandLineArgs[i];
// Console.WriteLine(c.ToString() + ", " + eps);
//Looking for beginning of next token
if (eps == enumParseState.StartToken)
{
if (rWhiteSpace.IsMatch(c.ToString()))
{
//Skip whitespace
}
else
{
token.Append(c);
eps = enumParseState.InToken;
}
}
else if (eps == enumParseState.InToken)
{
if (rWhiteSpace.IsMatch(c.ToString()))
{
Console.WriteLine("Token: [" + token.ToString() + "]");
listArgs.Add(token.ToString().Trim());
eps = enumParseState.StartToken;
//Start new token.
token.Remove(0, token.Length);
}
else if (c == '"')
{
// token.Append(c);
eps = enumParseState.InQuote;
}
else
{
token.Append(c);
eps = enumParseState.InToken;
}
}
//When in a quote, white space is included in the token
else if (eps == enumParseState.InQuote)
{
if (c == '"')
{
// token.Append(c);
eps = enumParseState.InToken;
}
else
{
token.Append(c);
eps = enumParseState.InQuote;
}
}
}
if (token.ToString() != "")
{
listArgs.Add(token.ToString());
Console.WriteLine("Final Token: " + token.ToString());
}
return listArgs;
}
In response to WWC's answer, Jamezor commented that his code will fail if the first character is a quote.
To fix that problem, you can replace the StartToken case with this:
if (eps == enumParseState.StartToken)
{
if (rWhiteSpace.IsMatch(c.ToString()))
{
//Skip whitespace
}
else if (c == '"')
{
eps = enumParseState.InQuote;
}
else
{
token.Append(c);
eps = enumParseState.InToken;
}
}
What exactly is the problem? Anyway here's some general advice:
Make sure your Main method (in Program.cs) is defined as:
void Main(string[] args)
Then args is an array containing the command-line arguments.
I'm trying to set up an mIRC bot for my channel, and my current project is playing an audio file on my computer whenever a certain event happens.
I've written a short C# console app that gets the name of the file from the arguments, and plays that file.
This works running it from cmd or using a shortcut, but when I enter the command on my channel, the program comes up, but throws a FileNotFound exception.
I wrote some code using try{} catch{} to see exactly what's happening. In the event that the file fails to play, it will first list the argument that was provided, the extension (I'm going to change this later), and finally the combined string. What it comes up with it this:
args[0]: audiofile
extension: .wav
filename: audiofile.wav
Which is exactly what the file name is, and that plays perfectly from the command line.
Does anybody know what's going on here?
static void Main(string[] args)
{
string extension = ".wav";
string filename = "null";
if (args == null || args.Length == 0)
{
Console.WriteLine("No arguments provided!");
Console.ReadLine();
return;
}
filename = args[0] + extension;
Console.Write("Press enter to play grenade... ");
Console.ReadLine();
try
{
Console.WriteLine("Playing file " + filename);
(new SoundPlayer(filename)).Play();
}
catch
{
Console.WriteLine("Error!");
Console.WriteLine("args[0]: " + args[0]);
Console.WriteLine("extension: " + extension);
Console.WriteLine("filename: " + filename);
}
Console.ReadLine();
}
mIRC script:
on $*:text:!grenade:#: {
/run "c:/users/electrospeed/documents/visual studio 2013/projects/audioplayer/audioplayer/bin/debug/audioplayer.exe" audiofile
}
At the mIRC code, you wrote audiofile at the end, correct me if i'm wrong, but I guess you meant %audiofile like in variable.
I don't think you need the quotation marks in the directory path.
I am trying to learn the basics of C# using Sams Teach Yourself C# in 21 days.
I have created this program by copying it line by line from the day 1 type and run section. It compiles fine but when you run it, it gives this error: "Input string was not in the correct format".
I am running the program from the console.
I am using the Visual Studio 2010 Express editor.
The code I copied is:
using System;
using System.IO;
/// <summary>
/// Class to number a listing. Assumes fewer than 1000 lines.
/// </summary>
class NumberIT
{
/// <summary>
/// The main entry point for the application.
/// </summary>
public static void Main(string[] args)
{
// check to see if a file name was included on the command line.
if (args.Length <= 0)
{
Console.WriteLine("\nYou need to include a filename.");
}
else
{
// declare objects for connecting to files...
StreamReader InFile = null;
StreamWriter OutFile = null;
try
{
// Open file name included on command line...
InFile = File.OpenText(args[0]);
// Create the output file...
OutFile = File.CreateText("outfile.txt");
Console.Write("\nNumbering...");
// Read first line of the file...
string line = InFile.ReadLine();
int ctr = 1;
// loop through the file as long as not at the end...
while (line != null)
{
OutFile.WriteLine("{1}: {2}", ctr.ToString().PadLeft(3, '1'), line);
Console.Write("..{1]..", ctr.ToString());
ctr++;
line = InFile.ReadLine();
}
}
catch (System.IO.FileNotFoundException)
{
Console.WriteLine("Could not find the file {0}", args[0]);
}
catch (Exception e)
{
Console.WriteLine("Error: {0}", e.Message);
}
finally
{
if (InFile != null)
{
// Close the files
InFile.Close();
OutFile.Close();
Console.WriteLine("...Done.");
}
}
}
}
}
Your culprits here are the OutFile.WriteLine and Console.Write statements:
OutFile.WriteLine("{1}: {2}", ctr.ToString().PadLeft(3, '1'), line);
Console.Write("..{1]..", ctr.ToString());
It should read:
OutFile.WriteLine("{0}: {1}", ctr.ToString().PadLeft(3, '1'), line);
Console.Write("..{0}..", ctr.ToString());
Note that the placeholders in the format string start from 0. Your closing bracket on the second statement was a square bracket instead of a curly one.
Another tip: you don't need to call .ToString() on ctr in the latter case, unless you wanna specify a culture explicitly.
Few things to note:
OutFile.WriteLine("{1}: {2}", ctr.ToString().PadLeft(3, '1'), line);
the index is 0 based, so it should be OutFile.WriteLine("{0}: {1}"...
Console.Write("..{1]..", ctr.ToString());
there is a typo here! (I hope!), and again it should be 0 not 1.