I want to see numbers updated only in console app, here is how I try to achieve this:
int successEntryCount = 0;
int failedEntryCount = 0;
Console.WriteLine("App Started:");
foreach (var entity in entities)
{
var res = bll.AsiErtelemeIptalPaketiGonder(entity);
if (res.State == Framework.Entities.MessageResultState.SUCCESS)
successEntryCount++;
else
failedEntryCount++;
Console.WriteLine("success :{0}", successEntryCount);
Console.WriteLine("fail:{0}", failedEntryCount);
}
Of course it duplicates the line and Console.Clear() is not a good option since the text would be blinking too fast. I just want to see only these numbers updated.
Use Console.SetCursorPosition method. Let's take a look at this simple example:
int successEntryCount = 0,
failedEntryCount = 10,
l = Console.CursorLeft,
t = Console.CursorTop;
for (int i = 0; i < 2000; i++)
{
Thread.Sleep(100);
Console.SetCursorPosition(l, t);
Console.WriteLine("success :{0}", successEntryCount++);
Console.WriteLine("fail:{0}", failedEntryCount++);
//or
//Console.Write("success :{0} fail:{1}", successEntryCount++ , failedEntryCount++);
}
It will update/print values without flickering.
There is more options (if you find them more attractive for you) to achieve same thing, for example:
Console.Write("\rsuccess :{0} fail:{1}", successEntryCount++, failedEntryCount++); //Carriage return
\r represents a carriage return (character 13) which means the cursor returns to the start of the line.
or
Console.Write("\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\bsuccess :{0} fail:{1}", successEntryCount++ , failedEntryCount++); //Using backspaces
\b is backspace character (character 8).
References: MSDN Escape Sequences
You can use Console.SetCursorPosition to set the cursor position. Also not to loose the existing console logs (already logged like - App Started: in your case), you can set the cursor position based on retrieved left and top position. The current left and right position can be retrieved using Console.CursorLeft and Console.CursorTop properties.
int successEntryCount = 0;
int failedEntryCount = 0;
Console.WriteLine("App Started:");
int left = Console.CursorLeft;
int right = Console.CursorTop;
foreach (var entity in entities)
{
var res = bll.AsiErtelemeIptalPaketiGonder(entity);
if (res.State == Framework.Entities.MessageResultState.SUCCESS)
successEntryCount++;
else
failedEntryCount++;
Console.SetCursorPosition(left, right);
Console.WriteLine("success :{0}", successEntryCount);
Console.WriteLine("fail:{0}", failedEntryCount);
}
Instead of
Console.WriteLine("success :{0}", successEntryCount);
Console.WriteLine("fail:{0}", failedEntryCount);
you might try something like
Console.Write("success :{0} fail:{1} \r", successEntryCount, failedEntryCount);
Related
I have a string with newline characters and I want to wrap the words. I want to keep the newline characters so that when I display the text it looks like separate paragraphs. Anyone have a good function to do this? Current function and code below.(not my own function). The WordWrap function seems to be stripping out \n characters.
static void Main(string[] args){
StreamReader streamReader = new StreamReader("E:/Adventure Story/Intro.txt");
string intro = "";
string line;
while ((line = streamReader.ReadLine()) != null)
{
intro += line;
if(line == "")
{
intro += "\n\n";
}
}
WordWrap(intro);
public static void WordWrap(string paragraph)
{
paragraph = new Regex(#" {2,}").Replace(paragraph.Trim(), #" ");
var left = Console.CursorLeft; var top = Console.CursorTop; var lines = new List<string>();
for (var i = 0; paragraph.Length > 0; i++)
{
lines.Add(paragraph.Substring(0, Math.Min(Console.WindowWidth, paragraph.Length)));
var length = lines[i].LastIndexOf(" ", StringComparison.Ordinal);
if (length > 0) lines[i] = lines[i].Remove(length);
paragraph = paragraph.Substring(Math.Min(lines[i].Length + 1, paragraph.Length));
Console.SetCursorPosition(left, top + i); Console.WriteLine(lines[i]);
}
}
Here is a word wrap function that works by using regular expressions to find the places that it's ok to break and places where it must break. Then it returns pieces of the original text based on the "break zones". It even allows for breaks at hyphens (and other characters) without removing the hyphens (since the regex uses a zero-width positive lookbehind assertion).
IEnumerable<string> WordWrap(string text, int width)
{
const string forcedBreakZonePattern = #"\n";
const string normalBreakZonePattern = #"\s+|(?<=[-,.;])|$";
var forcedZones = Regex.Matches(text, forcedBreakZonePattern).Cast<Match>().ToList();
var normalZones = Regex.Matches(text, normalBreakZonePattern).Cast<Match>().ToList();
int start = 0;
while (start < text.Length)
{
var zone =
forcedZones.Find(z => z.Index >= start && z.Index <= start + width) ??
normalZones.FindLast(z => z.Index >= start && z.Index <= start + width);
if (zone == null)
{
yield return text.Substring(start, width);
start += width;
}
else
{
yield return text.Substring(start, zone.Index - start);
start = zone.Index + zone.Length;
}
}
}
If you want another newline to make text look-like paragraphs, just use Replace method of your String object.
var str =
"Line 1\n" +
"Line 2\n" +
"Line 3\n";
Console.WriteLine("Before:\n" + str);
str = str.Replace("\n", "\n\n");
Console.WriteLine("After:\n" + str);
Recently I've been working on creating some abstractions that imitate window-like features in a performance- and memory-sensitive console context.
To this end I had to implement word-wrapping functionality without any unnecessary string allocations.
The following is what I managed to simplify it into. This method:
preserves new-lines in the input string,
allows you to specify what characters it should break on (space, hyphen, etc.),
returns the start indices and lengths of the lines via Microsoft.Extensions.Primitives.StringSegment struct instances (but it's very simple to replace this struct with your own, or append directly to a StringBuilder).
public static IEnumerable<StringSegment> WordWrap(string input, int maxLineLength, char[] breakableCharacters)
{
int lastBreakIndex = 0;
while (true)
{
var nextForcedLineBreak = lastBreakIndex + maxLineLength;
// If the remainder is shorter than the allowed line-length, return the remainder. Short-circuits instantly for strings shorter than line-length.
if (nextForcedLineBreak >= input.Length)
{
yield return new StringSegment(input, lastBreakIndex, input.Length - lastBreakIndex);
yield break;
}
// If there are native new lines before the next forced break position, use the last native new line as the starting position of our next line.
int nativeNewlineIndex = input.LastIndexOf(Environment.NewLine, nextForcedLineBreak, maxLineLength);
if (nativeNewlineIndex > -1)
{
nextForcedLineBreak = nativeNewlineIndex + Environment.NewLine.Length + maxLineLength;
}
// Find the last breakable point preceding the next forced break position (and include the breakable character, which might be a hypen).
var nextBreakIndex = input.LastIndexOfAny(breakableCharacters, nextForcedLineBreak, maxLineLength) + 1;
// If there is no breakable point, which means a word is longer than line length, force-break it.
if (nextBreakIndex == 0)
{
nextBreakIndex = nextForcedLineBreak;
}
yield return new StringSegment(input, lastBreakIndex, nextBreakIndex - lastBreakIndex);
lastBreakIndex = nextBreakIndex;
}
}
When the input's type is not an integer, the program should fail. However, there are two problems:
After a letter is typed and I get the "not valid" response, then if the next input is a number, it won't accept it and says "not valid".
How can I make it so when a wrong number is inputted, it stays on the same row and just clears the previous input from the screen (and allows for a retry from the same position)?
static void Main(string[] args)
{
int firstNum;
int Operation = 1;
switch (Operation)
{
case 1:
Console.SetCursorPosition(0, 0);
Console.Write("Write a number: ");
firstNum = ReadInteger("");
Console.ReadKey();
break;
}
}
private static int ReadInteger(string title)
{
while (true)
{
if (!string.IsNullOrWhiteSpace(title))
Console.WriteLine(title);
string input = Console.ReadLine();
if (int.TryParse(input, out int result))
return result;
Console.WriteLine("Sorry, not a valid integer value; please, try again.");
Console.ReadKey();
}
}
Ad 1)
Because you have Console.ReadKey at the end of ReadInteger which will be executed as well. So if you hit Console.ReadLine at the line string input = Console.ReadLine(); and enter something that is not a number, int.TryParse will return false. This leads to the error message and the execution of Console.ReadKey. So you should first of all get rid of that Console.ReadKey there.
Ad 2)
You are setting the cursor position before the call of ReadInteger but not within ReadInteger. So if someone enters a text, the end of the input is typically done by pressing enter. You then write a line (with Console.WriteLine). So if you want to have the cursor at the same position, you will have to reset it's position within the loop which is within the ReadInteger method.
How about something like this:
public static int ReadInt(string prompt)
{
Console.Clear();
var length = prompt.Length + 2; //2 is for a colon and a space
var position = length;
Console.Write($"{prompt}: ");
string buffer = String.Empty;
int returnNum = 0;
while (true)
{
Console.SetCursorPosition(position, 0);
var charRead = Console.ReadKey();
if(charRead.KeyChar == '\r')
{
return returnNum;
}
if (!int.TryParse(buffer + charRead.KeyChar, out returnNum))
{
Console.SetCursorPosition(position, 0);
Console.WriteLine(" "); //overwrite
Console.SetCursorPosition(0, 1);
Console.Write("Error: enter only digits");
continue;
}
else
{
buffer += charRead.KeyChar;
++position;
//overwrite any error
Console.SetCursorPosition(0, 1);
Console.Write(" ");
}
}
}
It's not perfect. It doesn't handle typing in too many digits. It doesn't handle backspace. It clears the console to establish position (it doesn't look like you can read the console position, and I'm too lazy to keep track of things).
If you do handle backspace, make sure you don't let users backup too much. It's been years (um, no, decades) since I've done low level console management, but I can remember doing this in CP/M in the early 80s - if you backed up to far, the OS died (which would be a very result in Windows :-) ).
I have a console app in C# that does a animation with a word, in a loop. Its basically showing the word going from left to righ.
My idea is that if the user press upArrow the animation would start to go up , if he press left the word would satrt to go left... and so on
My question is, how can i have a loop running and also have the program listen for the keyboard key that will be pressed at any given moment?
I wrote a good and considerable code for you although you need to complete it yourself. It just follows the order of the Left Arrow key. You need to add some extra code for following the other orders. Also you have to care about indexoutofrangeexception. As you can see I have written some extra code to handle the left side of console. I hope you enjoy it.
static void Main(string[] args)
{
const string txt = "STACKOVERFLOW";
var x = 1;
var startPos = 0;
var col = 0;
while (true)
{
do
{
while (!Console.KeyAvailable && (startPos <= 100 || startPos >= 0))
{
startPos = col + x;
if (startPos < 0)
{
startPos = 0;
x = 1;
}
Console.SetCursorPosition(startPos, 0);
Console.WriteLine(txt);
col = startPos;
Thread.Sleep(500);
Console.Clear();
}
} while (Console.ReadKey(true).Key != ConsoleKey.LeftArrow);
x = -1;
}
}
I don't know if you have found a solution for your program yet, but here is a good tutorial you might find useful.
Basic C# Game Programming Moving Object on the form
I have a console Application that Asks The user to answer question, The score is display at the upper-right of the screen, I want the score to be auto-Updates when a user gives a correct answer.
public void L1Timer()
{
Console.Clear();
int ch = 0, score = 0;
Console.Write("Chances : " + ch);
Console.CursorLeft = 40;
Console.Write("Marks : " + score);
for (int time = 0; time <= 100000; time++)
{
Console.SetCursorPosition(65, 0);
Console.Write("Time Elapsed : " + time + " Secs");
Console.CursorLeft = 40;
Thread.Sleep(1000);
}
}
public void Level1()
{
Console.WriteLine("\n\n");
Console.CursorLeft = 40;
Console.WriteLine("C _ _ E _ _ _ T _ _ N");
Console.WriteLine("\n\n");
int tot = 0;
while (tot != 70)
{
Console.Write("Guess : ");
string gues = Console.ReadLine();
if ((gues == "E") || (gues == "L") || (gues == "B") || (gues == "R"))
{
tot += 10;
}
}
}
static void Main(string[] args)
{
VocEnhancer VE = new VocEnhancer();
Thread T1 = new Thread(new ThreadStart (VE.L1Timer));
Console.WriteLine("\n\n\n\n\n");
Thread T2 = new Thread(new ThreadStart(VE.Level1));
T1.Start();
T2.Start();
}
This is my Code...I don't know what to add to auto-update the scores.
Without your code, we can only assume and my suggestion as follows:
string question = "CEO of Microsoft";
string actualAnswer ="STEVE BALLMER";
Console.WriteLine(question);
string userAnswer = "";
Console.WriteLine(userAnswer);
int score = 0;
if(actualAnswer.Trim() == userAnswer.ToUpper().Trim())
{
score++;
}
First a warning: console is not meant to display graphics, menus, or to be drawn on. It is meant to be written upon, one line at the time. For all things graphics there are windows, and windows should be used, not consoles. However, if you are just playing around and making fun at your leisure time then go ahead and write characters at strange places in the console.
To move the cursor use SetCursorPosition method. To find out where the cursor currently is use CursorLeft and CursorTop properties. When you want to write something at fixed coordinates save current cursor position, change to fixed position, write the text, and change back to old position.
But what should happen when all text reaches the end of the screen, and text at the top disappears? Well, there are ways to solve this, but don't bother. Just use window instead of console.
I get a string from the user and then put it in a char array. Now I want to display all the characters in the string along with how many times they appear. My code is as follows Please Correct me ?
using System;
class count
{
public void charcount()
{
int i ;
int count = 0;
string s;
Console.WriteLine("Enter the String:");
s = Console.ReadLine();
char[] carr = s.ToCharArray();
for(i = 0; i < carr.Length; i++)
{
for(int j = 1; j < carr.Length; j++)
{
if(carr[j] == carr[i])
{
count++;
}
else
{
return;
}
Console.WriteLine("The Character " + carr[i] + " appears " + count);
}
}
}
static void Main()
{
count obj = new count();
obj.charcount();
}
}
Well, your code will at least have problems due to the fact that you don't build a list of unique characters, you find them in the original string. Any string with characters that appear multiple times will show odd results.
Here's a LINQ expression that calculates the information for you (you can run this in LINQPad to immediately see the results):
void Main()
{
string s = "This is a test, with multiple characters";
var statistics =
from c in s
group c by c into g
select new { g.Key, count = g.Count() };
var mostFrequestFirst =
from entry in statistics
orderby entry.count descending
select entry;
foreach (var entry in mostFrequestFirst)
{
Debug.WriteLine("{0}: {1}", entry.Key, entry.count);
}
}
Output:
: 6 <-- space
t: 5
i: 4
s: 4
h: 3
a: 3
e: 3
l: 2
c: 2
r: 2
T: 1
,: 1
w: 1
m: 1
u: 1
p: 1
If you can't use LINQ, here's an example that doesn't use that:
void Main()
{
string s = "This is a test, with multiple characters";
var occurances = new Dictionary<char, int>();
foreach (char c in s)
{
if (occurances.ContainsKey(c))
occurances[c] = occurances[c] + 1;
else
occurances[c] = 1;
}
foreach (var entry in occurances)
{
Debug.WriteLine("{0}: {1}", entry.Key, entry.Value);
}
}
It looks like you want an outer loop and an inner loop, and for each char in the array, you want to compare to each that follows with int j = 1. In that case, you want int j = i + 1 in the inner loop:
for (int i = 0; i < carr.Length; i++)
{
for (int j = i + 1; j < carr.Length; j++)
{
}
}
But your return statement exits the function right in the middle of things. You need to let the loops complete, so you want to remove that return.
Your Console.WriteLine executes on every iteration of the inner loop, but you really only want it to iterate on the outer loop -- once for each character of the string and not once for every combination of i and j. So you need to push that to the outer loop, outside of the inner loop.
Also, you need to reset the count every time you begin another iteration of the outer loop, because you are counting again, and, you want to start counting at 1 not zero when you find a character because it just appeared once as you first reach it.
And as Lasse points out, you'll get strange output when you hit the same character as you move along the outer loop. An easy way to prevent that is to set the further (rightwards) char[j] to '\0' (null character) on every match, and then in the outer loop, ignore null characters in your counting for example by using continue, effectively culling them as you go along:
for(int i = 0; i < carr.Length; i++)
{
if (carr[i] == '\0')
{
continue; // skip any further chars we've already set to null char
}
int count = 1;
for (int j = i + 1; j < carr.Length; j++)
{
if(carr[j] == carr[i])
{
carr[j] = '\0'; // don't look for this char again later
count++;
}
}
Console.WriteLine("The Character " + carr[i] + " appears " + count);
}
My first thought would be to use a Dictionary as Daniel suggests, like this:
var dict = new Dictionary<char, int>();
string s = "This is a test, with multiple characters";
foreach (var c in s)
{
if (dict.ContainsKey(c))
{
dict[c]++;
}
else
{
dict[c] = 1;
}
}
foreach (var k in dict.Keys)
{
Console.WriteLine("{0}: {1}", k, dict[k]);
}
But I like the elegant LINQ solutions.
If you would have tested your code, you would have realized, that the code is very wrong.
Some of its problems:
You have only one count variable, although you want to count the occurences of all characters in your string
You are comparing the string with itself and return from your method, as soon, as the characters don't match.
The right way would be to use a Dictionary<char, int> to hold the count for each character, something like this:
var counts = new Dictionary<char, int>();
foreach(var c in s)
{
int count;
if(!counts.TryGetValue(c, out count))
{
counts.Add(c, 1);
}
else
{
++counts[c];
}
}
I didn't use LINQ on purpose, because I don't think you would understand that code. That's no offence.
If you want to go the LINQ way, this is a fairly brief way to do it (which I realize is pretty much the same as Lasse V. Karlsen's answer, only using different syntax):
var s = Console.ReadLine();
foreach (var group in s.GroupBy(c => c).OrderByDescending(g => g.Count()))
{
Console.WriteLine(" {0}: {1}", group.Key, group.Count());
}
The logic is the same whatever approach you use:
Identify each unique character
Count how many times each character occurs in the text
Output the result
In my code sample, s.GroupBy(c => c) takes care of the first two steps. The call OrderByDescending(g => g.Count()) will just sort the result so that more frequent characters come first. Each element in the result has a Key property (the character) and (amongst others) a Count() method that will return the number of occurrences for that character.