This question already has answers here:
Non-invocable member cannot be used like a method?
(6 answers)
Closed 5 years ago.
Hey StackOverflow users,
I'm working on a discord bot in C#. To keep my code clean, I'd like to use a function that adds more lines to a string.
An example of what I want to avoid is:
Description = $"Hey { username }! {Environment.NewLine + Environment.NewLine}{funMsg[randomNumber]}",
What I tried to do is:
public string inertlines(int i)
{
string st = "";
for (int c = 0; c < i; c++)
{
st += Environment.NewLine();
}
return st;
}
The visual studio compiler gives an error regarding the NewLine statement. "Non-invocable member 'Environment.NewLine' cannot be used like a method.
I'd really appreciate it if someone could tell me what do to avoid this and/or another method that could replace the Environment.NewLine() methode.
Finally I want to clearify that this is NOT a duplicate. For new programmers this post does explain alot more of a more specific problem. The post that got compared to mine had the same SOLUTION, however, not the same problem. It's even a whole different SUBJECT. On top of that, starters could copy the solution to easialy add extra lines to a string or understand how functions work better, as Environment.NewLine() is a well known and easy to understand methode under newer programmers.
Thanks in advance,
Jelle
Strings are immutable. If you're going to concatenate many of them, for effiency's sake, instead try using StringBuilder:
public string insertlines(string s, int i)
{
StringBuilder sb = new StringBuilder();
sb.Append(s); // create the string
for (int c = 0; c < i; c++)
{
sb.AppendLine(""); // add a line each time
}
return sb.ToString();
}
The answer turns out to be really simple
public string insertlines(int i)
{
string st = "";
for (int c = 0; c < i; c++)
{
//Environment.NewLine shouldn't have "()" in it's own class
st += Environment.NewLine;
}
return st;
}
The usage of this to create white lines in a string would be:
Console.WriteLine($"I want 2 {insertLines(2)} blanc lines under the 2"});
or to simplify that example:
Console.WriteLine("I want 2 " + insertLines(2) + " blanc lines under the 2");
For anyone reading this, please just use "\n" for new lines in a string. I've learned alot more about coding and think my question and answer were not the best, most helpful ones.
Related
This question already has answers here:
How to reverse an array using the Reverse method. C# [closed]
(6 answers)
Closed 6 months ago.
using System;
using System.Linq;
namespace Array.ReversingArrayChar
{
class Program
{
static void Main(string[] args)
{
string input = Console.ReadLine();
char[] symbol = input.Split(' ').Select(char.Parse).ToArray();
symbol.Reverse();
for (int a = 0; a <= symbol.Length - 1; a++)
{
Console.Write(symbol[a] + " ");
}
}
}
}
When I run the code I get the Array printed but not in reversed order even tho I used .Reverse(). It's probably a really simple mistake but it's too late at night for my brain to figure it out.
Enumerable.Reverse is a LINQ extension that returns the sequence reversed, so you have to assign it to a variable. But here you want to use Array.Reverse:
Array.Reverse(symbol);
Use Enumerable.Reverse if you don't want to modify the original collection and if you want to support any kind of sequence. Use List.Reverse or Array.Reverse if you want to support only these collections and you want to modify it directly. Of course this is more efficient since the method knows the size and you need less memory.
Oh Man..! you are almost there, your code is fine but you need to use the output of the .Reverse() method. since the method won't modify the actual collection, it will return the reversed array. you can try the following:
string input = "A S D R F V B G T";
char[] symbols = input.Split(' ').Select(char.Parse).ToArray();
foreach (var symbol in symbols.Reverse())
{
Console.Write(symbol + " ");
}
You will get the output as T G B V F R D S A
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');
We have been tasked with designing a C# trivia application as a File I/O exercise. So far, I've got a good start, but the presentation step is kind of stumping me.
I'm starting with a delimited file featuring the following data:
Question;CorrectAnswerA;AnswerB;AnswerC;AnswerD;AnswerExplanation
e.g.,
What color is the sky?;Blue;White;Green;Yellow;The sky is blue.
The game will display the question and the four answers from which the user can select.
What Color is the Sky?
A. Blue
B. White
C. Green
D. Yellow
Select A, B, C, or D:
Unfortunately, for ease of populating the dataset, A is always the correct answer. I want to randomize the order in which the four answers display, but the program still needs to know which was the correct answer. I also need to have a user input of A, B, C, or D tie back to a specific instance of an answer to compare the selectedAnswerString to the correctAnswerString.
I've been playing with an array of the four answers which are randomly populated, but I can't wrap my head around how to flag something as correct based on the user's choice; my logic to do or assign that always seems to fall out of scope or duplicate across all four records in the array.
Other students I've talked to said they created their datasets with the answers pre-scrambled (so they can just print them in the order read) with a FIFTH answer field for the correct answer. While definitely an EASY way to make it happen, I don't think it's as elegant as my strategy.
Should I just change the input dataset? does anyone have any ideas on a good way to pursue my idea for the randomization?
Create a class called Question with properties: int Id, string QuestionText, List<string> Answers, string CorrectAnswer
Or, as step forward, also create class Answer with Id and Value and reference to it.
public class Question
{
public int Id;
public string QuestionText;
public List<Answer> Answers;
public Answer CorrectAnswer;
}
public class Answer
{
public int Id;
public string Value;
}
Afterwards populate this structure and randomize when printing
Keep track of the correct answer using a separate variable. Then use Fisher-Yates to shuffle your array:
Random random = new Random();
void Shuffle(string[] answers) {
for (int i = 0; i < answers.Length - 1; i++) {
int j = random.Next(i, answers.Length);
string temp = answers[j];
answers[j] = answers[i];
answers[i] = temp;
}
}
After the user responds, just compare their selection with the correct answer you've saved.
Try defining your data structure for a question in this way:
public class Question
{
public string Question;
public string[] Answers;
public int CorrectAnswer;
public string CorrectAnswerExplanation
}
This way you can scramble the strings in the array Answers, while still keeping track of the index of the correct answer in CorrectAnswer.
Alternatively if you can't use a separate class to model the question (this is a homework question so maybe you have not learned this yet), you can use a predetermined position in the array (the 1st or the 5th element) to hold the index of the correct answer. So your array for answers would look like:
"Blue", "White", "Green", "Yellow", "0"
Step 1: Define a data structure. Others have already given you a structure so use that.
Step 2: Populate your data structure. You could System.IO.File.ReadLines and parse each line - I assume you have this bit handled already.
Step 3: Randomize the order of your answers. For this, assuming you have your structure:
public static void RandomiseAnswers(IEnumerable<Question> questions)
{
var rand = new Random((int)DateTime.Now.Ticks);
foreach (var question in questions)
{
question.Answers = question.Answers.OrderBy(x => rand.Next()).ToArray();
}
}
Step 4: Recieve gold star from teacher for your outstanding work
Personally I'd put a boolean in the Answer class defaulting to false. This way when the answer is selected you can read whether it's correct or not.
public class AskQuestion
{
public int Id;
public string Question;
public string Explanation;
public List<Answer> Answers = new List<Answer>();
}
public class Answer
{
public bool Correct = false;
public string Value;
}
now when you randomize the list the correct answer is automatically identified
One way to use these classes would be like this:
static void Main(string[] args)
{
StreamReader sr = new StreamReader("text.txt");
List<AskQuestion> Questions = new List<AskQuestion>();
Random rnd = new Random(DateTime.Now.Millisecond);
//Loop through the file building a list of questions
while(!sr.EndOfStream)
{
AskQuestion NewQuestion = new AskQuestion();
string[] input = sr.ReadLine().Split(';');
NewQuestion.Question = input[0];
NewQuestion.Explanation = input[5];
for(int i = 1; i < 5; i++)
{
Answer NewAnswer = new Answer();
NewAnswer.Value = input[i];
NewQuestion.Answers.Add(NewAnswer);
}
//The first question is always correct so set its boolean value to true;
NewQuestion.Answers[0].Correct = true;
//Now ranmdomize the order of the answers
NewQuestion.Answers = NewQuestion.Answers.OrderBy(x => rnd.Next()).ToList();
Questions.Add(NewQuestion);
}
//Generate menu and get response for each question
foreach(AskQuestion q in Questions)
{
Console.WriteLine(q.Question + ":\n\tA - " + q.Answers[0].Value + "\n\tB - " + q.Answers[1].Value + "\n\tC - " + q.Answers[2].Value + "\n\tD - " + q.Answers[3].Value + "\n");
char input = '0';
while(input < 'A' || input > 'D')
{
input = char.ToUpper(Console.ReadKey().KeyChar);
if(input >= 'A' && input <= 'D')
{
//Use the boolean value in the answer to test for correctness.
if(q.Answers[input - 'A'].Correct)
{
Console.WriteLine("\nCorrect\n");
}
else
Console.WriteLine("\nWrong\n");
Console.WriteLine(q.Explanation);
}
}
}
Console.ReadLine();
}
This question already has answers here:
c# multi assignment
(7 answers)
Closed 8 years ago.
In some languages it is possible to initialize several variables at the same time from an array.
For example in PHP you can do something like this:
$array = array('a', 'b', 'c');
list($a, $b, $c) = $array;
Is it possible to do this in C# as well?
I want to apply this on a program where I read all lines from a file where I know every line is two words only (never more, never less).
I know I can create the function myself (and sending in variables by reference with outkeyword) but I would like to know if any built in functionality exists for it.
I would like to know this mostly for the reason that if it is possible the code might be more readable for other developers.
In C#,
string[] arr1 = new string[] { "one", "two", "three" };
string s1 = arr1[0];
string s2 = arr1[1];
string s3 = arr1[2];
If readability is the issue and if I understand you correctly - I don't know of an in-built way. But you can create a function for that.
void Doit(out string one, out string two, string[] input)
{
one = input[0];
two = input[1];
}
And use it thus:
string[] s = new string[] { "First", "Second" };
string a, b;
Doit(out a, out b, s);
I just realized that you don't need my answer. (I had initially understood "I know I can create the function myself..." differently.) Perhaps, though, it can help someone else.
char[] array = new char[] {'a','b','c'};
As far as I know there is no buit-in way to do that.
Maybe a good way to implement that functionality is by using extension methods in order to improve readability.
Simply write the needed code in a extension method that can be attached to the type you want to initialize like a list in your example above and take an array as input to that function:
public static class Extensions {
public static void initFromArray<T> (this List<T> list, T[] array) {
for (int i = 0; i < array.Length; i++) {
list[i] = array[i];
}
}
}
Then you can use this method for example like in the following:
int[] array = new int [] { 1, 4, 6, 2, 5 };
List<int> list = new List<int>();
for (int i = 0; i < 4; i++) list.Add(0);
list.initFromArray<T>(array);
This question already has answers here:
Closed 11 years ago.
Possible Duplicate:
Can I “multiply” a string (in C#)?
Is there a simple way to display a String multiple times by using something like str * 2?
In other words, is there a way to have:
int numTimes = 500;
String str = "\n";
String body = ""
for (int i = 0; i < numTimes; i++)
{
body = "Hello" + str;
}
Without needing the for loop?
Nope. There is no such operator.
you could do
body = "Hello" + String.Join("", Enumerable.Range(0, numTimes).Select(i => str));
but that's internally still looping.
The answer to this, without simply hiding the loop or some other contrived example, is no.
Yes and no.
No, not out of the box.
Yes, you can make an extension method to do that pretty easily.
See thread on string extension methods here C# String Operator Overloading
It would still be looping, so you should use StringBuilder, not pure concatenation, if possible, especially if you don't know how many times it will loop. Strings are immutable, so 500 loops is an awful lot of temp strings in memory.