This might be a hard question, or a stupidly simple one. Either way, bear with me, as I'm quite new to C#.
I've been building a Form with a ListBox inside, and a few other things, and all has been well. Where things get odd are in the filling of said box with information.
My logic to filling this ListBox thus far has been:
foreach (var value in userList)
{
listBoxForForm.Items.Add("#" + value.internalId + " \t\t-\t" + value.title + "\t\t-\t" + value.typeName);
}
(Don't mind the odd between the " and the \t!)
The problem is that this looks odd if certain values are too long (not "long" as in value.length but "long" as in width).
To better explain it, I took a screenshot (forgive the government-style censoring):
As you can see, the problem is that the text doesn't seem to format correctly when using \t in this context.
Is there a way I can format this text neatly in the intended 3-column style I'm going for here? Without knowing the length of the variables in each value, I mean?
You should try with String.PadLeft():
using System;
class Program {
static void Main()
{
string s = "cat".PadRight(10); string s2 = "poodle".PadRight(10);
Console.Write(s);
Console.WriteLine("feline");
Console.Write(s2);
Console.WriteLine("canine");
}
}
which will output:
cat feline
poodle canine
Rather than using tabs, you should use a String.PadRight(X) where X is the maximum length of the field. You will need to ensure that your X value is longer than the maximum length of the data, or clip the data to the maximum length to ensure that the columns line up.
I think what you are looking for is this.
String.PadRight and String.PadLeft Methods
Related
Hoping someone can help. I'm a very basic beginner in C#. I set myself the task of creating a console application where I enter a resource I need i.e Screw or screws into the console, hit enter and it retrieves all the junk from the list that contain that word, along with the amount of resources you would receive from the junk. So Type Writer would be 2 screws. It's for Fallout 76 so I can see what junk contains what resource.
However I'm having a few issues:
The console only returns one result for screw, even though there are multiple results. (How do I resolve this and receive multiple results? i.e Clip board and Toy Car)
How do I search and get results for partial matches i.e if I type scre or screws?
Is there a better way of creating a console application where you store values and a user searches for those values? I cannot find anything close to what I need scouring the internet.
Thank you for all the help.
using System;
using System.Collections.Generic;
class JunkList
{
public string Resource { get; set; }
public string Junk { get; set; }
public int Amount { get; set; }
public JunkList(string r, string j, int a)
{
this.Resource = r;
this.Junk = j;
this.Amount = a;
}
}
class Program
{
static void Main(string[] args)
{
string searchName;
List<JunkList> infoList = new List<JunkList>();
infoList.Add(new JunkList("Screw", "Type Writer", 2));
infoList.Add(new JunkList("Screw", "Clip Board", 1));
infoList.Add(new JunkList("Screw", "Toy Car", 3));
Console.Write("Which resource do you want to search for?? \n");
searchName = Console.ReadLine();
for (int i = 0; i < infoList.Count; i++)
{
if (string.Compare(searchName, infoList[i].Resource, true) == 0)
{
Console.Write("Resource : " + infoList[i].Resource + "\n");
Console.Write("Junk : " + infoList[i].Junk + "\n");
Console.Write("Resource Amount : " + infoList[i].Amount + "\n");
break;
}
}
Console.ReadKey();
}
}
The console only returns one result for screw, even though there are
multiple results. (How do I resolve this and receive multiple results?
i.e Clip board and Toy Car)
Your issue is that you're breaking after finding the very first result:
if (string.Compare(searchName, infoList[i].Resource, true) == 0)
{
Console.Write("Resource : " + infoList[i].Resource + "\n");
Console.Write("Junk : " + infoList[i].Junk + "\n");
Console.Write("Resource Amount : " + infoList[i].Amount + "\n");
break; // REMOVE THIS LINE
}
break means that you're exiting from your for loop, so you're actually exiting as soon as you find a result.
How do I search and get results for partial matches i.e if I type scre
or screws?
You can change your if condition from
if (string.Compare(searchName, infoList[i].Resource, true) == 0)
to something like
if (infoList[i].Resource.ToLowerInvariant().Contains(searchName.ToLowerInvariant()))
This checks if the inserted string is contained in one of the strings that you have in your list. The ToLowerInvariant is used to make the search case-insensitive.
Of course, this is not a fuzzy-search, so searching for screws won't lead to any result. Doing fuzzy searches is a little bit more complex and it's probably outside the scope of this question.
Is there a better way of creating a console application where you
store values and a user searches for those values? I cannot find
anything close to what I need scouring the internet.
Opinion-based questions are not meant for StackOverflow, and asking a better way to do something is one of those. I don't think you'll get an answer on this.
To make it a less subjective, I'm going to interpret your last question as "Is there a common software pattern or approach that is used for storing data objects that can then be easily searched?"
In that regard, you're describing features and capabilities that a database is really good at, specifically storing some table of data and providing a fast way to search (query) it using criteria that you define.
C# and the .NET frameworks offer some pretty in-depth and robust tools for leveraging databases and managing mappings between data classes like JunkList and database tables; these types of tools are called ORMs, or Object Relational Mappers, and you'll see reference to them scattered throughout Microsoft's documentation, especially Entity Framework.
When getting started, more complicated ORMs can get a bit overwhelming, so it's not a bad idea to start small. Check out some very simple ORMs that use something like SQLite, which just live in a file and require minimal dependencies (the act of calling the database actually can be enough to create it!).
You might take a look at https://github.com/praeclarum/sqlite-net , which is very easy to set up in a matter of minutes and start using with just the basics provided in its documentation.
The reason you only get one result back is because of the break statement. It cancels the for loop. Try removing it.
Try looking at the String.Contains() method.
I'm working in c# and wondering if it's possible to read back multiple variables and load into an array using Streamreader.Readline()?
Here's an example:
I have an array of different types being written using Streamwriter
foreach (Stuff stf in StuffArray)
{
sw.WriteLine(" " + stf.car+ " " + stf.carOwned + " " + stf.carLocation);
}
sw.Close();
It writes out a text line that looks like:
Magnum True Alabama
When I go to read it back the only option I have is to read the entire line with Streamreader.
I want to load it back like:
for (int i = 0; i < stfArray.Length; i++)
{
stfArray[i] = new stfArray(Readline spot 1, Readline spot 2, Readline spot3)
}
So I can put the stuff back into the array or a new array in the exact same way it was when I extracted it.
Thanks!
Read the line, parse it (say with string.Split) and then take the tokens that you've parse and rehydrate your variables.
You probably want to use a more sophisticated format that word, space, etc. (think of cars whose model name contains a space, or places like New York). Pick a separator that will not occur in your strings.
Or better still, pick a well known serialization format like XML or JSON.
Since you are creating string representation on your own, you are 100% sure about its format. Under any other occasion, you should consider something more robust, like serialization to XML and then writing it to a file.
In your situation I would recommend creating new collection of Stuff and add object, that lies in every line of your file, like:
List<Stuff> stuffItems = new List<Stuff>();
while(!streamReader.EndOfStream)
{
string[] line = streamReader.ReadLine().Split(' ');
stuffItems.Add(new Stuff(line[0], line[1], line[2]));
}
And now you can use this list however you want, for example overwrite old one calling ToArray method on list, etc.
But, again, I warn you about this approach: when you change your format, for example change delimiting character, you'd get exception :)
I have a listbox where I want to display a list of names and highscores from a character class. I use ListBox.Items.Add to add the following string for each character:
public String stringHighscore()
{
return name + "\t\t\t" + score.ToString();
}
The problem is that when the name exceeds a certain length, the score gets pushed to the right. The listbox looks like this (sorry, my rep doesn't allow me to post images yet):
(Link to the listbox image on tinypic)
I have thought this may be due to the "\t" but I am not sure. How can I solve this and properly align the scores? Would it be better if I used two listboxes, one for names and one for scores?
You can use String.PadRight method.
Returns a new string that left-aligns the characters in this string by
padding them with spaces on the right, for a specified total length.
Let's say you have 20 characters length for name as maximum
public String stringHighscore()
{
return name + name.PadRight(20 - name.Length) + "\t\t\t" + score.ToString();
}
If your name's length is 13, this will add 7 space characters. And that way, your all name's length will equal (20) at the end.
Look at this csharp-examples article :
Align String with Spaces.
For official reference, look Composite Formatting
Good luck!
Seems to me like you would be best off using a ListView rather than trying to manually align anything yourself. Usage is barley harder than working with simple list boxes, and all the configuration can be done in the IDE (I'm assuming you are using VisualStudio, or a similarly powerful IDE).
Say you have a ListView item called scoresListView. From the IDE you can set the View property to Details, which will cause the list to be rendered in columns of a given width with a heading at the top (I figure you would want "Name" and "Score"). The code to add a column looks something like this (I assume you have a using System.Windows.Forms clause at the top of your C# file for the sake of readability):
scoresListView.Columns.Add("Name", 200); // add the Names column of width 200 pixels
scoresListView.Columns.Add("Score", 200, HorizontalAlignment.Right); // add the Score column of width 200 pixels (Right Aligned for the sake of demonstration)
Adding items (a name/score pair) to the list view can be as simple as:
string myName = "abcdef"; // sample data
int myScore = 450;
scoresListView.Items.Add(new ListViewItem(new string[] { myName, myScore.ToString() } )); // add a record to the ListView
Sorry there isn't all that much explanation, hope this helps now or in the future - the ListView is a very useful control.
how do I get text to wrap from one acrofield to the next? I have an adobe pdf doc our client gave us. It has acro fields one atop another (all with the same name). They want the text to wrap from one to another when it reaches the end of the line. All the other examples I see out there do not deal with filling in acro fields that wrap. Please help!
// loop through disabilities and display them
foreach (var disability in formNature.Disabilities)
{
fields.SetField("EVALUATION", disability.PrimaryDisabilityName + "; ");
}
in theory this should loop through all the disabilities they had entered on the web form and display them one after another while text-wrapping when it reaches the end of each line. But instead it only displays one item one the field.
This isn't a complete answer unfortunately.
First, when you call SetField() you are erasing the current contents of the field and replacing it with your new value. When done in a loop only the last value will ever be stored then. What you need to do is loop through each value and concatenate them into one big string.
string buf = '';
foreach (var disability in formNature.Disabilities)
{
buf += disability.PrimaryDisabilityName + "; ";
}
buf = buf.Trim();
Second, the PDF standard to the best of my knowledge does not support chaining of fields for overflow which is what you are looking for. The only way that I know of to accomplish what you are trying is to actually measure the strings and compare them to the widths of the fields and truncate them as needed. To do this you will need to find the font used for the given field, create a BaseFont from it and use that to Measure the string. Then compare that with the field's rectangle and use only the characters that "fit" into that field. Repeat as needed.
That all said, I would really really recommend that you just edit the PDF and replace the multiple fields with one large field that supports multiple lines. Your life will be much, much easier.
I'm trying to work through the problems on projecteuler.net but I keep running into a couple of problems.
The first is a question of storing large quanities of elements in a List<t>. I keep getting OutOfMemoryException's when storing large quantities in the list.
Now I admit I might not be doing these things in the best way but, is there some way of defining how much memory the app can consume?
It usually crashes when I get abour 100,000,000 elements :S
Secondly, some of the questions require the addition of massive numbers. I use ulong data type where I think the number is going to get super big, but I still manage to wrap past the largest supported int and get into negative numbers.
Do you have any tips for working with incredibly large numbers?
Consider System.Numerics.BigInteger.
You need to use a large number class that uses some basic math principals to split these operations up. This implementation of a C# BigInteger library on CodePoject seems to be the most promising. The article has some good explanations of how operations with massive numbers work, as well.
Also see:
Big integers in C#
As far as Project Euler goes, you might be barking up the wrong tree if you are hitting OutOfMemory exceptions. From their website:
Each problem has been designed according to a "one-minute rule", which means that although it may take several hours to design a successful algorithm with more difficult problems, an efficient implementation will allow a solution to be obtained on a modestly powered computer in less than one minute.
As user Jakers said, if you're using Big Numbers, probably you're doing it wrong.
Of the ProjectEuler problems I've done, none have required big-number math so far.
Its more about finding the proper algorithm to avoid big-numbers.
Want hints? Post here, and we might have an interesting Euler-thread started.
I assume this is C#? F# has built in ways of handling both these problems (BigInt type and lazy sequences).
You can use both F# techniques from C#, if you like. The BigInt type is reasonably usable from other languages if you add a reference to the core F# assembly.
Lazy sequences are basically just syntax friendly enumerators. Putting 100,000,000 elements in a list isn't a great plan, so you should rethink your solutions to get around that. If you don't need to keep information around, throw it away! If it's cheaper to recompute it than store it, throw it away!
See the answers in this thread. You probably need to use one of the third-party big integer libraries/classes available or wait for C# 4.0 which will include a native BigInteger datatype.
As far as defining how much memory an app will use, you can check the available memory before performing an operation by using the MemoryFailPoint class.
This allows you to preallocate memory before doing the operation, so you can check if an operation will fail before running it.
string Add(string s1, string s2)
{
bool carry = false;
string result = string.Empty;
if (s1.Length < s2.Length)
s1 = s1.PadLeft(s2.Length, '0');
if(s2.Length < s1.Length)
s2 = s2.PadLeft(s1.Length, '0');
for(int i = s1.Length-1; i >= 0; i--)
{
var augend = Convert.ToInt64(s1.Substring(i,1));
var addend = Convert.ToInt64(s2.Substring(i,1));
var sum = augend + addend;
sum += (carry ? 1 : 0);
carry = false;
if(sum > 9)
{
carry = true;
sum -= 10;
}
result = sum.ToString() + result;
}
if(carry)
{
result = "1" + result;
}
return result;
}
I am not sure if it is a good way of handling it, but I use the following in my project.
I have a "double theRelevantNumber" variable and an "int PowerOfTen" for each item and in my relevant class I have a "int relevantDecimals" variable.
So... when large numbers is encountered they are handled like this:
First they are changed to x,yyy form. So if the number 123456,789 was inputed and the "powerOfTen" was 10, it would start like this:
theRelevantNumber = 123456,789
PowerOfTen = 10
The number was then: 123456,789*10^10
It is then changed to:
1,23456789*10^15
It is then rounded by the number of relevant decimals (for example 5) to 1,23456 and then saved along with "PowerOfTen = 15"
When adding or subracting numbers together, any number outside the relevant decimals are ignored. Meaning if you take:
1*10^15 + 1*10^10 it will change to 1,00001 if "relevantDecimals" is 5 but will not change at all if "relevantDecimals" are 4.
This method make you able to deal with numbers up doubleLimit*10^intLimit without any problem, and at least for OOP it is not that hard to keep track of.
You don't need to use BigInteger. You can do this even with string array of numbers.
class Solution
{
static void Main(String[] args)
{
int n = 5;
string[] unsorted = new string[6] { "3141592653589793238","1", "3", "5737362592653589793238", "3", "5" };
string[] result = SortStrings(n, unsorted);
foreach (string s in result)
Console.WriteLine(s);
Console.ReadLine();
}
static string[] SortStrings(int size, string[] arr)
{
Array.Sort(arr, (left, right) =>
{
if (left.Length != right.Length)
return left.Length - right.Length;
return left.CompareTo(right);
});
return arr;
}
}
If you want to work with incredibly large numbers look here...
MIKI Calculator
I am not a professional programmer i write for myself, sometimes, so sorry for unprofessional use of c# but the program works. I will be grateful for any advice and correction.
I use this calculator to generate 32-character passwords from numbers that are around 58 digits long.
Since the program adds numbers in the string format, you can perform calculations on numbers with the maximum length of the string variable. The program uses long lists for the calculation, so it is possible to calculate on larger numbers, possibly 18x the maximum capacity of the list.