I am doing my homework and I have to do a program that extends simple letters from a file, like E and F, to continuous productions, given also in the folder, such as E+T E-F etc. Anyway the code shown below gives me an argument out of range exception. I crafted the same code in java and all works fine. I don't know why in C# it gives me this exception. Please give me some advice!!
I forgot to put the file that I'm reading from:
EFT
a+()
E
E+T|E-T|T
T*F|T/F|F
a|(E)
public void generare(){
String N = null;
String T = null;
String S = null;
String[] P = null;
TextReader tr = new StreamReader("dateIntrare.txt");
try
{
N = tr.ReadLine();
T = tr.ReadLine();
S = tr.ReadLine();
P = new String[N.Length];
for (int i = 0; i < N.Length; i++)
{
P[i] = tr.ReadLine();
}
tr.Close();
Console.WriteLine("Neterminale: N = " + N);
Console.WriteLine("Terminale: T = " + T);
Console.WriteLine("Productii ");
for (int i = 0; i < P.Length; i++)
Console.WriteLine("\t" + P[i]);
Console.WriteLine("Start: S = " + S);
Boolean gata = false;
String iesire = S.Substring(0, S.Length);
Console.WriteLine("\nRezultat");
Console.Write("\t");
while ((gata == false) && (iesire.Length < 50))
{
Console.Write(iesire);
Boolean ok = false;
for (int i = iesire.Length - 1; i >= 0 && ok == false; i--)
{
for (int j = 0; j < N.Length && ok == false; j++)
if (N[j] == iesire[i])
{
String s1 = iesire.Substring(0, i);
String s2 = iesire.Substring(i + 1, iesire.Length); // HERE IS THE EXCEPTION TAKING PLACE
String inlocuire = P[N.IndexOf(iesire[i])];
String[] optiuni = null;
String[] st = inlocuire.Split('|');
int k = 0;
foreach (String now in st)
{
k++;
}
optiuni = new String[k];
st = inlocuire.Split('|');
k = 0;
foreach (string next in st)
{
optiuni[k++] = next;
}
Random rand = new Random();
int randNr = rand.Next(optiuni.Length);
String inlocuireRandom = optiuni[randNr];
iesire = s1 + inlocuireRandom + s2;
ok = true;
}
}
if (ok == false)
{
gata = true;
}
else
{
if (iesire.Length < 50)
Console.Write(" => ");
}
}
}
catch (FileNotFoundException)
{
Console.WriteLine("Eroare, fisierul nu exista!");
}
Console.WriteLine();
}
But why in java works and here not? I'm confused
When in doubt, read the documentation. In Java, the 2-parameter overload of substring takes a start index and an end index. In .NET, the second parameter is the number of characters to take, not an end index.
So you probably want
String s2 = iesire.Substring(i + 1, iesire.Length - i - 1);
Or to be simpler about it, just use the 1-parameter version, which takes all the characters from the specified index onwards:
String s2 = iesire.Substring(i + 1);
(I'd use that in Java too...)
Fundamentally though, it's worth taking a step back and working out why you couldn't work this out for yourself... even if you missed it before:
Look at the line that threw the exception in your code
Look at which method actually threw the exception (String.Substring in this case)
Look at the exception message carefully (it's a really good hint!) and also any nested exceptins
Read the documentation for the relevant method carefully, especially the sections describing the parameters and exceptions
This is a common mistake while porting codes from Java to c#.
Substring in Java takes start & end parameters but in c# they are start and length
Related
I'm trying to find a long string in another string. For this I've been using G[i].Contains(P[arr]) but for some reason the code just skips that condition. In my case : G[I] is 1000 character long and P[arr] is 475. When I debug I can see strings are not trimmed and also I have verified that P[ARR] is part of G[I] in Notepad++ so it should definitely satisfy a condition.
for (int arr = 0; arr < P.Length; arr++)
{
for (int i = a; i < G.Length; i++)
{
if (G[i].Contains(P[arr]))
{
if (!(b == 0))
{
a = i + 1;
continue;
}
primary_1 = (a == 0) ? G[i].IndexOf(P[arr]) : primary;
++count;
a = i + 1;
Console.WriteLine("Counter: " + i);
break;
}
}
}
I'm having trouble in this program, which is written to convert Unicode characters to 32-bit format; in the index section that started from zero.
Does the index need to start from zero?
Why can not it start from number 1? Please explain this part well.
int a;
textBox2.Text = " ";
for (int i = 0; i < textBox1.Text.Length; i++)
{
a = Char.ConvertToUtf32(textBox1.Text.Substring(i, 1), 0);
textBox2.Text = a.ToString();
if (textBox1.Text == " ")
{
textBox2.Text = " " ;
}
}
A string is similar to an array, and indexes in c# start from 0 for any array type. As for your code's efficiency, you can also move the if check inside the loop, to outside, as it is independent of any index. See the sample code below:
/// <param name="source"> equivalent to TextBox1.Text in original post</param>
public static int[] ConvertToUtf32(string source)
{
int[] result = new int[source.Length]; //equivalent to all the chars displayed in TextBox2.Text in original post
if (source.Equals(" "))
{
result[0] = ' ';
}
else
{
for (int i = 0; i < source.Length; i++)
{
result[i] = Char.ConvertToUtf32(source.Substring(i, 1), 0);
}
}
return result;
}
I'm trying to make a look and say sequence ant my code so far only works as it should when I have the 'realCounter' set to 2 or less and don't understand why. Thanks for any help! Here is my main :
string number = "1";
string[] tempStore = new string[2];
int realCounter = 0;
while (realCounter < 2)
{
int counter = 1;
for (int i = 0; i < number.Length; i++)
{
try
{
if (number[i] == number[i + 1])
{
counter++;
}
}
catch
{
tempStore[0] = number[i].ToString();
number = counter.ToString();
number = number + tempStore[0];
}
}
realCounter++;
}
Console.WriteLine(number);
Console.ReadLine();
I've been changing the line with the while loop from realCounter < 2 to realCounter < 3 and the program doesn't perform as it should
It is because you are specifically checking to ensure realCounter < 2 as a condition of your while loop
try
{
if (number[i] == number[i + 1])
{
counter++;
}
}
catch
{
tempStore[0] = number[i].ToString();
number = counter.ToString();
number = number + tempStore[0];
}
You are only updating your number variable when you encounter an exception. You only encounter an exception when number[i + 1] hits an IndexOutOfBounds exception. So you're only updating number with the LAST sequence it encounters, and you're dropping all the rest.
I'm facing a problem I don't even know what to search in Google/Stack Overflow.
So comment if you feel the need for further explanation, questions.
Basically I want to intersect two lists and return the similarity with the preserved order of the original first string value.
Example:
I have two strings, that I convert to a CharArray.
I want to Intersect these two arrays and return the values that are similar, including/with the order of the first string (s1).
As you can see the first string contains E15 (in that specific order), and so does the seconds one.
So these two strings will return : { 'E', '1', '5' }
string s1 = "E15QD(A)";
string s2 = "NHE15H";
The problem I am facing is that if i replace "s2" with:
string s2 = "NQE18H" // Will return {'Q', 'E', '1' }
My operation will return : {'Q', 'E', '1' }
The result should be : {'E', '1' } because Q don't follow the letter 1
Currently my operation is not the greatest effort, because i don't know which methods to use in .NET to be able to do this.
Current code:
List<char> cA1 = s1.ToList();
List<char> cA2 = s2.ToList();
var result = cA1.Where(x => cA2.Contains(x)).ToList();
Feel free to help me out, pointers in the right direction is acceptable as well as a full solution.
This is a "longest common substring" problem.
You can use this extension to get all substrings lazily:
public static class StringExtensions
{
public static IEnumerable<string> GetSubstrings(this string str)
{
if (string.IsNullOrEmpty(str))
throw new ArgumentException("str must not be null or empty", "str");
for (int c = 0; c < str.Length - 1; c++)
{
for (int cc = 1; c + cc <= str.Length; cc++)
{
yield return str.Substring(c, cc);
}
}
}
}
Then it's easy and readable with this LINQ query:
string longestIntersection = "E15QD(A)".GetSubstrings()
.Intersect("NQE18H".GetSubstrings())
.OrderByDescending(s => s.Length)
.FirstOrDefault(); // E1
Enumerable.Intersect is also quite efficient since it's using a set. One note: if one both strings is larger than the other then it's more efficient(in terms of memory) to use it first:
longString.GetSubstrings().Intersect(shortString.GetSubstrings())
I think this should do it:
string similar = null;
for (int i = 0; i < s1.Length; i++)
{
string s = s1.Substring(0, i + 1);
if (s2.Contains(s))
{
similar = s;
}
}
char[] result = similar.ToCharArray();
#TimSchmelter provided the link to this answer in the comments of the original post.
public int LongestCommonSubstring(string str1, string str2, out string sequence)
{
sequence = string.Empty;
if (String.IsNullOrEmpty(str1) || String.IsNullOrEmpty(str2))
return 0;
int[,] num = new int[str1.Length, str2.Length];
int maxlen = 0;
int lastSubsBegin = 0;
StringBuilder sequenceBuilder = new StringBuilder();
for (int i = 0; i < str1.Length; i++)
{
for (int j = 0; j < str2.Length; j++)
{
if (str1[i] != str2[j])
num[i, j] = 0;
else
{
if ((i == 0) || (j == 0))
num[i, j] = 1;
else
num[i, j] = 1 + num[i - 1, j - 1];
if (num[i, j] > maxlen)
{
maxlen = num[i, j];
int thisSubsBegin = i - num[i, j] + 1;
if (lastSubsBegin == thisSubsBegin)
{//if the current LCS is the same as the last time this block ran
sequenceBuilder.Append(str1[i]);
}
else //this block resets the string builder if a different LCS is found
{
lastSubsBegin = thisSubsBegin;
sequenceBuilder.Length = 0; //clear it
sequenceBuilder.Append(str1.Substring(lastSubsBegin, (i + 1) - lastSubsBegin));
}
}
}
}
}
sequence = sequenceBuilder.ToString();
return maxlen;
}
I have made this code to get from 2a3b to aabbb. This also has to apply when no numbers are given. Like aa2b => aabb.
The program is fully working but my problem is, it takes in alot of space. I think it is my split but my array will be like this if the input is 2a2b:
2
NULL
NULL
a
2
NULL
NULL
b
Does someone know what i'm doing wrong? Is it my split?
static void Main(string[] args)
{
string test = "";
int intNumber = 1;
string value = "2a2b";
string[] array = new string[20];
int count = 1;
array = Regex.Split(value, "(\\d{0,2})");
while (count < array.Length)
{
int num;
if (array[count] != "")
{
bool isNumeric = int.TryParse(array[count], out num);
if (!isNumeric)
{
test = test + string.fill(array[count], intNumber);
test = test + array[count];
Console.WriteLine(test);
intNumber = 1;
}
else
{
intNumber = num;
}
}
count++;
}
Console.WriteLine("woord:" + test);
Console.ReadLine();
How about using a simple Regex.Replace?
string input = "2a3bcccc";
string output = Regex.Replace(
input,
#"(\d+)(\w)",
m => new String(m.Groups[2].Value[0],int.Parse(m.Groups[1].Value)));
result : aabbbcccc
A simpler way to resolve your problem is to get rid of regex, the array creation would be like:
char[] array = value.ToArray();
The code, with the minor corrections due to the array and some improvements being a char array (intead of a string array):
static void Main(string[] args)
{
string test = "";
int intNumber = 1;
string value = "2a2b";
foreach (char c in value.ToArray())
{
int num;
bool isNumeric = int.TryParse(c.ToString(), out num);
if (!isNumeric)
{
test = test + new string(c, intNumber);
Console.WriteLine(test);
intNumber = 1;
}
else
{
intNumber = num;
}
}
Console.WriteLine("woord:" + test);
Console.ReadLine();
}
Quick test program works like a charm without using a regex.
const string value = "aa2b";
var result = "";
for (var i = 0; i < value.Length; i++)
{
int num;
if (Int32.TryParse(value.Substring(i, 1), out num))
{
for (var j = 0; j < num; j++)
{
result += value.Substring(i + 1, 1);
}
i++;
}
else
{
result += value.Substring(i, 1);
}
}
textBox1.AppendText("woord:" + result);
I generally try to avoid Regex, unless there is a complex pattern I need to verify.
Here is my solution to your problem:
string k = Console.ReadLine();
string t = "";
int count = 0, next;
for (int i = 0; i < k.Length; i++)
{
while (int.TryParse(k[i].ToString(), out next)) // Find the count of the next letter
{
count = count * 10 + next; // If count had a 2, and the next character is 3 (means we need to calculate 23), simply multiply the previous count by 10, and add the new digit
i++; // Move to the next character
}
t += new String(k[i], count > 0 ? count : 1); // Add the new sequence of letters to our string
count = 0; // Clear the current count
}
Console.WriteLine(t);
You can optimize the above, by using the StringBuilder class, but I think it's enough to understand the general solution first, rather than trying to find optimizations.