Related
I'm trying to convert a string (ex. "0.20055") to its equivalent double.
I already know that for some reason that string does not contain a valid double, but I don't understand why.
I really need to be able to convert this string to a double... Could anyone explain me why it's not a valid double? And how to fix this?
Here is some of my code:
double[] values_in_double = null;
string[] values_in_string = lines[j].Split(',');
for(int x=0; x < numCols; x++)
{
double val;
bool r = double.TryParse(values_in_string[x],out val);
if (!r)
return;
values_in_double[x] = Convert.ToDouble(values_in_string[x]);
}
As you can see I have a string[] of lines, in which a line is like:
0.20055,0.37951,0.39641,2.0472,32.351,0.38825,0.24976,1.3305,1.1389,0.50494
and I split them. But then I need to convert each one to a double value.
The main changes I would make to your code are to
remove the return statement since that will exit our method prematurely
use a List<double> to store your doubles (you don't have to declare a size ahead of time, which is nice because we don't know for sure how many items in the string will successfully convert to a double)
to use the val variable when adding it to the List, since double.TryParse has assigned the value to this variable already.
I also added a check to ensure that the variable numRows is not larger than the string array, because that would cause an exception in our loop:
// Mock values read from file
var input = new StringBuilder();
input.Append("0.20055,0.37951,0.39641,2.0472,32.351,0.38825,0.24976,1.3305,");
input.Append("1.1389,0.50494,0.24976,0.6598,0.1666,0.24976,497.42,0.73378,");
input.Append("2.6349,0.24976,0.14942,43.37,1.2479,0.21402,0.11998,0.47706,");
input.Append("0.50494,0.60411,1.4582,1.7615,5.9443,0.11788,593.27,0.50591,");
input.Append("0.12804,0.66295,0.14942,94.14,3.8772,0.56393,0.21402,1.741,");
input.Append("1.5225,49.394,0.1853,0.11085,2.042,0.051402,0.12804,114.42,");
input.Append("71.05,1.0097,348690,0.12196,0.39718,0.87804,0.37854,0.25792,");
input.Append("2.2437,2.248,0.001924,8.416,5.1372,82.658,4.4158,7.4277");
string[] values_in_string = inputString.ToString().Split(',');
// Declare values_in_double as a List so we don't have to worry about sizing
List<double> values_in_double = new List<double>();
// We will get errors if numCols is larger than our string array, so to be safe,
// set a variable that is the smallest of either numCols or our string array length
var numIterations = Math.Min(numCols, values_in_string.Length);
for (int x = 0; x < numIterations; x++)
{
double val;
// If TryParse succeeds, 'val' will contain the double value, so add it to our List
if (double.TryParse(values_in_string[x], NumberStyles.Any,
System.Globalization.CultureInfo.InvariantCulture, out val))
{
values_in_double.Add(val);
}
}
There is also a much shorter way to write this code. The line basically says: For each item in values_in_string, Where double.TryParse returns true, Select val (the item as a value) And convert all the val items into a List:
string[] values_in_string = inputString.ToString().Split(',');
double val = 0;
List<double> values_in_double = values_in_string
.Where(value => double.TryParse(value, NumberStyles.Any,
System.Globalization.CultureInfo.InvariantCulture, out val))
.Select(v => val)
.ToList();
Try this
Double.TryParse(values_in_string[x], NumberStyles.Any, CultureInfo.InvariantCulture, out val);
change
double[] values_in_double = null;
string[] values_in_string = lines[j].Split(',');
to
string[] values_in_string = lines[j].Split(',');
int arraySize = values_in_string.Length;
double[] values_in_double = new double[arraySize];
as you use
double[] values_in_double = null;
and value cannot be assign to null array
Try changing the line :
double[] values_in_double = null;
into
double[] values_in_double = new double[numCols];
Because otherwise the code you provided wouldn't run since the array is not defined (cannot be null).
The problem you have with that is the culture definition on your PC or server, if the delimitator are ',' the sistem interpret '.' as a char.
Use like this:
double vValue;
string[] vValuesString = vLines[j].Split(',');
double[] vValuesDouble = new double[vValuesString.Length];
for (int x = 0; x < vValuesString.Length; x++)
if (double.TryParse(vValuesString[x], System.Globalization.NumberStyles.Any, System.Globalization.CultureInfo.InvariantCulture, out vValue))
return; 'or use' continue;'or use' vValuesDouble[x] = 0;
else vValuesDouble[x] = vValue;
NOTES:
Instance your 'double[] vValuesDouble = new double[vValuesString.Length];', you can't asing a value to a null array.
When you use a TryParce the out var return with the result of convert string to a double, you don't need to re-convert it again.
Never declare variable in a loop, it get declare and instace every run of loop.
TryParce return a bool value that indicates the result of convert you don't need declare and instance a var, just use it in a if.
Use some protocol to define your variable's name.
Try to resume your code the most posible you can.
I put the entire using System.Globalization, but you can declare the using on top or define your System.Globalization for your entire aplication.
And last, sorry for my english, is not my first languaje.
Best.
This question already has answers here:
C# multidimensional arrays iteration
(5 answers)
Closed 2 years ago.
I am trying to print out my array of numbers that I have assigned to a particular array. My algorithm for choosing numbers consists of choosing a random number that is not a duplicate and storing it inside the array.
Pretty simple really, but I have no idea as to why it is printing out this error.
int[] ticket1 = new int[4];
for (int i = 0; i < 4; i++)
{
int temp = rand.Next(43);
while (ticket1.Contains(temp))
{
temp = rand.Next(43);
}
ticket1[i] = temp;
}
Console.WriteLine("{0}{1}", item.PadRight(20), ticket1.ToString());//ticket1 produces System.Int32[] instead of 4 numbers.
//I have changed this line to:
//Console.WriteLine("{0}{1}", item.PadRight(20), string.Join(",", ticket1));
//And it still doesn't work. the error remains. (System.Int32[])
My question is, how can I print out my 4 numbers (beside each other) in string format.
//EDIT: I've found my problem. I am putting my ticket1 inside a foreach loop, it's somehow not reaching out to the array values and it therefore prints out System.Int32[] instead.
All fixed.
If you call ToString() on an array like that, you simply get the full name of the type of class.
You could fix it a few ways. Print only the current item inside the loop, or print each item one at a time outside of the loop:
Console.WriteLine("{0}{1}", item.PadRight(20), ticket1[0]);
Console.WriteLine("{0}{1}", item.PadRight(20), ticket1[1]);
// etc...
Or "flatten" the collection before printing:
Console.WriteLine("My numbers: ", String.Join(", ", ticket1));
ticket1.ToString() does not print the content of the array, only its type, because this is the way the ToString() method is implemented on arrays.
You can fix this in several ways - for example, by using string.Join method:
Console.WriteLine("{0}{1}", item.PadRight(20), string.Join(",", ticket1));
Because you are not writing your array elements, you are writing your array itself, that's why ToString() generates it's full type name.
Change your ticket1.ToString() to ticket1[i] in your for loop.
for (int i = 0; i < 4; i++)
{
int temp = rand.Next(43);
while (ticket1.Contains(temp))
{
temp = rand.Next(43);
}
ticket1[i] = temp;
Console.WriteLine("{0} {1}", item.PadRight(20), ticket1[i]);
}
If you don't want to print it inside your for loop, then you can use String.Join to concatenate all your elements in your array in a simple string like;
for (int i = 0; i < 4; i++)
{
int temp = rand.Next(43);
while (ticket1.Contains(temp))
{
temp = rand.Next(43);
}
ticket1[i] = temp;
}
Console.WriteLine("{0} {1}", item.PadRight(20), string.Join(",", ticket1));
Because when you call .ToString() on an object you get the type of that object. For basic primitive (value) types this behavior is overridden to output the value. But for something like an array there's no "default" string representation, so the behavior you're seeing is the default.
You could wrap your data in an object and override .ToString() on that object. If you have to output the values in many places in the code that would be the way to go so you only have to write the logic once. ("Smart data structures and dumb code works a lot better than the other way around." - Eric Raymond)
But if you only need to do it here then you can just output the values directly. Basically join the values as a string in whatever representation you want. For example, if they should be comma-separated:
Console.WriteLine(
"{0}{1}",
item.PadRight(20),
string.Join(",", ticket1));
I didn't get the problem - I was trying to do a simple action:
for(i = x.Length-1, j = 0 ; i >= 0 ; i--, j++)
{
backx[j] = x[i];
}
Both are declared:
String x;
String backx;
What is the problem ? It says the error in the title...
If there is a problem - is there another way to do that?
The result (As the name 'backx' hints) is that backx will contain the string X backwards.
P.S. x is not empty - it contains a substring from another string.
Strings are immutable: you can retrieve the character at a certain position, but you cannot change the character to a new one directly.
Instead you'll have to build a new string with the change. There are several ways to do this, but StringBuilder does the job in a similar fashion to what you already have:
StringBuilder sb = new StringBuilder(backx);
sb[j] = x[i];
backx = sb.ToString();
EDIT: If you take a look at the string public facing API, you'll see this indexer:
public char this[int index] { get; }
This shows that you can "get" a value, but because no "set" is available, you cannot assign values to that indexer.
EDITx2: If you're looking for a way to reverse a string, there are a few different ways, but here's one example with an explanation as to how it works: http://www.dotnetperls.com/reverse-string
String is immutable in .NET - this is why you get the error.
You can get a reverse string with LINQ:
string x = "abcd";
string backx = new string(x.Reverse().ToArray());
Console.WriteLine(backx); // output: "dcba"
String are immuatable. You have convert to Char Array and then you would be able to modify.
Or you can use StringBuilder.
for example
char[] wordArray = word.ToCharArray();
In C# strings are immutable. You cannot "set" Xth character to whatever you want. If yo uwant to construct a new string, or be able to "edit" a string, use i.e. StringBuilder class.
Strings are immutable in C#. You can read more about it here: http://msdn.microsoft.com/en-us/library/362314fe.aspx
Both the variables you have are string while you are treating them as if they were arrays (well, they are). Of course it is a valid statement to access characters from a string through this mechanism, you cannot really assign it that way.
Since you are trying to reverse a string, do take a look at this post. It has lot of information.
public static string ReverseName( string theName)
{
string revName = string.Empty;
foreach (char a in theName)
{
revName = a + revName;
}
return revName;
}
This is simple and does not involve arrays directly.
The code below simply swaps the index of each char in the string which enables you to only have to iterate half way through the original string which is pretty efficient if you're dealing with a lot of characters. The result is the original string reversed. I tested this with a string consisting of 100 characters and it executed in 0.0000021 seconds.
private string ReverseString(string testString)
{
int j = testString.Length - 1;
char[] charArray = new char[testString.Length];
for (int i = 0; i <= j; i++)
{
if (i != j)
{
charArray[i] = testString[j];
charArray[j] = testString[i];
}
j--;
}
return new string(charArray);
}
In case you need to replace e.g. index 2 in string use this (it is ugly, but working and is easily maintainbable)
V1 - you know what you want to put their. Here you saying in pseudocode string[2] = 'R';
row3String.Replace(row3String[2], 'R');
V2 - you need to put their char R or char Y. Here string[2] = 'R' if was 'Y' or if was not stay 'Y' (this one line if needs some form of else)
row3String.Replace(row3String[2], row3String[2].Equals('Y') ? 'R' : 'Y');
This question already has answers here:
Remove element of a regular array
(15 answers)
Closed 9 years ago.
string[] columns
I want to delete the item on an index specified by a variable of type int.
How do I do this ?
I tried
columns.RemoveAt(MY_INT_HERE);
But apparently this does not works.
Array is immutable class, you can't change it, all you can do is to re-create it:
List<String> list = columns.ToList(); // <- to List which is mutable
list.RemoveAt(MY_INT_HERE); // <- remove
string[] columns = list.ToArray(); // <- back to array
May be the best solution is to redesign your code: change immutable array into List<String>:
List<String> columns = ...
columns.RemoveAt(MY_INT_HERE);
If you don't want to use linq you can use this function :
public string[] RemoveAt(string[] stringArray, int index)
{
if (index < 0 || index >= stringArray.Length)
return stringArray;
var newArray = new string[stringArray.Length - 1];
int j = 0;
for (int i = 0; i < stringArray.Length; i++)
{
if(i == index)continue;
newArray[j] = stringArray[i];
j++;
}
return newArray;
}
You use it like that : columns = RemoveAt(columns, MY_INT_HERE)
You can also make it to an extension method.
You cannot delete items in an array, because the length of a C# array is fixed at the time when it is created, and cannot be changed after that.
You can null out the corresponding element to get rid of the string, or use LINQ to produce a new array, like this:
columns = columns.Take(MY_INT_HERE-1).Concat(columns.Skip(MY_INT_HERE)).ToArray();
You need to add using System.Linq at the top of your C# file in order for this to compile.
However, using a List<string> would be a better solution:
List<string> columns;
columns.RemoveAt(MY_INT_HERE);
Try one of the following (depending on what you need):
columns[MY_INT_HERE] = null;
columns[MY_INT_HERE] = string.Empty;
...otherwise you'll just have to create a new array which has a length of 1 less than your current array, and copy the values over.
If you want something more flexible, you might use a something like a List<string>, where you can use RemoveAt()
Arrays are faster for the computer to work with but slower for a programmer. You will have to find that value with a loop or some other means, then set that position to null. You will end up with an empty space in the array. You could reallocate the array etc etc...
What is easier to use for relatively small amounts of data is a List. You can do myList.RemoveAt(100); and it will work nicely.
You can not delete it.You can recreate the array or I advice you to use List<string> for the same.
List<string> columns = new List<string>();
columns.RemoveAt(1);
It will remove the 2nd element from your List<String> columns
I am working on a file parser, and this bit of code is not giving me what I want. Before I go any farther, I should mention that I did not write this program, I am only editing the source to fix this specific problem. Also, I can compile the code, so that is not a problem (you know how downloaded programs always have compile errors). Here's the code.
case EsfValueType.Binary4E: //System.String[]
{
int size = (int)(this.reader.ReadUInt32() - ((uint)this.reader.BaseStream.Position));
var strings = new string[size / 4];
for (int i = 0; i < size / 4; i++)
strings[i] = this.stringValuesUTF16[this.reader.ReadUInt32()];
esfValue.Value = strings.ToString();
break;
}
Now, I added the .ToString(); part to the above line, but it made no difference. The problem is that esfValue.Value ends up with System.String[] as it's value, and I want the value of the System.String object. If you can make sense out of this and tell me what is wrong, it would be appreciated.
The program name is ESF Editor 1.4.8.0.
case EsfValueType.Binary4E: //System.String[]
{
int size = (int)(this.reader.ReadUInt32() - ((uint)this.reader.BaseStream.Position));
var strings = new StringBuilder();
for (int i = 0; i < size / 4; i++)
{
strings.Append(this.stringValuesUTF16[this.reader.ReadUInt32()]); //or AppendLine, depending on what you need
}
esfValue.Value = strings.ToString();
break;
}
The strings variable is an array of strings - the Array class does not override the default ToString() implementation which returns the type of the object.
You need to concatenate all the strings in the array - either looping and concatenating or using LINQ and assign the resulting string to esfValue.Value. Of course, this assumes you want the values all in one string, one after the other.
Your issue is that strings isn't a single string, its an array of strings. As a result your call to ToString is calling Object.ToString(), which returns the type of the object.
Maybe you want something like
esfValue.Value = strings.Aggregate((acc, next) => acc + next)
which will simply concatenate all the strings together.
When you do a .ToString() on a class that doesn't override the .ToString() base method to return a custom string (which string[] doesn't), you're always going to get the type's namespace/class as the result.
Arrays, in and of themselves, don't have values. What value are you trying to get? Are you trying to join the array into a single, character-delimited string? If so, this would work:
esfValue.Value = string.Join(",", strings);
Just replace the , with whatever character you want to delimit the array with.
I think you just need to join the string values contained in the string array. In order to do so, you need to call String.Join and pass the string separator and the string array. It returns a single System.String.