|
A good point. Such easily pre-checkable conditions can be coded around, in a UI at least, so that the user can't make that stupid mistake.
|
|
|
|
|
Be careful with assumptions about what the user can and cannot do through the UI, especially if you work on the web.
The QA team at my company has specific instructions to enable all disabled buttons and controls using various means (on the web, it's pretty easy: Inspect Element. For Windows applications, a special app is needed). The main reason is to secure the app against users being malicious rather than stupid, though.
|
|
|
|
|
If the user bypasses having things disabled or manually submits invalid data, then a terse error message is fair enough. That's not normal usage, that's abuse, and the code should protect itself against such things. The example in the OP appears to be for something that can happen in normal usage when it shouldn't be able to, though.
|
|
|
|
|
Yes you can do that, but it will result in the 'stupid user' complaining about the execute button not being active. At least the way it's handled here offers the opportunity to explain why this won't work, and what is expected. Granted, it could be expressed ... differently
|
|
|
|
|
I just use a message box that says "Too late for sorry, earthling!" It should NEVER be seen by anyone but me, and so far <crossing wings> I have yet to hear about it
|
|
|
|
|
emajyn wrote: I have yet to hear about it
Perhaps because such a message screams to the user that you don't want to hear about it if it ever does happen.
At least add a unique guru meditation number or something to the message. That'll turn it into a whimisical way to deliver an obscure error. Might someday keep your management from loosing face to some customer with clout who happens to get that message.
We can program with only 1's, but if all you've got are zeros, you've got nothing.
|
|
|
|
|
Yes, I too once coded an error message under a condition that at that point I assumed was a foregone conclusion. It said sth along the lines of. "you should never see this error message. If you do, please contact <my name>"
Of course, that impossible condition did hit eventually, and I got a call from our customer.. Thankfully the software was still under testing at that point so it wasn't some clueless user, but a rather exhilarated tester...
|
|
|
|
|
precisely <chuckle> - but people who use software that6 still contains that as an error message know me well enough that calling me is the first thing they would do anyway
|
|
|
|
|
Agreed. Keep thinking your user is "stupid" and pretty soon you won't have any.
/ravi
|
|
|
|
|
What's the name of the validator app?
|
|
|
|
|
I called it "Rude XSD validator".
It was something I threw together in a hurry. The software we develop is serviced/administered by another company. We had a situation in which we needed to know if XML files provided by a third party were in accordance to a given XSD. The administrators were unable to figure it out and asked me to provide them with a tool...
So I quickly threw together a WinForms GUI in which one can load one XSD, easily choose one or more files, and validate them all.
In other words, a few people I knew a little and collaborated with would be my users. We have an informal tone, and nobody complained of anything.
|
|
|
|
|
public void WriteCode(ICodeContext ctx, ICodeFile file)
{
Programmer.BeMeanToUsersAsTheyAreStoopid(ctx, file, MeanLevel.Medium);
}
I think computer viruses should count as life. I think it says something about human nature that the only form of life we have created so far is purely destructive. We've created life in our own image.
Stephen Hawking
|
|
|
|
|
Ha Ha, Our in-house system was developed using Access 97 (Archaic) Every now and again it decides to tell me "Me.Dirty" in a debug message! (Maybe someone is trying to tell me something)
|
|
|
|
|
There is a great tool for working with images called "ImgBurn", it has more coded insults than any other application I've ever used.
It's more condescending than anything, like, hey, I've noticed you're doing it wrong, would you like me to do it right? (Yes, No)
It's also very good at it's job, and has saved me a TON of wasted disc, I highly recommend it.
|
|
|
|
|
I looked those up on Google, and found that those are quotes from movies. They can be turned off in the options dialog. I never noticed them before, and I use ImgBurn quite a bit.
Bob Dole The internet is a great way to get on the net.
2.0.82.7292 SP6a
|
|
|
|
|
We can strip leading and trailing spaces from a string….
int len = strlen((LPSTR)wName);
while( *((LPSTR)wName + len - 1) == ' ')
{
*((LPSTR)wName + len - 1) = '\0';
len = strlen((LPSTR)wName);
}
firstNonSpace=((LPSTR)wName);
while(*firstNonSpace != '\0' && isspace(*firstNonSpace))
{
++firstNonSpace;
}
len = strlen(firstNonSpace)+1;
strcpy((LPSTR)wName, firstNonSpace);
Or just call…
MSDN: “Removes all leading and trailing spaces from a string.”
PathRemoveBlanks(wName);
I need a 32 bit unsigned value just to hold the number of coding WTF I see in a day …
modified 28-Sep-12 10:08am.
|
|
|
|
|
You should probably add your context, as PathRemoveBlanks is a shell utility function, while most people here use dotnet where String.Trim would suffice.
|
|
|
|
|
I'm no good at Big O notation, but that's some kind of amortized N⁵, isn't it?
|
|
|
|
|
1. This code was COPIED to 3 different places - they didn't bother to make a function out of all of it. That is probably the worst error, because now if this 'new' code has bugs, you have to modify three places instead of one.
2. It 'excessively' calculates the length of the string. I think I am being kind here when I say that.
3. 'Familiarity' was my joke - there is already a function in Windows to do this.
I need a 32 bit unsigned value just to hold the number of coding WTF I see in a day …
|
|
|
|
|
Blake Miller wrote: if this 'new' code has bugs, you have to modify three places instead of one.
Or you can create a function with this code and replace the code in the other 3 (and modify just one).
|
|
|
|
|
Blake Miller wrote: 2. It 'excessively' calculates the length of the string.
And just as excessively casts wName to LPSTR.
|
|
|
|
|
Not sure if you are joking, or looking for a serious answer.
The code you posted makes WAY too many passes through the source string. If you're looking for maximum performance, you can get this down to just a single pass thusly:
LPSTR* nxt = wName;
while(*nxt && isspace(*nxt))
nxt++;
if (!*np) {
wName = '\0';
return wName;
}
LPSTR* start = nxt;
LPSTR* last_no_ws = nxt;
while(*nxt) {
if (!isspace(*nxt))
last_no_ws = nxt;
nxt++;
}
int len = (last_no_ws - start) + 1;
memmove(wName, start, len);
wName[len] = '\0';
return wName;
You could even save the 'memove' at the end by just modifying the wName string in place (add null after last_no_ws), then return the reference to 'start'.
|
|
|
|
|
This is great. I was just posting the orginal code because of the three reasons I listed. 1. Should be a function - REGARDLESS. 2 - It's inefficient on multiple levels. 3. MS already has the 'tried and true' function to call anyways.
I like to see that others do not consider what I posted to be optimal in ANY case, so that is comforting
I need a 32 bit unsigned value just to hold the number of coding WTF I see in a day …
|
|
|
|
|
Changes:
1. Clear defined end of first loop cutting trailing spaces
2. No undefined behavior of strcpy with overlapping memory areas
3. No unnecessary strlen calls
4. Unified way to test for whitespaces via isspace
5. No warnings because of signed/unsigned conflicts (int <-> unsigned int strlen(...))
LPSTR myStrTrim(LPSTR pszString)
{
LPSTR pszLastChar = pszString + strlen(pszString) - 1;
while (pszLastChar >= pszString && isspace(*pszLastChar))
*pszLastChar-- = '\0';
LPSTR pszFirstChar = pszString;
while(pszFirstChar < pszLastChar && isspace(*pszFirstChar))
++pszFirstChar;
memmove(pszString, pszFirstChar, pszLastChar-pszFirstChar+1);
return pszString;
}
|
|
|
|
|
One of the best languages for string manipulation is PowerBasic. You can use it to write 32 bit DLL's callable from other languages.
To trim leading spaces: LTRIM$(AnyStringVar)
To trim any character from left: LTRIM$(AnyStringVar, SomeCharacter)
To trim any of multiple characters from left: LTRIM$(AnyStringVar, ANY SomeCharacters)
To trim trailing edge spaces: RTRIM$(AnyStringVar)
To trim any trailing character: RTRIM$(AnyStringVar,SomeCharacter)
To trim any of multiple trailing characters: RTRIM$(AnyStringVar, ANY SomeCharacters)
Trim both leading and trailing spaces: TRIM$(AnyStringVar)
Trim any character leading or trailing: TRIM$(AnyStringVar, SomeCharacter)
Trim any of multiple characters leading and trailing: TRIM$(AnyStringvar, ANY SomeCharacters)
PowerBasic supports pointers too !
PowerBasic has many other powerful string functions (both ANSI and UNICODE) such as:
ACODE$ - Translate a Unicode string into an ANSI string.
BIN$ - Return a string with the binary (base 2) representation of a value.
BITS$ - Copies string contents without modification.
BUILD$ - Concatenate multiple strings with high efficiency.
CHOOSE$ - Return one of several values, based upon the value of an index.
CHR$ - Convert one or more character codes into ASCII character(s).
CHR$$ - Convert one or more character codes into Unicode character(s).
CHRBYTES - Determine the size of a single character in a string variable.
ChrToOem$ - Translates a string of ANSI/WIDE characters to OEM byte characters.
ChrToUtf8$ - Translates a string of ANSI/WIDE characters to UTF-8 byte characters.
CLIP$ - Deletes characters from a string.
CLSID$ - Return a 16-byte (128-bit) GUID string containing a CLSID.
CSET - Center a string within the space of another string or UDT.
CSET$ - Return a string containing a centered (padded) string.
DEC$ - Convert an integral value to a decimal string.
EXTRACT$ - Return up to the first occurrence of a specified character.
FORMAT$ - Return a string containing formatted numeric data.
GUID$ - Return a 16-byte (128-bit) Globally Unique Identifier GUID.
GUIDTXT$ - Return a 38-byte human-readable GUID/UUID string.
HEX$ - Hexadecimal (base 16) string representation of an argument.
INSTR - Search a string for the first occurrence of a character or string.
JOIN$ - Return a string consisting of all of the strings in a string array.
LCASE$ - Return a lowercase version of a string argument.
LEFT$ - Return the left-most n characters of a string.
LEN - Return the logical length of a variable, UDT, or Union.
LSET - Left-align a string within the space of another string or UDT.
LSET$ - Return a string containing a left-justified (padded) string.
MAX$ - Return the argument with the largest (maximum) value.
MCASE$ - Return a mixed case version of a string argument.
MID$ - Return a portion of a string.
MID$ - Replace characters in a string with characters from another string.
MIN$ - Return the argument with the smallest (minimum) value.
MKBYT$ - Convert a Byte value into a binary encoded string.
MKCUR$ - Convert a Currency value into a binary encoded string.
MKCUX$ - Convert an Extended Currency value into a binary encoded string.
MKD$ - Convert a Double-precision value into a binary encoded string.
MKDWD$ - Convert a Double-word value into a binary encoded string.
MKE$ - Convert an Extended-precision value into a binary encoded string.
MKI$ - Convert a integral value into a binary encoded string.
MKL$ - Convert a Long-integer value into a binary encoded string.
MKQ$ - Convert a Quad-integer value into a binary encoded string.
MKS$ - Convert a Single-precision value into a binary encoded string.
MKWRD$ - Convert a Word value into a binary encoded string.
NUL$ - Return a string containing a specified number of $NUL characters.
OCT$ - Return a string that is a octal (base 8) representation of a value.
OemToChr$ - Translates a byte string of OEM characters into ANSI/WIDE characters.
PARSE - Parse a string and extract all delimited fields into an array.
PARSE$ - Return a delimited field from a string expression.
PARSECOUNT - Return the count of delimited fields in a string expression.
PEEK$ - Returns consecutive 1-byte characters starting at a specific memory location.
PEEK$$ - Returns consecutive 2-byte wide characters starting at a specific memory location.
POKE$ - Store a sequence of bytes starting at a specific memory location.
POKE$$ - Store a sequence as 2-byte wide characters starting at a specific memory location.
PROGID$ - Return the alphanumeric PROGID string (text) of a given CLSID.
REGEXPR - Scan a string for a matching "wildcard" or regular expression.
REGREPL - Scan a "wildcard" match in a string with a new string.
REMAIN$ - Returns the portion of a string which follows the first occurrence of a character or group of characters.
REMOVE$ - Return a copy of a string with characters or strings removed.
REPEAT$ - Return a string consisting of multiple copies of a specified string.
REPLACE - Replace all occurrences of one string with another string.
RETAIN$ - Return a string with all non-specified characters removed.
RIGHT$ - Return the rightmost n characters of a string.
RSET - Right justify a string into the space of a string variable or UDT.
RSET$ - Return a string containing a right-justified (padded) string.
SHRINK$ - Shrinks a string to use a consistent single character delimiter.
SIZEOF - Return the total or physical length of any PowerBASIC variable.
SPACE$ - Return a string consisting of a specified number of spaces.
SPLIT - Splits a string into two parts.
STR$ - Return the string representation of a number in printable form.
STRDELETE$ - Delete a specified number of characters from a string expression.
STRING$ - Returns an ANSI string consisting of multiple copies of a specified character.
STRING$$ - Returns a WIDE string consisting of multiple copies of a specified character.
STRINSERT$ - Insert a string at a specified position within another string.
STRPTR - Return the address of the data held by a variable length string.
STRREVERSE$ - Reverse the contents of a string expression.
SWAP - Exchange the values of two strings, pointers, or pointer targets.
SWITCH$ - Return one item of a series based upon a True/False evaluation.
TAB$ - Return a string with TAB characters expanded with spaces.
TALLY - Count the number of occurrences of specified characters/strings.
UCASE$ - Return an all-uppercase (capitalized) version of a string.
UCODE$ - Translate an ANSI string into a Unicode string.
UNWRAP$ - Removes paired characters from the beginning and end of a string.
USING$ - Format string/numeric expressions using a mask string.
Utf8ToChr$ - Translates a byte string of OEM characters into ANSI/WIDE characters.
VERIFY - Determine if each character of a string is in another string.
WRAP$ - Adds paired characters to the beginning and end of a string.
PowerBasic string functions are fast, fast, fast. The compiler was written in assembler and the generated machine code is optimized for speed.
|
|
|
|