C# String Concatenation OutOfRange error - c#

I'm utilizing Get String functions from a "Label" class to put together lines to print on a bitmap. The program compiles fine, and the previous form passes the LabelQueue properly (it would appear with no issue before I tried to print the bitmap). All the code of this particular initializer/constructor is below. The erroneous lines of code are the final three lines of the function before the "c++".
Let me know if you need me to add any more necessary code.
I'm getting an IndexOutofRange exception, claiming it was outside of the bounds of the array.
private LabelQueue lq;
public Print(LabelQueue queue)
{
InitializeComponent();
lq = queue;
pictureBox1.Image = new Bitmap(2550, 3300);
System.Drawing.Graphics formGraphics = this.CreateGraphics();
System.Drawing.Font textFont = new System.Drawing.Font("Times New Roman", 8);
System.Drawing.SolidBrush textBrush = new System.Drawing.SolidBrush(System.Drawing.Color.Black);
System.Drawing.StringFormat textFormat = new System.Drawing.StringFormat();
int x, y, c = 0;
while (c < 30)
{
// Get coordinates for where to put values.
x = ((c % 3) * 600) + 300;
// Accounts for column gap
if (c % 3 > 0)
x = x + ((c % 3) - 1) * 75;
y = ((c % 10) * 270) + 300;
string firstLine, secondLine, thirdLine;
firstLine = lq.labels[c].GetLastName() + ", " + lq.labels[c].GetFirstName() + " " + lq.labels[c].GetMiddleName();
secondLine = lq.labels[c].GetNewStreet();
thirdLine = lq.labels[c].GetNewCity() + ", " + lq.labels[c].GetNewState() + lq.labels[c].GetNewZIP() + lq.labels[c].GetNewCountry();
formGraphics.DrawString(firstLine, textFont, textBrush, x, y, textFormat); // Line turning up the error
formGraphics.DrawString(firstLine, textFont, textBrush, x, y + 10, textFormat); // Naturally, both these lines would need to be fixed too
formGraphics.DrawString(firstLine, textFont, textBrush, x, y + 20, textFormat);
c++;
}
}

Without a good, minimal, complete code example that reliably demonstrates the problem, it's impossible to know for sure the exact fix you need.
However, based on the information on this question and the comments so far, it appears that you simply aren't limiting your loop correctly. The while statement should look like this:
while (c < lq.Count())
Note that the above uses the Enumerable.Count() extension method. I chose that as the answer, because you didn't include the declaration/implementation of your LabelQueue object, so there's no way to know for sure what the correct syntax would be, but the extension method is likely to work because pretty much any reasonable collection type that supports an indexer will implement some interface that allows the Enumerable.Count() method to work well.
That said, your type probably has a Count property, which you can use instead of the Count() extension method. Either will work equally well.
Finally, for future reference it is fine to answer your own question. It's just that your answer should actually be an answer. I.e. it needs to explain clearly what was wrong, and what you did to fix it. Writing "Issue is fixed" doesn't count as an answer.
For that matter, if you don't like my answer here and you want to write your own, you can still do that. You can even accept your own answer instead of mine if you'd rather. Just make sure it's a real answer.

Related

A for loop somehow overrides an entire array, even though I can see no reason for that

So, been looking at this code for a good while now, and I am lost.
The point is to run a for loop that adds classes to an array, and then for each class runs through an array of points inside of that class, and add variations to it.
This then shows as a bunch of dots on a form, which are supposed to move independently of each other, but now follows each other completely.
It does not matter how much variation there is or anything, it's just 99 dots with the exact same acceleration, velocity, and location, and path.
The code is here, the method isn't touched by any other code, and the problem arises before it returns.
//Point of the method is to put variations of Baby into an array, and return that array
Dot.Class[] MutateAndListBaby(Dot.Class Baby)
{
//Making the empty array
Dot.Class[] BabyList = new Dot.Class[dots.Length];
//For loop that goes through through the whole array
for (int i = 1; i < BabyList.Length; i++)
{
//For each itteration the for loop adds the class reference to the index, then puts the standard directions into that reference, and then sets a value preventing it from being changed in another code
BabyList[i] = new Dot.Class();
BabyList[i].Directions = Baby.Directions;
BabyList[i].StartupComplete = true;
//The zero index variation when made like this, allows it to not be overriden, which would lead one to believe that how the directions are copied is he problem
//But it shouldn't be, BabyList[i].Directions = Baby.Directions; should be fire and forget, it should just add the Directions to the array and then leave it
BabyList[0] = new Dot.Class();
BabyList[0].Directions = new PointF[100];
for (int b = 0; b < BabyList[0].Directions.Length; b++)
{
BabyList[0].Directions[b] = new Point (5, 10);
}
BabyList[0].StartupComplete = true;
//The for loop that shuld add variation, but it seems like it somehow overrides it self, somehow
for (int b = 0; b < BabyList[i].Directions.Length; b++)
{
if (rand.Next(0, 101) >= 100)
{
int rando = rand.Next(-50, 51);
float mod = (float)rando / 50;
float x = BabyList[i].Directions[b].X;
x = x + mod;
BabyList[i].Directions[b].X = rand.Next(-5, 6);
}
if (rand.Next(0, 101) >= 100)
{
int rando = rand.Next(-50, 51);
float mod = (float)rando / 50;
float y = BabyList[i].Directions[b].Y;
y = y * mod;
BabyList[i].Directions[b].Y = rand.Next(-5, 6);
}
}
//Now one would assume this would create a unique dot that would move 100% independently right? Since it's at the end of the for loop, so nothin should change it
// Nope, somehow it makes every other dot copy its directions...
if (i == 5)
{
for (int b = 0; b < BabyList[5].Directions.Length; b++)
{
BabyList[5].Directions[b] = new PointF(-5f, -5f);
}
}
}
return BabyList;
}
}
}
With the code there, what I get is the 0 index dot going its own way, while the other 99 dots for some reason follow the 5th index's Directions, even though they should get their own variations later on in the code.
Any help would be much appreciated, it probarbly something obvious, but trust me, been looking at this thing for quite a while, can't see anything.
If I understand you correctly, this might be the issue:
BabyList[i].Directions = Baby.Directions;
Directions is of type array of PointF - a reference. The line above does not copy the array. Is that what you assume? If I'm not misreading the code you're presenting, you're creating one Dot.Class with its own array of PointF at index 0 and fill the rest of your Dot.Class array with instances that share one single array.
Directions is array, which is a reference type. When you're making assigment of a variable of this type
BabyList[i].Directions = Baby.Directions;
no new instance is created and reference us just being copied into new variable which still references original instance. Essentially in your loop only very first item gets a new instance of Directions as it's explicitly constructed. The rest share the instance which comes as a member of parameter passed to the method.
You probably want to change your if conditions:
(rand.Next(0, 101) >= 100
to
(rand.Next(0, 100) < 99
This will run an average of 99 times out of 100, whereas your current condition runs 1 out of 101 times (on average)
Oh, and Benjamin Podszun's answer about assigning the same array (not a copy of the same array) to Directions apply as well!
(Assuming that Directions isn't a getter that you created to return a copy of an array instead of a reference!)

Problems with EquationMgr & SelectionManger Solidworks Api C#

I'm trying to understand principles of solidworks API, but have several problems.
Here is my code:
for (var i = 0; i < selMgr.GetSelectedObjectCount(); i++)
{
var Face = selMgr.GetSelectedObject(i+1);
surfaces.Add(Face.GetSurface());
measure = swModel.Extension.CreateMeasure();
if (surfaces[i].IsCylinder())
{
// Problem # 1
Console.WriteLine("Cylinder " + i);
measure.Calculate(surfaces[i]);
var diameter = measure.Diameter * 1000;
var length = 1000 * measure.Perimeter / (measure.Diameter * Math.PI);
var temp = swApp.OpenDoc6(#"E:\OAK\Locator9.SLDPRT", 1, 1, "", 0, 0);
var part = component.AddComponent5(#"E:\OAK\Locator9.SLDPRT", 0, "", true, "", 0, 0, 0.3);
swApp.CloseDoc(#"E:\OAK\Locator9.SLDPRT");
ModelDoc2 locator = part.GetModelDoc();
var eqMgr = locator.GetEquationMgr();
Console.WriteLine("Evaluated diameter " + diameter);
Console.WriteLine("Evaluated length " + length);
Console.WriteLine(eqMgr.Equation[1] + " " + eqMgr.Equation[2]);
//Problem #2
eqMgr.set_Equation(1, $#"""D""={diameter}");
eqMgr.set_Equation(2, $#"""L""={length}");
eqMgr.EvaluateAll();
locator.EditRebuild3();
locator.ForceRebuild3(false);
}
else
{
// TODO: Handle other type of surface
}
}
1) I want to measure perimeter & diameter of the selected surface. But if a return value of GetSelectedObjectCount() method is greater than 1, measure.Diameter & measure.Perimeter both returns -1. And I kinda understand why, 'cause such operation isn't possible via UI as well, but can I do smth to solve the problem?
2) The code above has no influence on the equation of the inserted component, even if it writes it on the console.
Help please!
1 For primitive surfaces you can use *Params property of the ISurface object to get the information you need. For cylinder it would be CylinderParams. I can't find the link right now but I remember reading that measure shouldn't be used for any precise calculations as it is not guaranteed to be accurate at all times. If you don't care about precision and still want to use measure you can manually manipulate set of selected objects.
2 I haven't used IEquationMgr but in general I tried to stay away from VB styled parameterized properties like Equation , I'd suggest trying to Delete and then Add equation.

Need help for search optimization

I am fairly new to programming and i need some help with optimizing.
Basically a part of my method does:
for(int i = 0; i < Tiles.Length; i++)
{
x = Tiles[i].WorldPosition.x;
y = Tiles[i].WorldPosition.y;
z = Tiles[i].WorldPosition.z;
Tile topsearch = Array.Find(Tiles,
search => search.WorldPosition == Tiles[i].WorldPosition +
new Vector3Int(0,1,0));
if(topsearch.isEmpty)
{
// DoMyThing
}
}
So i am searching for a Tile in a position which is 1 unit above the current Tile.
My problem is that for the whole method it takes 0.1 secs which results in a small hick up..Without Array.Find the method is 0.01 secs.
I tried with a for loop also, but still not great result, because i need 3 more checks for
the bottom, left and right..
Can somebody help me out and point me a way of acquiring some fast results?
Maybe i should go with something like threading?
You could create a 3-dimensional array so that you can look up a tile at a specific location by just looking what's in Tiles[x, y + 1, z].
You can then iterate through your data in 2 loops: one to build up Tiles and one to do the checks you are doing in your code above, which would then just be:
for(int i = 0; i < Tiles.Length; i++)
{
Tile toFind = Tiles[Tile[i].x, Tile[i].y + 1, Tile[i].z];
if (toFind != null) ...
}
You would have to dimension the array so that you have 1 extra row in the y so that Tiles[x, y + 1, z] doesn't cause an index-out-of-range exception.
Adding to Roy's solution, if the space is not continuous, as it might be, you could put a hashcode of WorldPosition (the x, y and z coordinates) to some good use here.
I mean you could override WorldPosition's GetHashCode with your own implementation like that:
public class WorldPosition
{
public int X;
public int Y;
public int Z;
public override int GetHashCode()
{
int result = X.GetHashCode();
result = (result * 397) ^ Y.GetHashCode();
result = (result * 397) ^ Z.GetHashCode();
return result;
}
}
See Why is '397' used for ReSharper GetHashCode override? for explanation.
Then you can put your tiles in a Dictionary<WorldPosition, Tile>.
This would allow for quickly looking up for dict[new WorldPosition(x, y, z + 1)] etc. Dictionaries use hashcode for keys, so it would be fast.
First, like #Roy suggested, try storing the values in an array so you can access them with x,y,z coordinates,
Another thing you could do is change the search to
Tile topsearch = Array.Find(Tiles,
search => search.WorldPosition.x == Tiles[i].WorldPosition.x &&
search.WorldPosition.y == (Tiles[i].WorldPosition.y + 1) &&
search.WorldPosition.z == Tiles[i].WorldPosition.z)
This might be faster as well, depending on how many fields your WorldPosition has

Negating a variable shortcut

This maybe a trivial question but I couldn't find it so easily.
There are some shortcuts like
i = i + 1;
i++;
i = i+20;
i += 20;
But is there something to negate in place a variable?
MyClass.MyVeryLongSubClass.MoreStuff.MyBooleanHere = !MyClass.MyVeryLongSubClass.MoreStuff.MyBooleanHere;
Something like:
x ^= true;
It's a bit obscure though, which is why people generally don't use that.
A purely numeric (and not obscure) solution would be:
x *= -1;
UPDATE
Note also that the assignment operation yields a value and can be used within an expression.
instead of
x = -x;
y = 100 * x;
you can write
y = 100 * (x = -x);
or even
y = 100 * (x *= -1);
But I prefer the first version. The second and third are not easily understandable.

How To Use ZXing C# Port

NOTE: My original question was about whether the ZXing C# port is reliable, but here, I'm trying to figure out how to use it. Thus, they are not duplicates.
I'm trying to use the ZXing C# module, but I'm having trouble. Does anyone who has used ZXing before know how to do it correctly? Unfortunately, the C# documentation is quite small.
My current code is:
using com.google.zxing;
using com.google.zxing.client.j2se;
using com.google.zxing.common;
//...
Reader reader = new MultiFormatReader();
MonochromeBitmapSource image = new BufferedImageMonochromeBitmapSource(new Bitmap(Image.FromFile("barcode.jpg")),false);
Result result = reader.decode(image);
string text = result.getText();
sbyte[] rawbytes = result.getRawBytes();
BarcodeFormat format = result.getBarcodeFormat();
ResultPoint[] points = result.getResultPoints();
Console.WriteLine("barcode text: {0}", text);
Console.WriteLine("raw bytes: {0}", rawbytes);
Console.WriteLine("format: {0}", format);
Console.ReadLine();
I'm getting an exception on the line that starts with "Result result = ..." The ReaderException states: "Unable to cast object of type 'com.google.zxing.oned.MultiFormatOneDReader' to type 'com.google.zxing.Reader'.
So, what am I doing wrong?
UPDATE: I'm going to try the suggested ideas, but in the meantime, I found this issue in the ZXing group.
This is a sample to generate a QRCode.
QRCodeWriter writer = new QRCodeWriter();
com.google.zxing.common.ByteMatrix matrix;
int size = 180;
matrix = writer.encode("MECARD:N:Owen,Sean;ADR:76 9th Avenue, 4th Floor, New York, NY 10011;TEL:+12125551212;EMAIL:srowen#example.com;; ", BarcodeFormat.QR_CODE, size, size, null);
Bitmap img = new Bitmap(size, size);
Color Color = Color.FromArgb(0, 0, 0);
for (int y = 0; y < matrix.Height; ++y)
{
for (int x = 0; x < matrix.Width; ++x)
{
Color pixelColor = img.GetPixel(x, y);
//Find the colour of the dot
if (matrix.get_Renamed(x, y) == -1)
{
img.SetPixel(x, y, Color.White );
}
else
{
img.SetPixel(x, y, Color.Black);
}
}
}
img.Save(#"c:\test.bmp",ImageFormat.Bmp);
See the Barcode format at http://code.google.com/p/zxing/wiki/BarcodeContents
I think that must be a deficiency in the port, since in the original Java these classes are cast-compatible. Perhaps just use MultiFormatOneDReader as the reference type in the code rather than Reader, though the line should have been fine as-is. If you otherwise fix the source and want to submit the change let us (the project) know.
I suspect you are just missing a cast/are using the wrong type, try changing
Result result = reader.decode(image);
line in to one of the following
Result result = (Result)reader.decode(image);
or possibly
MultiFormatOneDResult result = reader.decode(image);
I'm afraid I don't have access to a c# compiler right now, so I can't verify this - so I apologise if I'm way off the mark!

Categories

Resources