|
Why PIEBALD?
pie·bald adjective \ˈpī-ˌbȯld\ : spotted with two different colors (especially black and white)
1: composed of incongruous parts
It's an under-utilized word. And it begins with PIE. Yummy yummy pie. I particularly like the "composed of incongruous parts" part.
Why a cow?
It's not a cow; it's a bull.
Fine; why a bull then?
Because I couldn't find a cow.
Ooookay... why a bovine?
Because they're big, dumb, and slow-moving?
When I think of piebald animals, I think of Holstein cattle. Writing PIEBALD on a Holstein just seemed like a good idea at the time.
This particular bull (not actually a Holstein) was at the L.A. County Fair, and I was able to get a good side view. The cows were crammed together and/or lying down.
|
|
|
|
|
And in my head I always pronounce it PEE BALL DEE
|
|
|
|
|
... and I think of a pie that has no crust on top, such as a pumpkin pie or dutch apple.
I'm retired. There's a nap for that...
- Harvey
|
|
|
|
|
|
Ha!
I accidently ran into your post today and I realized that:
1. There are indeed a lot of articles on this "subject"
2. What a fool I was to write another one[^]. Now I see why it got such a low rating: it probably pissed off all those who were sick and tired of the subject.
3. My code is still significantly nicer than most (with the exception of OG's spoof which is just great and yes, my modesty is legendary)
Here it is to complete your compendium :
void spell (unsigned long long num, char* buffer)
{
if (num < 20)
{
const char *nums[] = {
"zero", "one", "two", "three", "four", "five", "six", "seven", "eight",
"nine", "ten", "eleven", "twelve", "thirteen", "fourteen", "fifteen",
"sixteen", "seventeen", "eighteen", "nineteen" };
strcat (buffer, nums[num]);
return;
}
int ilog = (int)log10 ((double)num);
unsigned long long exp = (unsigned long long) pow (10, ilog);
if (ilog < 2)
{
const char *tens[] = {
"twenty", "thirty", "forty", "fifty", "sixty", "seventy", "eighty", "ninety" };
strcat (buffer, tens[num / exp - 2]);
num %= exp;
if (num)
{
strcat (buffer, "-");
spell (num, buffer);
}
}
else if (ilog < 3)
{
spell (num / exp, buffer);
strcat (buffer, " hundred");
num %= exp;
if (num)
{
strcat (buffer, " ");
spell (num, buffer);
}
}
else
{
const char *thpows[] = { "thousand", "million", "billion", "trillion" };
int pwr = ilog / 3 - 1;
if (pwr >= _countof (thpows))
{
strcpy (buffer, "HUGE!!!");
return;
}
exp = (unsigned long long)pow (10, (pwr+1) * 3);
spell (num / exp, buffer);
strcat (buffer, " ");
strcat (buffer, thpows[pwr]);
num %= exp;
if (num)
{
strcat (buffer, " ");
spell (num, buffer);
}
}
}
Mircea
|
|
|
|
|
I always use a DataReader, never a DataAdapter or DataSet. In my opinion, DataAdapters, DataSets, and DataGrids were developed to allow Microsoft presenters to very quickly query, display, and update simple data and get an "oooh" from the crowd. They are fine for prototyping, but are not suitable for production enterprise applications. DataAdapters are very limited in what they can do and actually try to do too much -- e.g. optimistic concurrency[^].
The few times I've been lazy and used a DataAdapter in a real scenario, it bit me and I had to rework the code to use a DataReader instead.
Also, bear in mind that in ADO.net, all data access goes through a DataReader -- ExecuteScalar, ExecuteNonQuery, DataAdapter.Fill, and DataAdapter.Update all use ExecuteReader to perform the tasks.
ExecuteReader can be used to execute any SQL statement your database accepts -- queries, DML, and DDL. And, in some cases (SQL Server) you can pass a semi-colon delimited list of SQL Statements (though it doesn't report the results of non-queries the way I'd like ).
By using a DataReader you can reduce your application's memory footprint when you don't need to have all the records in memory at the same time. Or you can fill a collection of custom objects rather than a DataTable. Or you can fill a DataTable your own way and avoid the DataAdapter's overhead.
DataGrids and DataGridViews are rarely an appropriate control for displaying and editing data in real situations.
|
|
|
|
|
A bunch of years ago a colleague gave me a copy of a program that would automatically close a Windows Messenger window. I have since modified it to close the nagging windows from Avira:
#include <windows.h>
#include <stdio.h>
void
main
(
void
)
{
HWND hTemp ;
HWND hok ;
while ( 1 )
{
if ( ( hTemp = FindWindow ( NULL , "Notifier of Avira AntiVir Personal - Free Antivirus" ) ) != NULL )
{
SetActiveWindow ( hTemp ) ;
hok = FindWindowEx ( hTemp , NULL , NULL , "OK" ) ;
SendMessage ( hok , WM_LBUTTONDOWN , 0 , 0 ) ;
SendMessage ( hok , WM_LBUTTONUP , 0 , 0 ) ;
printf ( "." ) ;
}
Sleep ( 1000 ) ;
}
}
I compiled it and I have a Windows Scheduled Task run it when I log in. You can modify the code to suit your needs.
|
|
|
|
|
PIEBALD's general rule for code formatting (yes, there is one): Things that go together (e.g. parentheses, braces, brackets, etc.) should line up, either horizontally or vertically.
Addendum: Separators in lists "go together" with the list designators.
Ad nauseum: Be liberal in defining what qualifies as a "separator".
If what you have fits horizontally, so be it, but things are likely to get more complex as they develop so you should plan ahead to avoid having to reformat later.
Worrying about vertical space is for others, use as much as you like.
Don't choose a style simply because others deride yours; they can reformat if they like.
|
|
|
|
|
(I don't feel that this code is enough to warrant a full article.)
There are times when I need to produce a hash string of something -- a password or a file perhaps. .net contains providers for many common hash algorithms. Here is the code I use (if you don't trust SHA1, just use something else):
# region Heading
/**************************************************************************************************************/
/* */
/* LibStr.Hash.cs */
/* */
/* Produces a hash string */
/* */
/* This is free code, use it as you require. If you modify it please use your own namespace. */
/* */
/* If you like it or have suggestions for improvements please let me know at: PIEBALDconsult@aol.com */
/* */
/* Modification history: */
/* 2006-05-25 Sir John E. Boucher Added Hash */
/* 2009-08-01 Sir John E. Boucher Pulled from LibStr.cs */
/* */
/**************************************************************************************************************/
# endregion
namespace PIEBALD.Lib
{
public static partial class LibStr
{
private static readonly System.Security.Cryptography.HashAlgorithm defaultalgorithm =
new System.Security.Cryptography.SHA1Managed() ;
/**
<summary>
Produces a hash string from the provided string using SHA1
</summary>
<param name="Subject">
The string to hash
</param>
<returns>
The hash formatted as a hexdigits
</returns>
*/
public static string
Hash
(
string Subject
)
{
return ( Hash
(
System.Text.Encoding.Unicode.GetBytes ( Subject )
,
defaultalgorithm
) ) ;
}
/**
<summary>
Produces a hash string from the provided string using the provided algorithm
</summary>
<param name="Subject">
The string to hash
</param>
<param name="Algorithm">
The hash algorithm to use
</param>
<returns>
The hash formatted as a hexdigits
</returns>
*/
public static string
Hash
(
string Subject
,
System.Security.Cryptography.HashAlgorithm Algorithm
)
{
return ( Hash
(
System.Text.Encoding.Unicode.GetBytes ( Subject )
,
Algorithm
) ) ;
}
/**
<summary>
Produces a hash string from the provided array of bytes using SHA1
</summary>
<param name="Subject">
The array of bytes to hash
</param>
<returns>
The hash formatted as a hexdigits
</returns>
*/
public static string
Hash
(
byte[] Subject
)
{
return ( Hash
(
Subject
,
defaultalgorithm
) ) ;
}
/**
<summary>
Produces a hash string from the provided array of bytes using the provided algorithm
</summary>
<param name="Subject">
The array of bytes to hash
</param>
<param name="Algorithm">
The hash algorithm to use
</param>
<returns>
The hash formatted as a hexdigits
</returns>
*/
public static string
Hash
(
byte[] Subject
,
System.Security.Cryptography.HashAlgorithm Algorithm
)
{
System.Text.StringBuilder result =
new System.Text.StringBuilder ( Algorithm.OutputBlockSize ) ;
byte[] hash = Algorithm.ComputeHash ( Subject ) ;
for ( int i = 0 ; i < hash.Length ; i++ )
{
result.Append ( hash [ i ].ToString ( "X2" ) ) ;
}
return ( result.ToString() ) ;
}
}
}
|
|
|
|
|
(I don't feel that this code is enough to warrant a full article.)
Many times when writing a command-line/console application or utility, I desire different behavior when the input is a pipe or the output is redirected. For instance:
0) I may not be able to prompt for input or confirmation.
1) I may want to make the output more (or less) verbose.
It appears that .net does not make detecting such redirection easy. When I first butted up against this wall I searched and found an article by Dr. Gui which addressed using the Windows API function PeekConsoleInput to detect whether or not console input is a pipe. More recent searches have not turned up this article or any other.
Here then is my take on Dr. Gui's technique, with the ability to detect redirected output added:
# region Heading
/**************************************************************************************************************/
/* */
/* LibApi.IsPipe.cs */
/* */
/* IsPipe routine */
/* */
/* This is free code, use it as you require. If you modify it please use your own namespace. */
/* */
/* If you like it or have suggestions for improvements please let me know at: PIEBALDconsult@aol.com */
/* */
/* Modification history: */
/* 2003-11-24 Sir John E. Boucher Added IsPipe -- With thanks to Dr. Gui */
/* */
/**************************************************************************************************************/
# endregion
namespace PIEBALD.Lib
{
public static partial class LibApi
{
/**
<summary>
Standard I/O device numbers
</summary>
*/
public enum StdPort : uint
{
/**
<summary>
Standard input port
</summary>
*/
In = unchecked ( (uint) -10 )
,
/**
<summary>
Standard output port
</summary>
*/
Out = unchecked ( (uint) -11 )
,
/**
<summary>
Standard error port
</summary>
*/
Err = unchecked ( (uint) -12 )
} ;
/**************************************************************************************************************/
[System.Runtime.InteropServices.DllImportAttribute
(
"Kernel32"
,
SetLastError=true
,
EntryPoint="GetStdHandle"
)]
private static extern System.IntPtr
API_GetStdHandle
(
StdPort nStdHandle
) ;
[System.Runtime.InteropServices.DllImportAttribute
(
"Kernel32"
,
SetLastError=true
,
EntryPoint="PeekConsoleInput"
)]
private static extern bool
API_PeekConsoleInput
(
System.IntPtr hConsoleInput
,
System.IntPtr lpBuffer
,
uint nLength
,
out uint lpNumberOfEventsRead
) ;
[System.Runtime.InteropServices.DllImportAttribute
(
"Kernel32"
,
SetLastError=true
,
EntryPoint="WriteConsole"
)]
private static extern bool
API_WriteConsole
(
System.IntPtr hConsoleOutput
,
System.IntPtr lpBuffer
,
uint nNumberOfCharsToWrite
,
out uint lpNumberOfCharsWritten
,
System.IntPtr lpReserved
) ;
/**
<summary>
Test a standard I/O (console) port to determine whether or not it is a pipe (redirected)
</summary>
<remarks>
From a post by Dr. Gui
</remarks>
<param name="Port">
The port to test for pipeness
</param>
<returns>
Whether or not the port appears to be a pipe
</returns>
*/
public static bool
IsPipe
(
StdPort Port
)
{
bool result = false ;
uint junk ;
switch ( Port )
{
case StdPort.In :
{
result = !API_PeekConsoleInput
(
API_GetStdHandle ( Port )
,
System.IntPtr.Zero
,
0
,
out junk
) ;
break ;
}
case StdPort.Out :
case StdPort.Err :
{
result = !API_WriteConsole
(
API_GetStdHandle ( Port )
,
System.IntPtr.Zero
,
0
,
out junk
,
System.IntPtr.Zero
) ;
break ;
}
}
return ( result ) ;
}
/**************************************************************************************************************/
}
}
|
|
|
|
|
It's not difficult and more developers should learn to do it; it's a very useful tool to have.
When you install .net, the C# and VB.net compilers are installed as well (these are the same compilers that Visual Studio uses).
0. Open a DOS box; there are at least two ways to do this:
Start|Run cmd
Start|Programs|Accesories|Command prompt
Because I use a DOS box extensively I have it on my Quick launch toolbar
1. Determine which versions of the compiler you have:
C:\>dir /s /b "c:\windows\microsoft.net\framework\csc.exe
c:\windows\microsoft.net\framework\v1.1.4322\csc.exe
c:\windows\microsoft.net\framework\v2.0.50727\csc.exe
c:\windows\microsoft.net\framework\v3.5\csc.exe
C:\>dir /s /b "c:\windows\microsoft.net\framework\vbc.exe
c:\windows\microsoft.net\framework\v1.1.4322\vbc.exe
c:\windows\microsoft.net\framework\v2.0.50727\vbc.exe
c:\windows\microsoft.net\framework\v3.5\vbc.exe
C:\>
2. Execute the compiler of your choice, specifying your source code as a parameter:
C:\>c:\windows\microsoft.net\framework\v3.5\csc.exe Hello.cs
Microsoft (R) Visual C# 2008 Compiler version 3.5.30729.1
for Microsoft (R) .NET Framework version 3.5
Copyright (C) Microsoft Corporation. All rights reserved.
C:\>
3. Execute the program:
C:\>hello
Hello, world!
C:\>
4. If you do this frequently, you may want to write a BAT file to do this:
C:\>type csc.bat
@c:\windows\microsoft.net\framework\v3.5\csc.exe %*
C:\>
5. And/or add the compiler's directory to the Path environment variable
Start|Settings|Control panel|System|Advanced|Environment variables|System variables|Path|Edit
|
|
|
|
|
Text files generally contain several "lines" of text, separated by "linefeeds" (ASCII 10).
On some operating systems, the file will also contain "carriage returns" (ASCII 13).
The developers of the original C library decided that, for portability, the programmer shouldn't need to know the details.
So, in C you just specify '\n' and the operating system will add a '\r' if it chooses. Likewise, when reading a text file, if the file contains '\r\n', the '\r' will not be returned to the program.
And it was good.
But the designers of .net decided otherwise and think that the programmer should know the details, so we usually have to specify the '\r' or use System.Environment.NewLine which is supposed to aid portability (not that they expect .net to be ported), but which will do just the opposite in the end.
In theory, on a Windows system NewLine will equate to "\r\n" and on some other system it may be "\n" or "\r" or who knows what.
The problem, as I see it, is that this won't work on OpenVMS -- OpenVMS supports many types of files, including many types of text files.
On an OpenVMS system, you can have text files with "\r\n", "\n", or "\r" or with Fortran encoding, just about anything -- what will NewLine be set to on OpenVMS if .net gets ported to it? I suspect they will settle on "\n" and let the operating system figure it out -- just like in C.
|
|
|
|
|
Probably depends on how dynamic the newline functionality is in OpenVMS. Is it just something that is supported across the board, or is it a user setting? That is, does one go to the OpenVMS control panel (or whatever that OS has) and set the preferred newline character(s)? Or, do you just get files from various sources with various newlines and most of the OpenVMS software can support either newline? What about new files -- do they get a certain type of newline, or does it depend on the application? Then you've got to wonder if it supports mixed-mode line endings (that is, a single file with both \n and \r\n). I see a small chance that they'd modify the functionality of \n in mixed-mode line endings, but it seems unlikely otherwise. And the only reason I can think of that they'd modify \n would be so that it could match the line endings of nearby lines in a block of text. That just seems overly complicated though, so I'd guess they would stick with \n meaning \n and picking either \n or \r\n for Environment.Newline.
And then there's System.Text.RegularExpressions. I'm pretty sure newlines are (and must be) well defined in that assembly. If you set "." to recognize every character except newline, it will ignore only \n (i.e., it will pick up \r). And this is on Windows, where the standard newline is \r\n. Seems to me that they would want to keep \n unambiguous so that, at least, a regular expression written on one platform won't change when ported to another platform. By the way, here is a regular expression that recognizes newlines, in whatever form they may take (I use this little puppy quite often):
\r?\n
|
|
|
|
|
It's a per-file setting. I just did some experimenting to be sure I knew what I was talking about.
When I create a new text file, it has the attributes:
Record format: Variable length, maximum 255 bytes, longest 7 bytes
Record attributes: Carriage return carriage control
When reading it in "binary" mode I don't see \r or \n characters (I expected to see them). I believe the operating system (Record Management Services) stores the line length rather than inserting "special characters".
I can convert it to Stream_LF:
Record format: Stream_LF, maximum 255 bytes, longest 7 bytes
Record attributes: Carriage return carriage control
Then I see \n characters (as expected).
I can convert it to Stream_CR:
Record format: Stream_CR, maximum 0 bytes, longest 7 bytes
Record attributes: Carriage return carriage control
And again I don't see \r or \n characters (I expected to see \r).
When I read in "text" mode all have \n embedded.
When I FTP these to Windows, all have \r\n embedded.
The point is, what the program sees isn't necessarily what is written to disk.
All the program needs to know is that one line ends and another begins; the rest is just details.
But .net seems to want the program to know the details; this is a step backward.
|
|
|
|
|
This is a copy of a response I made in an article forum
Did you miss the "opinionated SOB" part?
I'm also a pedant with strong Theoretician[^] leanings.
The various terms defined within a discipline, software development for instance, are created to enable varied practioners from varied backgrounds to communicate clearly and unambiguously. Hence the terms must have clear and unambiguous meanings. Using terms to mean things other than that for which they are intended leads to ambiguity and confusion.
"Inherit", "derive", and "extend" are terms for the concept of a class having a base class whose members it will contain. A class may derive from a base class, it will inherit the members of that class, and it may extend that class.
The term for a class agreeing to fulfill the contract specified by an interface is "implement". If the definition of a class specifies that it will fulfill the contract of a given interface, it must implement all parts of that contract; it does not derive from the interface, it does not inherit anything from the interface, it does not extend the interface.
In Object Oriented Programming there are the concepts of IS_A and HAS_A; with interfaces we gain the concept of CAN_DO. Two totally unrelated classes that derive from very different base classes (such as Bird and Airplane) may both implement the IFly interface.
Derivation and inheritance specify a parent-child relationship; an interface can't have a class as a child, just as a dog can't have a cat as a child.
Also, interface implementation has nothing whatever to do with inheritance, claiming that it "simulates multiple-inheritance" diminishes the truly remarkable advance that interfaces represent.
modified 9-Feb-13 11:38am.
|
|
|
|
|
Haha, I'm glad I cyber stalked you and found this little gem. I have no interest in resurrecting this conversation, but thought I'd drop by and say "hi". By the way, I always wondered what piebald meant and I finally googled it and found a hit that makes sense... your profile piebald is quite nice.
|
|
|
|
|
I spent a lot of time trying to find the "best" way to clear a StringBuilder.
It turns out that, unlike a string, the Length property is not read-only.
Of course, Intellisense had been telling me that for years, I just hadn't noticed.
sb.Length = 0 ;
|
|
|
|
|
None of the three C# books I have give guidance on overloading the increment and decrement operators. MSDN doesn't seem to either.
The Microsoft and ECMA specifications merely say it's not like in C++:
"
Note that the operator returns the value produced by adding 1 to the operand, just like the postfix increment and decrement operators (§7.5.9), and the prefix increment and decrement operators (§7.6.5). Unlike in C++, this method need not, and, in fact, must not, modify the value of its operand directly.
"
and that's no help to me because I only dabbled in C++.
In my case, I expected it to be difficult, but because it is actually simple, it became difficult and confusing to me. The increment and decrement operators are different from the other operators, I expected the implementation to be different.
"Think our minds must be too highly trained, Majikthise." -- Vroomfondel
MSDN and mainstream books should explain how simple it is rather than expecting the reader to assume it is.
So here is what I think the documentation should say:
"
When overloading the increment and decrement operators, do not set the value; simply return the new value, the compiler will take care of setting the value and returning the new or old value as appropriate.
return ( x + 1 ) ;
return ( x = x + 1 ) ;
"
|
|
|
|
|