Losing value if backwards List printing matrix - c#

I need to display a Sheet so that the lines are aligned bottom and left. If there are no 10 characters in the word, the number of "+" characters is added so that the total of the line is 10 characters (see my output).
Why, when I print a List, I lose one row?
What's wrong with my piece of code? This matrix should be 10X10.
My output
List<string> filtredList = new List<string>() { "Jacuzzi", "Action", "Chinchilla", "Squeezebox", "Academic", "Abstract" };
int row = 10;
filtredList = Sorting(filtredList); //method is sorting by descending.
foreach (var item in filtredList) Console.WriteLine("Item: " + item + " length: " + item.Length);
Console.WriteLine("-------------------------------------");
//AFTER SORTING IN LIST:
//1)Squeezebox 2)Chinchilla 3)Academic 4)Abstract 5)Jacuzzi 6)Action
for (int i = 10; i > 0; i--)
{
try
{
if (filtredList[i].Length != 10)
{
Console.Write(filtredList[i]);
row = 10 - filtredList[i].Length;
Console.WriteLine(string.Concat(Enumerable.Repeat("+", row)));
}
else Console.WriteLine(filtredList[i]);
}
catch (SystemException)
{
row = 10;
Console.WriteLine(string.Concat(Enumerable.Repeat("+", row)));
}
}

Because your for loop is never gets to 0:
for (int i = 10; i > 0; i--)
i goes from 10 to 1 and that's why the first item of your list never prints.
Note:
Index of first item of an array or a list is 0
The better code would be:
for (int i = 9; i >= 0; i--)
Although you can use better alternatives for some of your code, but this will solve your problem.
EDIT:
You can use this approach (just change the for part to this) to not raise any exceptions (because its not normally a use case for try-catch)and also get faster results:
for (int i = 9; i >= 0; i--)
{
if (i < filtredList.Count)
{
if (filtredList[i].Length != 10)
{
Console.Write(filtredList[i]);
row = 10 - filtredList[i].Length;
Console.WriteLine(new string('+', row));
}
else Console.WriteLine(filtredList[i]);
}
else
{
row = 10;
Console.WriteLine(new string('+', row));
}
}

Related

ListView addition of the sum of numbers in lines

Please help with the code. How can you add numbers from 3,4,5 columns and transfer it to the "Total" column. At the same time, the "Total" column cannot be permanent, for example, listView1.Items [i] .SubItems [11] .Text - this solution is not appropriate, you need to possibly find the "Total" column itself because it is not permanent It can be like SubItems [ 9] 10.11, etc.
Code to write data to listView1
dataReader = await cmd1.ExecuteReaderAsync();
if (dataReader.FieldCount > 0)
{
for (int i = 0; i < dataReader.FieldCount; i++)
{
if (i == 0)
{
listView1.Columns.Add(dataReader.GetName(0), 0, HorizontalAlignment.Left);
}
else
{
listView1.Columns.Add(dataReader.GetName(i).ToString().Replace("_", " "), 80, HorizontalAlignment.Left);
}
}
ListViewItem lv = new ListViewItem();
//
while (await dataReader.ReadAsync())
{
lv = listView1.Items.Add(dataReader[dataReader.GetName(0)].ToString().Replace('_', ' '));
for (int h = 1; h < dataReader.FieldCount; h++)
{
lv.SubItems.Add(dataReader[dataReader.GetName(h)].ToString());
}
}
}
for (int i = 1; i < listView1.Columns.Count; i++)
listView1.Columns[i].Width = -2;
This code assumes there is a column named "Total" in listView1.
(int itt = 1; itt < listView1.Items.Count; itt++)
{
int Totall =
int.Parse(listView1.Items[itt].SubItems[2].Text) +
int.Parse(listView1.Items[itt].SubItems[3].Text) +
int.Parse(listView1.Items[itt].SubItems[4].Text);
//Сумма чисел добавить во всего
listView1.Items[itt].SubItems["Total"].Text = Totall.ToString();
}
int.Parse converts a string to an integer but keep in mind it will throw an exception if the string is not numerical. If you need error checking for that consider using int.TryParse.
Also note that SubItems are 0 indexed. Meaning 0 corresponds to the first visual column, 1 corresponds to the second.

Steganography extraction issue C#

I am able to hide my text inside an Image. But when I tried to extract the text from my image, I always only able manage to get only the first character. I don't know where went wrong?
My embed operation code:
public static Bitmap embedMessage(string hiddenText, Bitmap oriImage)
{
Color currentPixel;
int[] colorRGB = new int[3];
List<int> messageValue = new List<int>();
messageValue = ConvertMessage(messageValue, hiddenText);
int messageIndex = messageValue.Count;
int binaryCount = 0;
int zeroAdded = 0;
for(int row = 0; row < oriImage.Height; row++)
{
for(int col = 0; col < oriImage.Width; col++)
{
currentPixel = oriImage.GetPixel(col, row);
colorRGB[0] = ConvertEven(currentPixel.R);
colorRGB[1] = ConvertEven(currentPixel.G);
colorRGB[2] = ConvertEven(currentPixel.B);
for(int rgbIndex = 0; rgbIndex < colorRGB.Length; rgbIndex++)
{
if(messageIndex > 0)
{
colorRGB[rgbIndex] += messageValue[messageValue.Count - messageIndex] % 2;
messageValue[messageValue.Count - messageIndex] /= 2;
}
}
if (messageIndex == 0 && zeroAdded < 8)
{
oriImage.SetPixel(col, row, Color.FromArgb(colorRGB[0], colorRGB[1], colorRGB[2]));
zeroAdded++;
Console.WriteLine("Adding zero number: " + zeroAdded);
}
else
{
Console.WriteLine("Set Pixel");
oriImage.SetPixel(col, row, Color.FromArgb(colorRGB[0], colorRGB[1], colorRGB[2]));
}
if (zeroAdded == 8)
{
Console.WriteLine("Final Pixel Add");
oriImage.SetPixel(col, row, Color.FromArgb(colorRGB[0], colorRGB[1], colorRGB[2]));
return oriImage;
}
binaryCount++;
if (binaryCount % 8 == 0) { messageIndex--; Console.WriteLine("Message Index deducted"); }
}
}
return oriImage;
}
My embed implementation is the same to this example As for extraction I used the exact extraction code from the example. No matter what I tried, I am still only getting the first character of my embedded text. I tried checking my code by printing each operations and all of them fires without any issue which means the embed operation should be working as expected.
Just found my problem. Everything in my embed method should be in the R G B for loop.

C# Display loop iteration on single line in console

So im using a for loop to loop through all rows in an excel spreadsheet and i can display the current row number very easily by just using the "i" definition, however it prints on multiple lines since each iteraton displays with a Console.WriteLine() command.
What i would like is for it to only show it once, and have it display an updated iteration on one single line. Here is my current code:
void DeleteCells(string filePath)
{
int currRowNumber = 0;
// create excel-instance:
Application excel = new Application();
// open the concrete file:
Workbook excelWorkbook = excel.Workbooks.Open(#filePath);
// select worksheet. NOT zero-based!!:
_Worksheet excelWorkbookWorksheet = excelWorkbook.ActiveSheet;
if(isclosing)
{
closeProgram(excel, excelWorkbook);
}
int numRows = excelWorkbookWorksheet.UsedRange.Rows.Count;
Console.WriteLine("Number of rows: " + numRows);
Console.Write("Checking Row #: " + currRowNumber);
int numRowsDeleted = 0;
int nullCounter = 0;
//for (int j = 1; j <=)
for (int i = 1; i < numRows + 4; i++)
{
//We want to skip every row that is null and continue looping until we have more than 3 rows in a row that are null, then break
if (i > 1)
{
i -= 1;
}
//Create Worksheet Range
Microsoft.Office.Interop.Excel.Range range = (Microsoft.Office.Interop.Excel.Range)excelWorkbookWorksheet.Cells[i, 2];
string cellValue = Convert.ToString(range.Value);
if (nullCounter == 5)
{
Console.WriteLine("Null row detected...breaking");
Console.WriteLine("Number of rows deleted: " + numRowsDeleted);
break;
}
if (cellValue != null)
{
if (cellValue.Contains("MESSAGE NOT CONFIGURED"))
{
//Console.WriteLine("Deleting Row: " + Convert.ToString(cellValue));
((Range)excelWorkbookWorksheet.Rows[i]).Delete(XlDeleteShiftDirection.xlShiftUp);
numRowsDeleted++;
//Console.WriteLine("Number of rows deleted: " + numRowsDeleted);
nullCounter = 0;
i--;
currRowNumber++;
}
else
{
currRowNumber++;
nullCounter = 0;
}
}
else
{
nullCounter++;
//Console.WriteLine("NullCounter: " + nullCounter);
}
i++;
}
Console.WriteLine("Fixes Finished! Please check your excel file for correctness");
closeProgram(excel, excelWorkbook);
}
Sample output:
Row Number: 1
Row Number: 2
Row Number: 3
Row Number: 4
Row Number: 5
etc..
I want it to display only one line and continuously update the row number. How would i go about doing this? Any help is appreciated. Thanks.
UPDATE:
So i have the following loop:
for (int i = 1; i < numRows + 2; i++) //numRows was +4, now +2
{
Console.Clear();
Console.WriteLine("Number of rows: " + numRows);
Console.Write("Checking Row #: " + currRowNumber);
//We want to skip every row that is null and continue looping until we have more than 3 rows in a row that are null, then break
if (i > 1)
{
i -= 1;
}
//Create Worksheet Range
Microsoft.Office.Interop.Excel.Range range = (Microsoft.Office.Interop.Excel.Range)excelWorkbookWorksheet.Cells[i, 2];
string cellValue = Convert.ToString(range.Value);
if (nullCounter == 3) //was 5
{
Console.WriteLine("\nNull row detected...breaking");
Console.WriteLine("Number of rows deleted: " + numRowsDeleted);
break;
}
if (cellValue != null)
{
if (cellValue.Contains(searchText))
{
//Console.WriteLine("Deleting Row: " + Convert.ToString(cellValue));
((Range)excelWorkbookWorksheet.Rows[i]).Delete(XlDeleteShiftDirection.xlShiftUp);
numRowsDeleted++;
//Console.WriteLine("Number of rows deleted: " + numRowsDeleted);
nullCounter = 0;
i--;
currRowNumber++;
rowsPerSecond = i;
}
else
{
currRowNumber++;
nullCounter = 0;
}
}
else
{
nullCounter++;
//Console.WriteLine("NullCounter: " + nullCounter);
}
i++;
}
I want to calculate how many rows im looping through per second, then calculate from that number how long it will take to complete the entire loop, based on how many rows there are.
Again, any help is appreciated, thanks!
On each loop circle use the Clear() method before print output:
Console.Clear();
You could do this:
const int ConsoleWidth = 80;
for(int i = 0; i < 10; i++)
{
// pull cursor to the start of the line, delete it with spaces
// then pull it back again
for(int j = 0; j < ConsoleWidth; j++) Console.Write("\b");
for(int j = 0; j < ConsoleWidth; j++) Console.Write(" ");
for(int j = 0; j < ConsoleWidth; j++) Console.Write("\b");
Console.Write("Row Number: {0}", i);
}
If you do
Console.Write("Row Number: {0}", i);
It will keep appending in front of previous text.
If you do
Console.Clear();
Any message that you intend to write before this text will dissapear.
If you know the exact position of the text, you can try to modify the text in console at that position as:
// First time write
Console.WriteLine("Row Number: {0}", i);
// x,y coordinates in the method for later iterations
Console.SetCursorPosition(11, 0);
Console.Write(i);
If the amount of text in the row will never decrease (e.g. because the number only ever gets bigger) you can do this by using Console.Write() and prefixing the text with \r:
for (int i = 0; i < 100000; ++i)
Console.Write($"\rRow Number: {i}");
Console.WriteLine();
If the text decreases in length because the number gets smaller, you can use a formatting string to output the number left-justified with extra spaces which will overwrite the extra digits:
for (int i = 100000; i >= 0; --i)
Console.Write($"\rRow Number: {i, -6}");
Console.WriteLine();
Doing it this way has the advantage that you keep any previous text in the console and only update the single line. This also makes it a lot quicker compared to clearing the entire display every iteration.
try to use Console.SetCursorPosition before Console.Write
You can do as the previous answers suggested, here is another way.
int line = Console.CursorTop;
int len = new String("Row Number: ").length;
Console.WriteLine("Row Number: ");
for(your loop)
{
Console.WriteLine(i);
//Print whatever else you want!
Console.SetCursorPosition(len,line);
}
Advantage of this approach is that the position is remembered and you can come back to the same position after displaying any other information to the user, This is useful when updating a single character in a screen full of text!
To answer the next question, use
Stopwatch s = new Stopwatch();
long millis =0,avg;
for(int i=0;i<loopLength;i++)
{
s.Start();
//Do work
s.Stop();
millis += s.ElapsedMilliseconds;
avg = millis/(i+1);
Console.WriteLine("Time remaining :" + (TimeSpan.FromMilliseconds(avg*(loopLength - (i+1))).Seconds);
}

c# Loops with stars and spaces

I am currently breaking my head over this simple assignment for loops that I have to do.
Basically what I want to achieve is:
1) User gives imput how long the star pyramid should be
2) Make a pyramid with a for loop.
It needs to look something like this:
(If it needs to be 5 stories high; first row is 5 spaces 1 star; second row 4 spaces 2 stars and so on.
*
**
***
****
(Hard to format but you get my intention.)
I currently have this
public void Pyramid()
{
Console.WriteLine("Give the hight of the pyramid");
_aantal = Convert.ToInt32(Console.ReadLine());
for (int i = 1; i <= _aantal; i++) // loop for hight
{
for (int d = _aantal; d > 0; d--) // loop for spaces
{
Console.Write(_spatie);
}
for (int e = 0; e < i; e++) // loop for stars
{
Console.Write(_ster);
}
Console.WriteLine();
}
}
The output is always the inserted number amount of spaces and it is not decremented correctly.
Although if I debug it it counts down correctly.
Thank you for responding.
You could use the constructor of the string class to create the repetition for you, and then print both values at once, then you don't need the extra for loops
static void Main(string[] args)
{
int rowHeight = 5;
for (int row = 1; row <= rowHeight; row++)
{
string spaces = new string(' ', rowHeight - row);
string stars = new string('*', row);
Console.WriteLine("{0}{1}", spaces, stars);
}
Console.ReadLine();
}
UPDATE
for the semantics, i will then also show it with 2 for loops
static void Main(string[] args)
{
int rowHeight = 5;
for (int row = 1; row <= rowHeight; row++)
{
int totalSpaces = rowHeight - row;
for (int j = 0; j < totalSpaces; j++)
{
Console.Write(" ");
}
for (int j = 0; j < row; j++)
{
Console.Write("*");
}
Console.WriteLine();
}
Console.ReadLine();
}
well, your problem is
for (int d = _aantal; d > 0; d--) // loop for spaces
you really want
for (int d = _aantal - i ; d > 0; d--) // loop for spaces
but it really just mirrors what you currently have, and still doesn't create the pyramid look you seem to want.
I think the closest you'll get in a console app is by subtracting a space every other row:
for (int d = _aantal-i; d > 0; d-=2) // loop for spaces
which will give output:
Give the hight of the pyramid:
10
*
**
***
****
*****
******
*******
********
*********
**********
Got it !
static void Main(string[] args)
{
Console.WriteLine("Give the hight of the pyramid");
string _spatie = " ";
string _ster = "*";
int _aantal = Convert.ToInt32(Console.ReadLine());
for (int i = 1; i <= _aantal; i++) // loop for height
{
for (int d = i; d < _aantal; d++) // loop for spaces
{
Console.Write(_spatie);
}
for (int e = 1; e <= i; e++) // loop for stars
{
Console.Write(_ster);
}
Console.WriteLine();
}
Console.ReadKey();
}
Check this out..!! You were missing out the iterator 'i' of the height loop inside the spaces loop.
You will get the triangle :-
*
**
***
****
You will need odd number of stars always for a symmetrical pyramid.
I know you wanted to do this as a console app but if you adapt this code it should work fine
Replace textbox1/2 with Consle.Readline/Write
int pyramidstories = int.Parse(TextBox2.Text);
int I = 1;
while (I <= pyramidstories)
{
for (int spacecount = 0; spacecount < (pyramidstories - I); spacecount++)
{
TextBox1.Text += " ";
}
for (int starcount = 1; starcount < I + 1; starcount++)
{
TextBox1.Text += "*";
}
TextBox1.Text += Environment.NewLine;
I++;
}
As your question states you need:
4 spaces 1 star
3 spaces 2 stars
2 spaces 3 stars
etc..
so your pyramid should look something like
*
**
***
****
*****
The code sample above displays a pyramid as illustrated above
To get a pyramid (with proper spacing) like this:
You can use:
static void Main(string[] args)
{
// The length of the pyramid
int lengte = 18;
// Loop through the length as given by the user
for (int i = 0; i <= lengte; i++)
{
// If its an even number (we don't want 1-2-3.. but 1-3-5.. stars)
if (i % 2 == 0)
{
// Calculate the length of the spaces we need to set
int spatieLengte = (lengte / 2) - (i / 2);
// Display spaces
for (int spaties = 0; spaties <= spatieLengte; spaties++)
{
Console.Write(" ");
}
// Display stars
for (int sterren = 0; sterren <= i; sterren++)
{
Console.Write("*");
}
// Newline
Console.WriteLine();
}
}
Console.ReadLine();
}
Obviously the if block and spaceLengte variable aren't really needed. But I thought it would make it somewhat easier for OP to read.
Good luck / Succes ermee ;)

How can i check if the specific strings exist in a List<string> and if not to remove the indexs from the List?

I tried this but this is not working.
I'm getting index out of bound exception.
for (int x = 0; x < newText.Count; x++)
{
for (int y = 0; y < WordsList.words.Length; y++)
{
if (!newText[x].Contains(WordsList.words[y]))
{
for (int n = 0; n < 3; n++)
newText.RemoveAt(x);
}
}
}
newText is a List
words is string[]
newText format is like this:
index 0 = this is a text hello all
index 1 = time&date (6/14/2014....)
index 2 = empty ""
index 3 = text hello world
index 4 = time&date (6/14/2014....)
index 5 = empty ""
And so on...
What i want to do is to loop over newText and if in index 0 there no any word(string) from words then remove index 0,1,2 next itertion check index 3 for any words if not exist one word or more remove indexs 3,4,5.
If in index 0 or 3 there is one word or more then do nothing dont remove anything.
In the end newText should be in the same format as before:
index 0 text line
index 1 date&time
index 2 empty ""
Just the new newText content will be with text lines that contain one ore more strings from words.
EDIT
This is what i tried now:
First this is how i build the List:
List<string> t = filterNumbers(text);
for (int i = 0; i < t.Count; i++)
{
if (!newText.Contains(t[i]))
{
newText.Add(t[i]);
newText.Add(dateTime[i]);
newText.Add("");
}
}
Removing numbers and leave only text and add it.
In the end in this case i have in newText 150 indexs. That's 50 indexs of text lines.
Then i tried this:
int lastindex = newText.Count - 1;
for (int i = newText.Count - 1; i >= 0; i--)
{
for (int x = 0; x < WordsList.words.Length; x++)
{
if (!newText[i].Contains(WordsList.words[x]))
{
if (i != lastindex)
{
newText.RemoveAt(i + 1);
}
newText.RemoveAt(i);
}
}
}
But i'm getting exception on the line:
if (!newText[i].Contains(WordsList.words[x]))
Index was out of range. Must be non-negative and less than the size of the collection
EDIT
If I understood correctly that you wanted to check whether a specific line contains some words and if not remove that and the two following lines, here is a possible solution:
// start at the bottom in the first line "that matters" and go down by 3
for (int x = newText.Count - 3; x >= 0; x-=3)
{
// check if the line contains any of the words specified
if (!WordsList.words.Any(w => newText[x].Contains(w)) || newText[x] == "")
{
// remove the checked line as well as the next two if not
l.RemoveRange(x, 3);
}
}
EDIT
Corrected the predicate to:
!WordsList.words.Any(w => newText[x].Contains(w));
from
!WordsList.words.Any(w => newText.Contains(w));
EDIT 2
Added the empty string as possibility
The problem was that if the line to test was empty, it would pass the test because it does not contain any word from WordsList.words. The test now includes the empty string as an option and removes it when encountered.
Looking at your logic:
(1) for (int i = newText.Count - 1; i >= 0; i--)
{
(2) for (int x = 0; x < WordsList.words.Length; x++)
{
if (...)
{
(3) newText.RemoveAt(i);
}
}
}
You can see that even if you removed lines in (3), you continue loop in (2) which can try again remove line in (2) for new indexes, which now become out of bounds
you need to add break after (3) to continue loop (1)
// For each 3-word-sets
for (int x = 0; x < newText.Count; x += 3)
{
// For each word in that 3-word-set
for (int k = x; k < 3; k++)
{
// Check each word
bool breakOut = false;
for (int y = 0; y < WordsList.words.Length; y++)
{
if (!newText[k].Contains(WordsList.words[y]))
{
newText.RemoveAt(x+2);
newText.RemoveAt(x+1);
newText.RemoveAt(x);
x -= 3;
breakOut = true;
break;
}
}
if (breakOut) { break; }
}
}
I just wanted to test and experiment with your original code. Haven't tested this. Just make sure the list contains 3×n items.
Ok, it seems your data structure is really bad. Anyway if you have to keep the structure as is I think this can work :
var newList = new List<string>();
for (int index = 0; index < newText.Count; index = index + 3)
{
if (WordsList.Any(t => newText[index].ToLower().Trim().Contains(t.ToLower().Trim())))
{
newList.AddRange(newText.Skip(index).Take(3));
}
}
newText = newList;

Categories