How can i declare a variable inside String.format and use it again like :
String.Format("{0} {1}", int t = 1, new string[] { "a", "b" }.ElementAt(t));
update
I just want to learn something new and type the code in one line.
It is not necessary in this case, but useful in others.
update
I found another solution :
int indx;
var st = String.Format("{0} {1}", (indx=1), new string[] { "a", "b" }.ElementAt(indx));
It would be good if you would share reason why you try to do it this way, and maybe tell us what are you working on.
Your code to work should look like this
int t = 1;
string[] myArray = new string[] { "a", "b" };
Console.WriteLine(string.Format("{0} {1}", t, myArray[t]));
What you are attempting to do seems to be without any sense, first of all it will not work. Doing stuff your way makes it impossible to access t and array you created and even if it worked it would be same as static string string myString = "1 b". Your way you make it impossible to manipulate these variables because they would only exist in context of that one line and would be back to their initial value when it gets executed each time.
It is not possible. Consider string.format as a method with few overloads, which takes few set of parameters as mentioned in MSDN link. Your way of calling the method does not satisfy your intent hence it would fail.
I don't understand any reason why you would try to do something like this.
Related
Currently I am trying to write something to take strings from a txt file and input them into an array. I was doing it by manually inputting them and using interpolated strings but that is becoming unfeasible now. I need to be able to change parts of the string depending on the result of a function, and on any given string there could 0 to any number of parts that need to be changed. I figured this would work in theory but that there had to be a better way:
public void formatStringInSentencesArray(int numOfArgs, int arrIndexToBeFormatted, UnityAction[] funcsToBePutIn)
{
if (numOfArgs == 1)
{
conversation[index].sentences[arrIndexToBeFormatted] = string.Format(conversation[index].sentences[arrIndexToBeFormatted], funcsToBePutIn[0]);
}
...
else if (numOfArgs == 5)
{
conversation[index].sentences[arrIndexToBeFormatted] = string.Format(conversation[index].sentences[arrIndexToBeFormatted], funcsToBePutIn[0], funcsToBePutIn[1], funcsToBePutIn[2], funcsToBePutIn[3], funcsToBePutIn[4]);
}
Is there any way I could go about doing this in a way that isn't just a hacked together bunch of ifs and else ifs? (This is all written in C# for a unity game btw)
Welcome to SO.
string.format already supports arrays. Is this what you're looking for?
var paramArray = new string[] { "a", "b", "c", "d", "e" };
var output = string.Format("{0} {1} {2} {3}", paramArray);
Based on your example, I'd probably replace your function with:
conversation[index].sentences[arrIndexToBeFormatted] = string.Format(conversation[index].sentences[arrIndexToBeFormatted], funcsToBePutIn);
By using the params keyword, you can specify a method parameter that takes a variable number of arguments. The parameter type must be a single-dimensional array.
No additional parameters are permitted after the params keyword in a method declaration, and only one params keyword is permitted in a method declaration.
https://learn.microsoft.com/en-us/dotnet/csharp/language-reference/keywords/params
The compiler will deal with turning that line of Arguments into a single array.
The String.Format() - and function that use it like Console.WriteLine() - use the params keyword. The main function behaves as if it does, but given that the data comes from the OS it is possible it is not using the keyword (making the array is somebody elses job).
Using this, I'm trying to print a list of the contents of players.text
I know that the foreach loop will print it just fine if the Console.Writeline
is used. But I'm attempting to manipulate the data in particular ways later, and need it split using the indicated delimiter.
However, with the given code all I get is a repeated System.String[] printout.
I've done a search or two and most of what I've found has to do with one part or the other, I haven't found any information on how to use them together.
string[] playerFile = File.ReadAllLines("players.txt");
foreach (string s in playerFile)
{
//Console.WriteLine(s);
string[] playerStuff = s.Split(';');
Console.WriteLine(playerStuff);
}
Console.ReadKey();
I realize it's a simplistic question. But often, for me at least, it's missing the obvious that drives me the most crazy.
Thanks in advance.
Player;Team;POS;HR;RBI;AVG
Abreu, J;CWS;1B;30;101;0.29
Altuve, J;HOU;2B;15;66;0.313
Andrus, E;TEX;SS;7;62;0.258
Arenado, N;COL;3B;42;130;0.287
Aybar, E;LAA;SS;3;44;0.27
The above is the first few lines of the input.
Basically, I want it to look just like that, minus the semicolons. Formatting will come later.
Attempting to add a second foreach, such as was suggested below, the code looked like this:
foreach (string s in playerFile)
{
//Console.WriteLine(s);
string[] playerStuff = s.Split(';');
foreach (string player in playerStuff)
{
Console.WriteLine(player);
}
}
This resulted in EACH piece of information getting it's own line. I follow the logic of why it did that, but I'm not sure what to do about it.
For a method call to compile the compiler has to figure out what you want to do and here, in particular, there are many overloads to the Console.WriteLine method. An "overload" basically means that there are several definitions of Console.WriteLine, all taking different types of parameters.
If the compiler can find an overload that takes exactly what you're trying to pass it, in this case string[], then good, that's the overload that will be called.
If not then it will take "the next best thing", if at all possible.
Let's list all the overloads to Console.WriteLine:
WriteLine()
WriteLine(Boolean)
WriteLine(Char)
WriteLine(Char[])
WriteLine(Char[], Int32, Int32)
WriteLine(Decimal)
WriteLine(Double)
WriteLine(Int32)
WriteLine(Int64)
WriteLine(Object)
WriteLine(Single)
WriteLine(String)
WriteLine(String, Object)
WriteLine(String, Object, Object)
WriteLine(String, Object, Object, Object)
WriteLine(String, Object, Object, Object, Object)
WriteLine(String, Object[])
WriteLine(UInt32)
WriteLine(UInt64)
Now, now of these will be able to accept a string[] except one:
WriteLine(Object)
This particular overload will simply call .ToString() on whatever it is passed.
Since a string array does not have a ToString implementation that looks at the contents of the array, or anything like that, the basic System.Object.ToString() method that every type inherits is used, and this simply returns the full name of the type as a string, which is basically System.String[].
So that's why the code compiles, and also why it doesn't do what you expect it to do.
The question is, what do you expect it to do?
If you wanted it to output all the strings as a comma-separated set of values on each line you can do this:
Console.WriteLine(string.Join(", ", playerStuff));
If you simply wanted to concatenate all the strings and put nothing between them, replace the ", " in the above statement with "" or string.Empty:
Console.WriteLine(string.Join(string.Empty, playerStuff));
The reason you are getting the output that you are is because it is trying to write the Array object to the console; and it doesn't know how to handle it, so it is just printing out the Type of the object that it is trying to write out.
You need to do another foreach or something similar on playerStuff.
string[] playerFile = File.ReadAllLines("players.txt");
foreach (string s in playerFile)
{
//Console.WriteLine(s);
string[] playerStuff = s.Split(';');
//Inner foreach that writes out each entry of the array
foreach(var item in playerStuff)
{
Console.Write(item + " ");
}
Console.Write(Environment.NewLine);
}
Console.ReadKey();
OR even simpler
string[] playerFile = File.ReadAllLines("players.txt");
foreach (string s in playerFile)
{
Console.WriteLine(s.Replace(';', ' '));
}
Console.ReadKey();
OR a one liner
string[] playerFile = File.ReadAllLines("players.txt");
playerFile.ForEach(x => Console.WriteLine(x.Replace(';', ' ')));
Console.ReadKey();
Sample output image for all 3 of the above solutions:
Console.WriteLine docs for reference
String.Replace docs for reference
HOMEWORK QUESTION:
I need to create a simple trivia game that reads from a CSV file. My data for a particular question is structured as follows: "Question;AnswerA;AnswerB;AnswerC;AnswerD;CorrectAnswerLetter".
We're using a series of getters and setters to hold all the relevant data for a single question object, and I'm running into a problem with the array I've created to hold the four answers.
In my constructor, I'm using this code--which I believe instantiates the Answer array in question:
class TriviaQuestionUnit
{
...
const int NUM_ANSWERS = 4;
string[] m_Answers = new String[NUM_ANSWERS];
public string[] Answer
{
get { return m_Answers[]; }
set { m_Answers = value[];
}
...
// Answer array
public string[] GETAnswer(int index)
{
return m_Questions[index].Answer;
}
...
}
I'm accessing the getter and setter from my TriviaQuestionBank method, which includes this code:
...
const int NUM_QUESTIONS = 15;
TriviaQuestionUnit[] m_Questions = new TriviaQuestionUnit[NUM_QUESTIONS];
...
// Answer array
public string[] GETAnswer(int index)
{
return m_Questions[index].Answer;
}
...
I'm using using StreamReader to read a line of input from my file
...
char delim = ';';
String[] inputValues = inputText.Split(delim);
...
parses the input in an array from which I create the question data. For my four answers, index 1 through 4 in the inputValues array, I populate this question's array with four answers.
...
for (int i = 0; i < NUM_ANSWERS; i++)
{
m_Questions[questionCounter].Answer[i] = inputValues[i + 1];
}
...
I'm getting errors of Syntax code, value expected on the getters/setters in my constructor, and if I change the variable to m_Answers[NUM_QUESTIONS] I get an error that I can't implicitly convert string to String[].
Hopefully I've posted enough code for someone to help point me in the right direction. I feel like I'm missing something obvious, but I just cannot make this work.
Your code has some errors that will cause compilation errors, so my first lesson for you is going to be: listen to the compiler. Some of the errors might seem a bit hard to understand sometimes, but I can ensure you that a lot of other people have had the same problems before; googling a compiler error often gives you examples from other people that are similar to your issue.
You say "In my constructor", but the problem is that your code does not have a constructor. You do however initialize fields and properties on your class and surely enough, the compiler will create a default constructor for you, but you have not defined one yourself. I am not saying that your code does not work because you do not have a constructor, but you might be using the wrong terms.
The first problem is in your first code snippet inside TriviaQuestionUnit. Your first two lines are working correctly, you are creating a constant integer with the value 4 that you use to determine how large your array is going to be and then you initialize the array with that given number.
When you do new string[NUM_ANSWERS] this will create an array, with default (empty) values.
The first problem that arises in your code is the getters and setters. The property expects you to return an array of strings which the method signature in fact is telling us:
public string[] Answer
However, looking at the getter and setter, what is it that you return?
m_Answers is a "reference" to your array, hence that whenever you write m_Answers you are referring to that array. So what happens when we add the square brackets?
Adding [] after the variable name of an array indicates that we want to retrieve a value from within the array. This is called the indexer, we supply it with an index of where we want to retrieve the value from within the array (first value starts at index 0). However, you don't supply it with a value? So what is returned?
Listen to the compiler!
Indexer has 1 parameter(s) but is invoked with (0) argument(s)
What does this tell you? It tells you that it doesn't expect the empty [] but it would expect you to supply the indexer with a number, for instance 0 like this: [0]. The problem with doing that here though, is that this would be a miss-match to the method signature.
So what is it that we want?
We simply want to return the array that we created, so just remove [] and return m_Answers directly like this:
public string[] Answer
{
get { return m_Answers; }
set { m_Answers = value; }
}
Note that you were also missing a curly bracket at the end if the set.
When fixing this, there might be more issues in your code, but trust the compiler and try to listen to it!
string nr = "42245555" //just an example number
string expression = "{5}{6}/{7}{8}";
string res = String.Format(expression, new string[] {
nr[0].ToString(),nr[1].ToString(),
nr[2].ToString(), nr[3].ToString(),
nr[4].ToString(), nr[5].ToString(),
nr[6].ToString(), nr[7].ToString()
});
Why is this not working and how can I solve it?
I want expression to be either "{5}{6}/{7}{8}" or "{0}{3}/{7}{1}" or whatever the user wants.
You must supply at least the same number of parameters (or an array with at least the same number of elements) as the highest placeholder value plus one (placeholder values are zero indexed)
Max placeholder value {3}, you must supply at least four additional parameters.
Try this:
string res = String.Format(expression,
nr[0], nr[1],
nr[2], nr[3],
nr[4], nr[5],
nr[6], nr[7]);
Note that I took out new string[] { ... } I also took out all the ToString() because they are not required.
The relevant overload of Format is:
public static string Format(string format, params Object[] args)
This means you can either call it like this:
Format("...",new object[]{...})//Each array element is used
Or with the objects directly as parameters:
Format("...",object1, object2,...)//the objects are used
Unlike what I originally thought, a string[] does indeed go into the first variant of this code. This is due to array covariance in C#/.net which allows a string[] to be implicitly converted to a object[].
string.Format("{0} {1}",new string[]{"A","B"})
prints A B.
On the other hand if you try similar code with a int[] it won't work:
string.Format("{0} {1}",new int[]{1,2})
Will throw an exception because it goes into the second variation, and thus only a single parameter of type int[] is seen by string.Format. This difference is because array covariance only works on arrays with members that are a reference type like string and not a value type like int. This means int[] is not implicitly convertible to object[].
So the problem with your original code is probably just that you used the index {8} which is out of range.
The parameters in expression must start from "{0}" and the array must contain the same number of parameters as the expression and it must be an array of objects : new object[]{...
Your parameters are numbered 0..7, easy to read back. Yet you use {8} : Index out of Range
You don't need the new string[] { } around the parameters. It is allowed though.
without the new string[] { } you don't need the .ToString() calls either.
IF ur user wants {5}{6}/{7}{8} , then ur code will be:
String.Format("{0}{1}/{2}{3}",nr[4],nr[5],nr[6],nr[7]);
ur indexes in the expression must always start with 0..In my example if u want to display this for strings.. u start by 0,1,2,3.. 0 for nr[4], 1 for nr[5], 2 for nr[6], 3 for nr[7], etc..
You have to use:
nr.Substring(...)
in String.Format([expression], [values]) expression is a string represent a string with placeholders while values are inserted in those placeholders.
updated
string nr = "42245555" //just an example number
string res = String.Format("{0}{1}/{2}{3}", new string[] {
nr[5].ToString(),nr[6].ToString(),
nr[7].ToString(), nr[8].ToString()
});
or
string res = String.Format("{0}{1}/{2}{3}", new string[] {
nr[0].ToString(),nr[3].ToString(),
nr[7].ToString(), nr[1].ToString()
});
I'm trying to consume a DLL-located method in C#, which returns a dynamic array of structs. What ever I do, I receive the well-know "Object reference not set to an instance of an object" error, Here is my last code and it still tells that error:
string v_user = "kish";
string v_pass = "u";
string v_number = "p";
string v_address = "url has been replaced with this string";
string v_cid = "abc";
Cls_SMS.SMSReceive.STC_SMSReceive[] xts;
Cls_SMS.SMSReceive px = new Cls_SMS.SMSReceive();
// *** is the below line
xts = px.ExtendReceiveSMS(v_user, v_pass, v_number, v_address, v_cid);
int upper_bound = xts.GetUpperBound(0);
for (int counter = 0; counter < upper_bound; counter++)
{
Response.Write(xts[counter].Message.ToString());
Response.Write("<br>");
}
please note that my main problem is about receiving a dynamic array of structs with struct type name (Cls_SMS.SMSReceive.STC_SMSReceive) and other aspects such as connecting to the remote server is not my problem. I just want to allocate a dynamic array of vendor-defined structs to the left side of the assignment opeator in * line.
Please help me.
Thank you very much.
It is not clear how the px.ExtendReceiveSMS(v_user, v_pass, v_number, v_address, v_cid); method assigns the array, it probably doesn't assign it at all because of the exception. Here's how you could assign a dynamic array and return it:
public STC_SMSReceive[] ExtendReceiveSMS()
{
STC_SMSReceive[] result = new STC_SMSReceive[2];
result[0] = new STC_SMSReceive();
result[1] = new STC_SMSReceive();
return result;
}
Also if it is dynamic you might also take a look at List<T>:
public IList<STC_SMSReceive> ExtendReceiveSMS()
{
IList<STC_SMSReceive> result = new List<STC_SMSReceive>();
list.Add(new STC_SMSReceive());
list.Add(new STC_SMSReceive());
return result;
}
This has nothing to do with the strict array; simply, the library method you are using is returning null.
There are various possibilities here:
maybe returning null is an expected return value for some scenarios; check the documentation
maybe you need some additional configuration, or maybe you need to call some additional method (GetTheData() would be too hopeful ;p), or wait for some other event before this data is available - check the documentation
maybe it is simply a library bug; contact the vendor
If all 3 routes fail, personally I'd just open it reflector and look for a scenario that might return null. Then tell the vendor to fix the bug or clarify the documentation as appropriate.
If you replace your separate declaration of xts with:
var xts = px.ExtendReceiveSMS(v_user, v_pass, v_number, v_address, v_cid);
what type does Visual Studio now report xts to be?
You can tell by hovering over xts with your cursor and reading it off the tooltip.
Other than that if the vendor is reporting that it works for other users, you must have one (or more) of the arguments wrong. Ask the vendor for some example code that works so you can check to see if that connects to the server properly. If it does then the error is in the other arguments, if not then it's a problem with your connection to the server.