How to calculate output of Infix-Expression by using stacks in C# - c#

I already found different solutions on Stackoverflow, but there were some things I didn´t understand.
Whats the best method to calculate the Output of e.g.: ((1+(4*(2+3)))+((2+3)*(4*5))) ?
My method looks as following, but I know there are lots of mistakes in it:
public static int ComputeInfix(string infix) {
Stack<char> operatorstack = new Stack<char>();
Stack<int> operandstack = new Stack<int>();
for(int j = 0; j < infix.Length; j++) {
char c = infix[j];
if (c => 0 && c <= 9) {
operandstack.Push(c);
}
else if ((c == '+' || c == '*' || c == '/' || c == '-')) {
if (operatorstack.IsEmpty()) {
operatorstack.Push(c);
}
else {
if (operatorstack.Peek() != '*' || operatorstack.Peek() != '/') {
operatorstack.Push(c);
}
}
}
else if (c == '(') {
operatorstack.Push(c);
}
else if (c == ')') {
operatorstack.Pop();
}
}
return infix;
}
Now changed it to:
Stack<char> operatorstack = new Stack<char>();
Stack<char> operandstack = new Stack<char>();
for(int j = 0; j < infix.Length; j++) {
char c = infix[j];
if (c => '0' && c <= '9') {
operandstack.Push(c);
}
But get error:
Infix.cs(16,8): error CS0136: A local variable named c' cannot be
declared in this scope because it would give a different meaning to
c', which is already used in a `parent or current' scope to denote
something else

Since I spent the time to write it, here is my solution:
public static int ComputeInfix(string infix) {
var operatorstack = new Stack<char>();
var operandstack = new Stack<int>();
var precedence = new Dictionary<char, int> { { '(', 0 }, { '*', 1 }, { '/', 1 }, { '+', 2 }, { '-', 2 }, { ')', 3 } };
foreach (var ch in $"({infix})") {
switch (ch) {
case var digit when Char.IsDigit(digit):
operandstack.Push(Convert.ToInt32(digit.ToString()));
break;
case var op when precedence.ContainsKey(op):
var keepLooping = true;
while (keepLooping && operatorstack.Count > 0 && precedence[ch] > precedence[operatorstack.Peek()]) {
switch (operatorstack.Peek()) {
case '+':
operandstack.Push(operandstack.Pop() + operandstack.Pop());
break;
case '-':
operandstack.Push(-operandstack.Pop() + operandstack.Pop());
break;
case '*':
operandstack.Push(operandstack.Pop() * operandstack.Pop());
break;
case '/':
var divisor = operandstack.Pop();
operandstack.Push(operandstack.Pop() / divisor);
break;
case '(':
keepLooping = false;
break;
}
if (keepLooping)
operatorstack.Pop();
}
if (ch == ')')
operatorstack.Pop();
else
operatorstack.Push(ch);
break;
default:
throw new ArgumentException();
}
}
if (operatorstack.Count > 0 || operandstack.Count > 1)
throw new ArgumentException();
return operandstack.Pop();
}

Related

Convert lots of if's to something smaller

I need to check a char array and convert every char to a random number value into a int array;
I have managed to do this but with a lot of code.
Is there anyway I can write less code?
for (int i = 0; i < 8; i++)
{
if (oddF[i] == '0')
{
oddFlValue[i] = 1;
continue;
}
else if (oddF[i] == '1')
{
oddFValue[i] = 0;
continue;
}
else if (oddFiscal[i] == '8')
{
oddFiscalValue[i] = 19;
continue;
}
else if (oddF[i] == '9')
{
oddFValue[i] = 21;
continue;
}
else if ((oddF[i] == 'a') || (oddF[i] == 'A'))
{
oddFValue[i] = 1;
continue;
}
else if ((oddF[i] == 'b') || (oddF[i] == 'B'))
{
oddFValue[i] = 0;
continue;
}
This is just a sample as I need to check for every number and letter type.
Thanks!
I think the easiest way to do this would be to use a Dictionary<char, int>, and get its value. Something like this:
Dictionary<char, int> MyCombinations = new Dictionary<char, int>{
{'0', 1},
{'5', 15},
/*etc etc etc*/
};
And then use it like:
for (int i = 0; i < 8; i++)
{
oddFValue[i] = MyCombinations[oddFiscal[i]];
}
class Program
{
static void Main(string[] args)
{
char[] oddF = new char[8]{'0','1','8','A','b','9','a','B'};
int[] oddFValue = new int[8];
Dictionary<char, int> table = new Dictionary<char, int>(){
{ '0', 1 },
{ '1', 0 },
{ '8', 19 },
{ '9', 21 },
{ 'a', 1 },
{ 'A', 1 },
{ 'b', 0 },
{ 'B', 0 }
};
for (int i = 0; i < 8; i++)
{
oddFValue[i] = table[oddF[i]]; // Lookup which function should be called, and call it.
}
}
}
How about:
public int? ConvertCharToInt(char c)
{
switch (c)
{
case '0': return 1;
case '1': return 0;
case '8': return 19;
case '9': return 21;
case 'a':
case 'A': return 1;
case 'b':
case 'B': return 0;
// ...
default: return null;
}
}
And then:
for (int i = 0; i < 8; i++)
{
int? number = ConvertCharToInt(oddF[i]);
if (number.HasValue)
oddFValue[i] = number.Value;
else
// Character cannot be converted to int value
}

count vowels, consonants and numeric

What's wrong with my code? If I enter aaa, it returns 3 in the vowels row, but if I enter abc, it return 3 also in the vowels row.
By the way, it's a windows form .
txtInputString.SelectionStart = 0;
txtInputString.SelectionLength = txtInputString.Text.Length;
txtInputString.Focus();
int vowelCount = 0, consonants = 0, nonNumeric = 0;
int count = txtInputString.TextLength;
for (int i = 0; i < count; i++)
{
if ((txtInputString.Text.Contains('a') == true) || (txtInputString.Text.Contains('e') == true) || (txtInputString.Text.Contains('i')== true) || (txtInputString.Text.Contains('o')==true) || (txtInputString.Text.Contains('u')==true))
{
vowelCount++;
}
else if ((txtInputString.Text.Contains('b') == true) || txtInputString.Text.Contains('c') || txtInputString.Text.Contains("d") || txtInputString.Text.Contains("f") || txtInputString.Text.Contains("g"))
{
consonants++;
}
else
{
nonNumeric++;
}
}
txtVowel.Text = vowelCount.ToString() + "";
txtConsonant.Text = consonants.ToString() + "";
txtNonNumeric.Text = nonNumeric.ToString();
Try that :
txtInputString.SelectionStart = 0;
txtInputString.SelectionLength = txtInputString.TextLength;
txtInputString.Focus();
int vowelCount = 0, consonants = 0, nonNumeric = 0;
int count = txtInputString.TextLength;
for (int i = 0; i < count; i++)
{
char c = txtInputString.Text.ElementAt(i);
if (c == 'a' || c == 'e' || c == 'i' || c == 'o' || c == 'u')
vowelCount++;
else if (c == 'b' || c =='c' || c == 'd' || c == 'f')
consonants++;
else
nonNumeric++;
}
txtVowel.Text = vowelCount.ToString() + "";
txtConsonant.Text = consonants.ToString() + "";
txtNonNumeric.Text = nonNumeric.ToString();
you can make this a lot more simple by loading up all your consonants and vowels beforehand and applying some LINQ:
string consonants = "bcdfghjklmnpqrstvwxyz";
string vowels = "aeiou";
int vowelCount = 0, consonantCount = 0, nonNumericCount = 0;
var input = "alsdkghanivhusrvndb"; //some input
foreach (char t in input)
{
if (consonants.Any(c => c == t))
consonantCount++;
else if (vowels.Any(c => c == t))
vowelCount++;
else
nonNumericCount++;
}

Counting number of vowels in a string

I have a textbox where the user enters a random string. I want to count the number of vowels(A,E,I,O,U) in the string and show th results in the labelcontrol.
protected void Button1_Click(object sender, EventArgs e)
{
string EnterString;
EnterString = TextBox1.Text;
char ch1 = 'a';
char ch2 = 'e';
char ch3 = 'i';
char ch4 = 'o';
char ch5 = 'u';
int counta = 0;
int counte = 0;
int counti = 0;
int counto = 0;
int countu = 0;
char ch6 = 'A';
char ch7 = 'E';
char ch8 = 'I';
char ch9 = 'O';
char ch10 = 'U';
int countA = 0;
int countE = 0;
int countI = 0;
int countO = 0;
int countU = 0;
//const string vowels = "aeiou";
/* return value.Count(chr => vowels.Contains(char.ToLower(chr)));
return Value.Count()*/
int j = counta + counte + counti + counto + countu + countA + countE + countI + countO + countU;
foreach (char v in EnterString)
{
if (v == ch1) { counta++; j++; }
else if (v == ch2) { counte++; j++; }
else if (v == ch3) { counti++; j++; }
else if (v == ch4) { counto++; j++; }
else if (v == ch5) { countu++; j++; }
}
foreach (char v in EnterString)
{
if (v == ch6) { countA++; j++; }
else if (v == ch7) { countE++; j++; }
else if (v == ch8) { countI++; j++; }
else if (v == ch9) { countO++; j++; }
else if (v == ch10) { countU++; j++; }
}
Label1.Text = j.ToString();
}
You have this in your code:
const string vowels = "aeiou";
return value.Count(chr => vowels.Contains(char.ToLower(chr)));
That works, at least if your culture is US. So no idea why you commented it out in favor of the current monstrosity.
On a Turkish locale it will fail because the lower case of I is not i but ı (undotted). So if you define vowels as aeiouAEIOU you should use ToLowerInvariant.
But if you want to include other vowels (like Ä) I have no idea how to do that except by listing all the characters.
Full implementation:
int CountVowels(string value)
{
const string vowels = "aeiou";
return value.Count(chr => vowels.Contains(char.ToLowerInvariant(chr)));
}
Looks like you got the good code part from:
Counting vowels using switch
int vowel = 0;
Console.WriteLine("Please enter the string:");
string main = Console.ReadLine();
for (int j = 0; j < main.Length ; j++)
{
if (main[j] == 'a' || main[j] == 'A' || main[j] == 'e' || main[j] == 'E' || main[j] == 'i' || main[j] == 'I' || main[j] == 'o' || main[j] == 'O' || main[j] == 'u' || main[j] == 'U')
{
vowel++;
}
}
Console.WriteLine("Number of vowels in sentence is :"+ vowel);
Console.ReadLine();
Console.WriteLine("Please input your text: ")
mystring = Console.ReadLine
For i = 1 To mystring.Length
Console.Write((mystring(i - 1)) & ",")
isItAVowel = False
If mystring(i - 1) = "a" Or mystring(i - 1) = "A" Then isItAVowel = True
If mystring(i - 1) = "e" Or mystring(i - 1) = "E" Then isItAVowel = True
If mystring(i - 1) = "i" Or mystring(i - 1) = "I" Then isItAVowel = True
If mystring(i - 1) = "o" Or mystring(i - 1) = "O" Then isItAVowel = True
If mystring(i - 1) = "u" Or mystring(i - 1) = "U" Then isItAVowel = True
If isItAVowel Then
This could help good luck
private void button1_Click(object sender, EventArgs e)
{
string EnterString;
EnterString = textBox1.Text;
const string vowels = "aeiou";
label1.Text = EnterString.Count(myString => vowels.Contains(char.ToLowerInvariant(myString))).ToString();
}
public static void Main()
{
char[] sentence = new char[100];
int i, vowels = 0, consonants = 0, special = 0, n;
Console.WriteLine("Enter the Length of the sentence \n");
n = int.Parse(Console.ReadLine());
for (i = 0; i < n; i++)
{
sentence[i] = Convert.ToChar(Console.Read());
}
for (i = 0; sentence[i] != '\0'; i++)
{
if ((sentence[i] == 'a' || sentence[i] == 'e' || sentence[i] ==
'i' || sentence[i] == 'o' || sentence[i] == 'u') ||
(sentence[i] == 'A' || sentence[i] == 'E' || sentence[i] ==
'I' || sentence[i] == 'O' || sentence[i] == 'U'))
{
vowels = vowels + 1;
}
else
{
consonants = consonants + 1;
}
if (sentence[i] == 't' || sentence[i] == '\0' || sentence[i] == ' ')
{
special = special + 1;
}
}
consonants = consonants - special;
Console.WriteLine("No. of vowels {0}", vowels);
Console.WriteLine("No. of consonants {0}", consonants);
Console.ReadLine();
Console.ReadLine();
}
#include <bits/stdc++.h>
using namespace std;
int main()
{
int t;
cin >> t;
set<char> vowels = {'A', 'E', 'I', 'O', 'U', 'a', 'e', 'i', 'o', 'u'};
while(t--)
{
string s;
int c = 0;
cin >> s;
for(char i : s)
if(vowels.find(i) != vowels.end())
++c;
cout << c << "\n";
}
return 0;
}
string vowelList = ("aeiouAEIOU");
int i = 0;
int j = 0;
int vowelCount = 0;
string main = textBox1.Text; /or Console.ReadLine();
while (j < main.Length)
{
while (i < vowelList.Length)
{
if (main[j] == vowelList[i])
{
vowelCount++;
}
i++;
}
j = j + 1;
i = 0;
}
label1.Text = ("Number of vowels in sentence is :" + vowelCount); /or Console.Writeline ("Number of vowels in sentence is: " + vowelCount
count = 0
string=input("Enter string:")
vowels = set("aeiouAEIOU")
for letter in string:
if letter in vowels:
count += 1
print("Count of the vowels is:")
print(count)

Bracket Checker Using Stack and Queue in C#

I am having an issue solving Bracket Checker .
i cant seem to solve the problem if user input this sequence of bracket then my program must print its not a right sequence
Input:
({}[)
Output:
Not a Right Sequence
My code is below
Stack s = new Stack();
Queue q = new Queue();
bool isok = true;
string FinalData = "0";
Console.WriteLine("Enter Brackets");
string data = Console.ReadLine();
for (int i = 0; i < data.Length; i++)
{
if (data.Substring(i, 1) == "{"
|| data.Substring(i, 1) == "["
|| data.Substring(i, 1) == "("
)
{
s.Push(data.Substring(i, 1));
}
else
{
q.Enqueue(data.Substring(i, 1));
}
}
while (s.Count > 0 && q.Count > 0)
{
FinalData = (String)s.Pop();
string value = (String)q.Dequeue();
if (FinalData == value)
{
isok = false;
break;
}
}
if (isok)
Console.WriteLine(data + " is a Right Sequence.");
else
Console.WriteLine(data + " is Not a Right Sequence.");
Console.ReadLine();
}
I'l give you a few hints and the basic idea:
you don't need the Queue, just a Stack<char>.
read the input, for each char:
if the char is an open brace, push it
if the char is a close brace, pop the stack and compare.
discard other chars
boolean isCorrect;
public boolean checkBraces(String braces)
{
Stack<Character>stack = new Stack<Character>();
int openBCount = 0;
int closeBCount = 0;
for(int c = 0; c<=braces.length()-1; c++)
{
//check for open braces push to stack
if(braces.charAt(c)=='{' || braces.charAt(c)=='[' ||braces.charAt(c)=='(')
{
stack.push(braces.charAt(c));
openBCount++;
} ////check for close braces. pop the open braces
//compare it to the closed braces using the the
//method ValidatePerBraces
//therefor checking for CORRECTNEES of how the braces //are closed
else if(braces.charAt(c)=='}' || braces.charAt(c)==']' || braces.charAt(c)==')')
{
closeBCount++;
if(!ValidatePerBraces(stack.pop(), braces.charAt(c)))
{
isCorrect = false; //return false in case where they dont match
return isCorrect;
}
}
//for braces to be complete, open and close braces
//should be even, if they are not even then it is
//for sure wrong at least for the specification.
if(c>=braces.length()-1)
{
if(openBCount != closeBCount)
{
isCorrect = false;
return isCorrect;
}
}
}
isCorrect = true; // true if they all match
return isCorrect;
}
// returns true if validated
public boolean ValidatePerBraces(char a, char b)
{
return a == '(' && b== ')' || a == '[' && b == ']' || a == '{' && b== '}' ;
}
public bool CheckBraces(string data)
{
Stack<char> stack = new Stack<char>();
foreach(char c in data){
switch(c){
case '(':
case '[':
case '{':
stack.Push(c);
break;
case ')':
case ']':
case '}':
if(!CheckMatch(stack.Pop(),c)){
return false;
}
break;
}
}
return true;
}
private bool CheckMatch(char a, char b){
return a=='(' && b==')' ||
a=='[' && b==']' ||
a=='{' && b=='}';
}
Thannks Guys I have Solved The Problem Using stack And Queue Both AT the Same time. Here's the code
Stack s = new Stack();
Queue q = new Queue();
bool isRight = true;
char OpeningBracket = ' ';
char closingBracket = ' ';
Console.WriteLine("Enter Brackets");
string data = Console.ReadLine();
char[] character = data.ToCharArray();
for (int i = 0; i < character.Length; i++)
{
if (character[i] == '(' || character[i] == '{' ||
character[i] == '[')
{
s.Push(character[i]);
}
else
q.Enqueue(character[i]);
}
if (s.Count == 0 || q.Count == 0)
isRight = false;
while (s.Count > 0 && q.Count > 0)
{
OpeningBracket = (char)s.Pop();
closingBracket = (char)q.Dequeue();
if ((OpeningBracket == '(' && closingBracket != ')')
|| (OpeningBracket == '[' && closingBracket != ']')
|| (OpeningBracket == '{' && closingBracket != '}')
)
{
isRight = false;
}
}
if (isRight)
Console.WriteLine(data + " is a Right Sequence.");
else
Console.WriteLine(data + " is Not Right Sequence.");
Console.ReadLine();
}
private static bool IsCorrectBracketSeq(string sequence)
{
var stack = new Stack<char>();
foreach (var sign in sequence)
{
if(sign == '(' || sign == '[' || sign == '{')
stack.Push(sign);
else if (sign == ')' || sign == ']' || sign == '}')
{
if (!stack.Any())
return false;
var topSing = stack.Pop();
var str = $"{topSing}{sign}";
if (str != "[]" && str != "{}" && str != "()")
return false;
}
}
return stack.Count == 0;
}
static bool IsBracesValidator(string input)
{
bool IsValidBraces = true;
char[] chrArray = input.ToCharArray();
List<Char> foundOpenParanthesis = new List<char>();
List<Char> foundClosedParanthesis = new List<char>();
char[] chrOpenParanthesis = { '{', '[', '(', '<' };
char[] chrClosedParanthesis = { '}', ']', ')', '>' };
for (int i = 0; i <= chrArray.Length - 1; i++)
{
if (chrOpenParanthesis.Contains(chrArray[i]))
{
foundOpenParanthesis.Add(chrArray[i]);
}
if (chrClosedParanthesis.Contains(chrArray[i]))
{
foundClosedParanthesis.Add(chrArray[i]);
}
}
if (foundOpenParanthesis.Count == foundClosedParanthesis.Count)
{
for(int i=0;i< foundOpenParanthesis.Count;i++)
{
char chr = foundOpenParanthesis[i];
switch (chr)
{
case '[': chr = ']'; break;
case '<': chr = '>'; break;
case '(': chr = ')'; break;
case '{': chr = '}'; break;
}
if (!chr.Equals(foundClosedParanthesis[foundClosedParanthesis.Count - i-1]))
{
IsValidBraces = false;
break;
}
}
} else
{
IsValidBraces = false;
}
return IsValidBraces;
}

How to escape JSON string?

Are there any classes/functions available to be used for easy JSON escaping? I'd rather not have to write my own.
I use System.Web.HttpUtility.JavaScriptStringEncode
string quoted = HttpUtility.JavaScriptStringEncode(input);
For those using the very popular Json.Net project from Newtonsoft the task is trivial:
using Newtonsoft.Json;
....
var s = JsonConvert.ToString(#"a\b");
Console.WriteLine(s);
....
This code prints:
"a\\b"
That is, the resulting string value contains the quotes as well as the escaped backslash.
Building on the answer by Dejan, what you can do is import System.Web.Helpers .NET Framework assembly, then use the following function:
static string EscapeForJson(string s) {
string quoted = System.Web.Helpers.Json.Encode(s);
return quoted.Substring(1, quoted.Length - 2);
}
The Substring call is required, since Encode automatically surrounds strings with double quotes.
Yep, just add the following function to your Utils class or something:
public static string cleanForJSON(string s)
{
if (s == null || s.Length == 0) {
return "";
}
char c = '\0';
int i;
int len = s.Length;
StringBuilder sb = new StringBuilder(len + 4);
String t;
for (i = 0; i < len; i += 1) {
c = s[i];
switch (c) {
case '\\':
case '"':
sb.Append('\\');
sb.Append(c);
break;
case '/':
sb.Append('\\');
sb.Append(c);
break;
case '\b':
sb.Append("\\b");
break;
case '\t':
sb.Append("\\t");
break;
case '\n':
sb.Append("\\n");
break;
case '\f':
sb.Append("\\f");
break;
case '\r':
sb.Append("\\r");
break;
default:
if (c < ' ') {
t = "000" + String.Format("X", c);
sb.Append("\\u" + t.Substring(t.Length - 4));
} else {
sb.Append(c);
}
break;
}
}
return sb.ToString();
}
I have used following code to escape the string value for json.
You need to add your '"' to the output of the following code:
public static string EscapeStringValue(string value)
{
const char BACK_SLASH = '\\';
const char SLASH = '/';
const char DBL_QUOTE = '"';
var output = new StringBuilder(value.Length);
foreach (char c in value)
{
switch (c)
{
case SLASH:
output.AppendFormat("{0}{1}", BACK_SLASH, SLASH);
break;
case BACK_SLASH:
output.AppendFormat("{0}{0}", BACK_SLASH);
break;
case DBL_QUOTE:
output.AppendFormat("{0}{1}",BACK_SLASH,DBL_QUOTE);
break;
default:
output.Append(c);
break;
}
}
return output.ToString();
}
In .Net Core 3+ and .Net 5+:
string escapedJsonString = JsonEncodedText.Encode(jsonString);
The methods offered here are faulty.
Why venture that far when you could just use System.Web.HttpUtility.JavaScriptEncode ?
If you're on a lower framework, you can just copy paste it from mono
Courtesy of the mono-project #
https://github.com/mono/mono/blob/master/mcs/class/System.Web/System.Web/HttpUtility.cs
public static string JavaScriptStringEncode(string value, bool addDoubleQuotes)
{
if (string.IsNullOrEmpty(value))
return addDoubleQuotes ? "\"\"" : string.Empty;
int len = value.Length;
bool needEncode = false;
char c;
for (int i = 0; i < len; i++)
{
c = value[i];
if (c >= 0 && c <= 31 || c == 34 || c == 39 || c == 60 || c == 62 || c == 92)
{
needEncode = true;
break;
}
}
if (!needEncode)
return addDoubleQuotes ? "\"" + value + "\"" : value;
var sb = new System.Text.StringBuilder();
if (addDoubleQuotes)
sb.Append('"');
for (int i = 0; i < len; i++)
{
c = value[i];
if (c >= 0 && c <= 7 || c == 11 || c >= 14 && c <= 31 || c == 39 || c == 60 || c == 62)
sb.AppendFormat("\\u{0:x4}", (int)c);
else switch ((int)c)
{
case 8:
sb.Append("\\b");
break;
case 9:
sb.Append("\\t");
break;
case 10:
sb.Append("\\n");
break;
case 12:
sb.Append("\\f");
break;
case 13:
sb.Append("\\r");
break;
case 34:
sb.Append("\\\"");
break;
case 92:
sb.Append("\\\\");
break;
default:
sb.Append(c);
break;
}
}
if (addDoubleQuotes)
sb.Append('"');
return sb.ToString();
}
This can be compacted into
// https://github.com/mono/mono/blob/master/mcs/class/System.Json/System.Json/JsonValue.cs
public class SimpleJSON
{
private static bool NeedEscape(string src, int i)
{
char c = src[i];
return c < 32 || c == '"' || c == '\\'
// Broken lead surrogate
|| (c >= '\uD800' && c <= '\uDBFF' &&
(i == src.Length - 1 || src[i + 1] < '\uDC00' || src[i + 1] > '\uDFFF'))
// Broken tail surrogate
|| (c >= '\uDC00' && c <= '\uDFFF' &&
(i == 0 || src[i - 1] < '\uD800' || src[i - 1] > '\uDBFF'))
// To produce valid JavaScript
|| c == '\u2028' || c == '\u2029'
// Escape "</" for <script> tags
|| (c == '/' && i > 0 && src[i - 1] == '<');
}
public static string EscapeString(string src)
{
System.Text.StringBuilder sb = new System.Text.StringBuilder();
int start = 0;
for (int i = 0; i < src.Length; i++)
if (NeedEscape(src, i))
{
sb.Append(src, start, i - start);
switch (src[i])
{
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;
case '\"': sb.Append("\\\""); break;
case '\\': sb.Append("\\\\"); break;
case '/': sb.Append("\\/"); break;
default:
sb.Append("\\u");
sb.Append(((int)src[i]).ToString("x04"));
break;
}
start = i + 1;
}
sb.Append(src, start, src.Length - start);
return sb.ToString();
}
}
I ran speed tests on some of these answers for a long string and a short string. Clive Paterson's code won by a good bit, presumably because the others are taking into account serialization options. Here are my results:
Apple Banana
System.Web.HttpUtility.JavaScriptStringEncode: 140ms
System.Web.Helpers.Json.Encode: 326ms
Newtonsoft.Json.JsonConvert.ToString: 230ms
Clive Paterson: 108ms
\\some\long\path\with\lots\of\things\to\escape\some\long\path\t\with\lots\of\n\things\to\escape\some\long\path\with\lots\of\"things\to\escape\some\long\path\with\lots"\of\things\to\escape
System.Web.HttpUtility.JavaScriptStringEncode: 2849ms
System.Web.Helpers.Json.Encode: 3300ms
Newtonsoft.Json.JsonConvert.ToString: 2827ms
Clive Paterson: 1173ms
And here is the test code:
public static void Main(string[] args)
{
var testStr1 = "Apple Banana";
var testStr2 = #"\\some\long\path\with\lots\of\things\to\escape\some\long\path\t\with\lots\of\n\things\to\escape\some\long\path\with\lots\of\""things\to\escape\some\long\path\with\lots""\of\things\to\escape";
foreach (var testStr in new[] { testStr1, testStr2 })
{
var results = new Dictionary<string,List<long>>();
for (var n = 0; n < 10; n++)
{
var count = 1000 * 1000;
var sw = Stopwatch.StartNew();
for (var i = 0; i < count; i++)
{
var s = System.Web.HttpUtility.JavaScriptStringEncode(testStr);
}
var t = sw.ElapsedMilliseconds;
results.GetOrCreate("System.Web.HttpUtility.JavaScriptStringEncode").Add(t);
sw = Stopwatch.StartNew();
for (var i = 0; i < count; i++)
{
var s = System.Web.Helpers.Json.Encode(testStr);
}
t = sw.ElapsedMilliseconds;
results.GetOrCreate("System.Web.Helpers.Json.Encode").Add(t);
sw = Stopwatch.StartNew();
for (var i = 0; i < count; i++)
{
var s = Newtonsoft.Json.JsonConvert.ToString(testStr);
}
t = sw.ElapsedMilliseconds;
results.GetOrCreate("Newtonsoft.Json.JsonConvert.ToString").Add(t);
sw = Stopwatch.StartNew();
for (var i = 0; i < count; i++)
{
var s = cleanForJSON(testStr);
}
t = sw.ElapsedMilliseconds;
results.GetOrCreate("Clive Paterson").Add(t);
}
Console.WriteLine(testStr);
foreach (var result in results)
{
Console.WriteLine(result.Key + ": " + Math.Round(result.Value.Skip(1).Average()) + "ms");
}
Console.WriteLine();
}
Console.ReadLine();
}
I would also recommend using the JSON.NET library mentioned, but if you have to escape unicode characters (e.g. \uXXXX format) in the resulting JSON string, you may have to do it yourself. Take a look at Converting Unicode strings to escaped ascii string for an example.
I nice one-liner, used JsonConvert as others have but added substring to remove the added quotes and backslash.
var escapedJsonString = JsonConvert.ToString(JsonString).Substring(1, JsonString.Length - 2);
What about System.Web.Helpers.Json.Encode(...) (see http://msdn.microsoft.com/en-us/library/system.web.helpers.json.encode(v=vs.111).aspx)?
String.Format("X", c);
That just outputs: X
Try this instead:
string t = ((int)c).ToString("X");
sb.Append("\\u" + t.PadLeft(4, '0'));
There's a Json library at Codeplex
I chose to use System.Web.Script.Serialization.JavaScriptSerializer.
I have a small static helper class defined as follows:
internal static partial class Serialization
{
static JavaScriptSerializer serializer;
static Serialization()
{
serializer = new JavaScriptSerializer();
serializer.MaxJsonLength = Int32.MaxValue;
}
public static string ToJSON<T>(T obj)
{
return serializer.Serialize(obj);
}
public static T FromJSON<T>(string data)
{
if (Common.IsEmpty(data))
return default(T);
else
return serializer.Deserialize<T>(data);
}
}
To serialize anything I just call Serialization.ToJSON(itemToSerialize)
To deserialize I just call Serialization.FromJSON<T>(jsonValueOfTypeT)

Categories