How would I make a switch statement populate a list, or comma delimited string?
For example
switch(test)
{
case 0:
"test"
break;
case 1:
"test2"
break;
case 2:
"test3"
break;
}
So my program will go into this statement multiple times. So lets say it goes in there twice and has case 2 and case 1. I woulld like a string value containing the following:
string value = "test3, test2"
Looks like a List<string> would be ideal to hold your values, you can create a comma separated string from that using string.Join():
List<string> myList = new List<string>();
//add items
myList.Add("test2");
//create string from current entries in the list
string myString = string.Join("," myList);
By multiple times, you mean a loop? You can just have a string and concatenate the string using + operator, or you can just have a list and add to it everytime the case condition is satisfied.
But if you mean by conditional flow so that you want case 0, 1 and 2 to all be evaluated, then you can simply omit the break and do the same concatenation like I mentioned above.
private string strValue = string.Empty;
private string StrValue
{
get
{
return strValue ;
}
set
{
StrValue= string.Concat(strValue , ",", value);
}
}
switch(test)
{
case 0:
StrValue = "test"
break;
case1:
StrValue = "test2"
break;
case 2:
StrValue = "test3"
breakl
}
Where ever you used StrValue remove "," if "," comes in the last.
There's a couple ways you can do it, a very simple one is:
string csv = "";
while (yourCriteria) {
string value;
// insert code to get your test value
switch(test)
{
case 0:
value = "test";
break;
case1:
value = "test2";
break;
case 2:
value = "test3";
break;
}
csv += value + ", ";
}
csv = csv.Length > 0 ? csv.Substring(0, csv.Length-2) : "";
Use a loop and a StringBuilder. If you're doing repeated concatenation, StringBuilders are significantly more efficient than naive string concatenation with +.
StringBuilder sb = new StringBuilder();
for(...)
{
switch(test)
{
case 0:
sb.Append("test");
break;
case1:
sb.Append("test2");
break;
case 2:
sb.Append("test3");
break;
}
}
Related
I have a string being passed to me which can be between 1 and 6 characters long. Depending on the length of the string I need to add the appropriate prefix to the start of the string and return the appeneded string. So if I have something like the following passed to me
1
12
123
1234
12345
123456
I want the return string to look like
X000001
X000012
X000123
X001234
X012345
X123456
I have come up with the following method
public static string AddToStartOfString(string s)
{
string value = string.Empty;
switch (s.Length)
{
case 1:
value = "X00000" + s;
break;
case 2:
value = "X0000" + s;
break;
case 3:
value = "X000" + s;
break;
case 4:
value = "X00" + s;
break;
case 5:
value = "X0" + s;
break;
case 6:
value = "X" + s;
break;
}
return value;
}
This works. But I need this to work in case in future more lengths are added. Is there a way where I can add the prefix even if the length of string is greater than 6 in the future
You can do this:
public static string AddToStartOfString(string s, int digitCount = 6)
{
return "X" + s.PadLeft(digitCount, '0');
}
Beware that an input string longer than the max number of digits, once transformed, will not be truncated and will be longer than for values in the correct range.
had a similar problem recently, in your case i would do:
public static string Fill(string str, string prefix, int length)
{
for(int i=str.Length; i<length; i++)
str = "0" + str;
return prefix + str;
}
I want to create a program that takes in a string and output just the numbers, hopefully using regex to save effort, here is the following code i have
public void main{
string str = "abc-123.44def";
string output = "";
bool setA = false;
StringBuilder stb = new StringBuilder();
for(int i=0; i<str.Length; i++){
switch(str[i]){
case 'b':
setA = foo();
break;
case 'c':
foo2();
break;
case '\d':
case '-':
case '.':
if(setA){
stb.Append(str[i]);
}
break;
default:
break;
}
}
output = stb.toString();
}
public void foo(){
return true;
}
Problem is, the editor gives me a error saying
Unrecognized Escape Sequence
on the '\d' part. Ive seen online sample codes where such usage is allowed so im not sure why my editor is not accepting this. Can someone explain to me what the problem is and how to solve it?
EDIT: It seems like my sample was alittle misleading. I cannot just take out the numbers from the strings by itself since other characters in the string calls different functions and the number characters i want to take out depends on some of them. I updated the code to correct the misinformation.
You can use the Char.IsDigit() to check if a char is a digit (as I mentioned in my first comment):
string str = "abc-123.44def";
string output = "";
bool setA = false;
StringBuilder stb = new StringBuilder();
for(int i=0; i<str.Length; i++){
switch(str[i]){
case 'b':
setA = foo();
break;
case 'c':
foo2();
break;
// case '\d': REMOVE IT
case '-':
case '.':
if(setA){
stb.Append(str[i]);
}
break;
default:
if (Char.IsDigit(str[i])) stb.Append(str[i]); // Add this
break;
}
}
output = stb.ToString();
}
Result:
Is this what you are looking for ?
Regex r = new Regex(#"\d+");
string s = "abc-123.44def";
var matches = r.Matches(s);
List<string> numbersOnly = new List<string>();
foreach (Match match in matches)
numbersOnly.Add(match.Value);
foreach (var number in numbersOnly)
Console.WriteLine(number);
//output:
//123
//44
The below code writes a list of chocolate to a CSV file:
using (StreamWriter outfile = new StreamWriter(#"C:\Users\Martin\Desktop\chocListWRITE.csv", true)) //true: append text to a file with StreamWriter. The file is not erased, but just reopened and new text is added to the end.
{
Chocolate _choc = new Chocolate();
string line = _choc.Serialize();
outfile.WriteLine(line);
Console.WriteLine(line);
}
in the console they are displayed as:
11111, Mars
22222, Bounty
33333, Snickes
But in the output CSV file they are displayed as:
11111, Mars 22222, Bounty 33333, Snickers
This is fine however IF POSSIBLE I would like the output file to store the results the same as the console, with a new line after each object. So for this I have tried to store them as an array and output that????
I am getting the error 'the file could not be written' index was outside the bounds of the array' with choc[arrayNo] = Escape(c._barcode.number);
//dummy data of list of chocolates assigned to 'Chocolates'
//serialize function
string[] fullList = new string[] { };
string[] choc = new string[] { };
int arrayNo = -1;
foreach (Choclate c in Choclates)
{
arrayNo = arrayNo + 1;
choc[arrayNo] = Escape(c._barcode.number);//returns barcode as string
choc[arrayNo + 1] = Escape(c._bar.barName);//returns name as string
}
return choc;
}
string Escape(String s)
{
StringBuilder sb = new StringBuilder();
bool needQuotes = false;
foreach (char c in s.ToArray())
{
switch (c)
{
case '"': sb.Append("\\\""); needQuotes = true; break;
case ' ': sb.Append(" "); needQuotes = true; break;
case ',': sb.Append(","); needQuotes = true; break;
case '\t': sb.Append("\\t"); needQuotes = true; break;
case '\n': sb.Append("\\n"); needQuotes = true; break;
default: sb.Append(c); break;
}
}
if (needQuotes)
return "\"" + sb.ToString() + "\"";
else
return sb.ToString();
}
What about using this?
return Choclates
.Select(i => Escape(i._barcode.number) + "," + Escape(i._bar.barName))
.ToArray();
This is a simple way to build a string array from a collection. You might have to add System.Linq to your usings.
Also, there's a few helpful methods you can use to make the whole job easier, for example, your Encode method can use this:
private static readonly char[] CharsToEncode = new []{'"', '\r', '\n', ',', '\t'};
string Escape(string str)
{
if (str.IndexOfAny(CharsToEncode) != -1)
{
return "\"" + str.Replace("\"", "\"\"") + "\"";
}
else
{
return str;
}
}
In any case, building a string array is completely unnecessary when you're using a StreamWriter. You only have to go through each of the chocolates and WriteLine each of them as needed. This will also add the endlines. If your results are unexpected, you're doing something else wrong. Are you perhaps using the WriteLine method only once instead of once per chocolate? Or, is your output shown in the browser? In that case, it would tend to be interpreted as HTML, which means it would appear there are no line breaks (you have to use <br /> for line breaks in HTML).
Even though you are setting arrayNo to negative 1 you will still get an off by one error in the rest of your code. MattC is correct, initialize the size of the array to be the same as the count of the Choclates list but then in addition, you need to change the line of code
choc[arrayNo + 1] = Escape(c._bar.barName);//returns name as string
Suppose you have an array that is 1 element then in your example, when you start inside the foreach loop, arrayNo is equal to 0:
var firstElement = choc[arrayNo] // arrayNo is 0 so an array of 1 item will be able to reference this
var secondElement = choc[arrayNo + 1] // choc is a 1 element array so you will get out of bounds exception
EDIT
Have you tried using "\r\n" instead of just "\n" for the newline character? That makes a difference on some systems.
Okay, if I have a string that I want to be equal to something based on multiple conditions, what's the best way to implement that?
Psuedocode
int temp = (either 1, 2, or 3)
string test = (if temp = 1, then "yes") (if temp = 2, then "no") (if temp = 3, then "maybe")
Is there some concise way to do this? What would you do?
Use a switch
switch(temp)
{
case 1:
return "yes";
case 2:
return "no";
case default:
return "maybe";
}
You can use a switch statement as mentioned in other answers but a dictionary can also be used:
var dictionary = new Dictionary<int, string>();
dictionary.Add(1, "yes");
dictionary.Add(2, "no");
dictionary.Add(3, "maybe");
var test = dictionairy[value];
This method is way more flexible than a switch statement and ever more readable than nested tenary operator statements.
string test = GetValue(temp);
public string GetValue(int temp)
{
switch(temp)
{
case 1:
return "yes";
case 2:
return "no";
case 3:
return "maybe";
default:
throw new ArgumentException("An unrecognized temp value was encountered", "temp");
}
}
You can use a switch statement
string temp = string.Empty;
switch(value)
{
case 1:
temp = "yes";
break;
case 2:
temp = "no";
break;
case 3:
temp = "maybe";
break;
}
The basic idea is:
String choices[] = {"yes","no","maybe"};
string test = choices[temp-1];
There are many different ways of actually implementing it. Depending on what your condition variable is, you might like to implement it as some sort of key-value list. SEE Zeebonk's answer for an example.
the obvious answer would be switch case
but just another flavor:
int temp = x; //either 1,2 or 3
string test = (temp == 1 ? "yes" : temp == 2 ? "no" : "maybe");
This switch is closer to your pseudocode and is exact C# code:
int temp = /* 1, 2, or 3 */;
string test;
switch(temp)
{
case 1:
test = "yes";
break;
case 2:
test = "no";
break;
case 3:
test = "maybe";
break;
default:
test = /* whatever you want as your default, if anything */;
break;
}
Your pseudocode doesn't include a default case, but it's good practice to include one.
The most concise answer is the nested ternary operator
string test = (temp == 1 ? "yes" : (temp == 2 ? "no" : (temp == 3 ? "maybe" : "")));
if temp values are only 1,2,3 then
string test = (temp == 1 ? "yes" : (temp == 2 ? "no" : "maybe"));
of course this is the concise answer as asked, and this doesn't means that it is the best.
If you could not exclude that, in future you will need more values to test, then it is better to use a dictionary approach as explained in the #zeebonk answer.
You can also turn things around:
class Program
{
enum MyEnum
{
Yes = 1,
No,
Maybe
}
static void Main(string[] args)
{
Console.WriteLine(MyEnum.Maybe.ToString());
Console.ReadLine();
}
}
This also is more in line that temp can be only 1, 2 or 3. If it's an int compiler won't warn you if temp gets value of 34.
You can also do this:
string GetText(int temp){
return ((MyEnum)temp).ToString();
}
GetText(2) will return "No"
I have a ASP.Net web handler that returns results of a query in JSON format
public static String dt2JSON(DataTable dt)
{
String s = "{\"rows\":[";
if (dt.Rows.Count > 0)
{
foreach (DataRow dr in dt.Rows)
{
s += "{";
for (int i = 0; i < dr.Table.Columns.Count; i++)
{
s += "\"" + dr.Table.Columns[i].ToString() + "\":\"" + dr[i].ToString() + "\",";
}
s = s.Remove(s.Length - 1, 1);
s += "},";
}
s = s.Remove(s.Length - 1, 1);
}
s += "]}";
return s;
}
The problem is that sometimes the data returned has quotes in it and I would need to javascript-escape these so that it can be properly created into a js object. I need a way to find quotes in my data (quotes aren't there every time) and place a "/" character in front of them.
Example response text (wrong):
{"rows":[{"id":"ABC123","length":"5""},
{"id":"DEF456","length":"1.35""},
{"id":"HIJ789","length":"36.25""}]}
I would need to escape the " so my response should be:
{"rows":[{"id":"ABC123","length":"5\""},
{"id":"DEF456","length":"1.35\""},
{"id":"HIJ789","length":"36.25\""}]}
Also, I'm pretty new to C# (coding in general really) so if something else in my code looks silly let me know.
For .net 4.0 + there is standard
HttpUtility.JavaScriptStringEncode
For earlier west wind solution described by Lone Coder is quite nice
Here is an efficient and robust method that I found at http://www.west-wind.com/weblog/posts/114530.aspx
/// <summary>
/// Encodes a string to be represented as a string literal. The format
/// is essentially a JSON string.
///
/// The string returned includes outer quotes
/// Example Output: "Hello \"Rick\"!\r\nRock on"
/// </summary>
/// <param name="s"></param>
/// <returns></returns>
public static string EncodeJsString(string s)
{
StringBuilder sb = new StringBuilder();
sb.Append("\"");
foreach (char c in s)
{
switch (c)
{
case '\"':
sb.Append("\\\"");
break;
case '\\':
sb.Append("\\\\");
break;
case '\b':
sb.Append("\\b");
break;
case '\f':
sb.Append("\\f");
break;
case '\n':
sb.Append("\\n");
break;
case '\r':
sb.Append("\\r");
break;
case '\t':
sb.Append("\\t");
break;
default:
int i = (int)c;
if (i < 32 || i > 127)
{
sb.AppendFormat("\\u{0:X04}", i);
}
else
{
sb.Append(c);
}
break;
}
}
sb.Append("\"");
return sb.ToString();
}
I think you should rather look at the JavaScriptSerializer class. It's a lot more stable, and will correctly handle any kind of data or escape characters etc. Also, your code will look a lot cleaner.
In your case your class can look like this:
public static String dt2JSON(DataTable dt) {
var rows = new List<Object>();
foreach(DataRow row in dt.Rows)
{
var rowData = new Dictionary<string, object>();
foreach(DataColumn col in dt.Columns)
rowData[col.ColumnName] = row[col];
rows.Add(rowData);
}
var js = new JavaScriptSerializer();
return js.Serialize(new { rows = rows });
}
This method will return a correctly serialized json string... For example, sth like this:
{"rows":[{"id":1,"name":"hello"},{"id":2,"name":"bye"}]}
Have fun! :)
To correctly escape a string literal for Javascript, you first escape all backslash characters, then you escape the quotation marks (or apostrophes if you use them as string delimiters).
So, what you need is:
value.Replace("\\","\\\\").Replace("\"","\\\"")
What else jumps out to me is that you are using string concatenation in a loop. This is bad, as it scales very poorly. The += operator does not add characters at the end of the existing string (as strings are immutable and can never be changed), instead it copies the string and the added characters to a new string. As you copy more and more data each time, eEvery additional row roughly doubles the execution time of the method. Use a StringBuilder to build the string instead.
Use the ColumnName property to get the name of a column rather than the ToString method. The ToString method returns the Expression property value if it's set, only if that is not set does it return the ColumnName property.
public static String dt2JSON(DataTable dt) {
StringBuilder s = new StringBuilder("{\"rows\":[");
bool firstLine = true;
foreach (DataRow dr in dt.Rows) {
if (firstLine) {
firstLine = false;
} else {
s.Append(',');
}
s.Append('{');
for (int i = 0; i < dr.Table.Columns.Count; i++) {
if (i > 0) {
s.Append(',');
}
string name = dt.Columns[i].ColumnName;
string value = dr[i].ToString();
s.Append('"')
.Append(name.Replace("\\","\\\\").Replace("\"","\\\""))
.Append("\":\"")
.Append(value.Replace("\\","\\\\").Replace("\"","\\\""))
.Append('"');
}
s.Append("}");
}
s.Append("]}");
return s.ToString();
}
string.Replace(<mystring>, #"\"", #"\\"");
Why don't you just do this:
string correctResponseText = wrongResponseText.Replace("\"", "\\\"");
Works when i need send string from C# to html tag.
<buton onlick="alert('<< here >>')" />
HttpUtility.HtmlEncode
Here is a rework of #Bryan Legend's answer with Linq:
public static string EncodeJavaScriptString(string s)
=> string.Concat(s.Select(c => {
switch (c)
{
case '\"': return "\\\"";
case '\\': return "\\\\";
case '\b': return "\\b";
case '\f': return "\\f";
case '\n': return "\\n";
case '\r': return "\\r";
case '\t': return "\\t";
default: return (c < 32 || c > 127) && !char.IsLetterOrDigit(c) ? $"\\u{(int)c:X04}" : c.ToString();
}}));
Try it Online!
changelog:
Remove double quoting wrapping since I do it in the js
Use expression body
Use a cleaner switch
Use Linq
Add a check for Letter to allow é
Well, for starters you do not need quotes around the keys.
{rows:[,]} is valid.
and you could dt.Table.Columns[i].ToString().Replace("\","")
But if you want to retain the double quotes, single quote works the same way double quotes do in JS
Otherwise you could do
String.Format("{name: \"{0}\"}",Columns[i].ToString().Replace("\",""))