Converting integers to alphabetic characters - c++

I want to assign grades based on the test scores.
A for 90-100.
B for 80-89.
C for 70-79.
D for 60-69.
F for 0-59.
I know if you use switch or if..else statements, there will be no more than 5 statements but anyone has any better solution?
I used ASCII values to go about it but in terms of lines of code it's merely the same.
Here is the code:
Score/=10;
Score=min(9,Score);
Score=9-Score;
Score+=65;
if(Score<=68)
{
cout<<static_cast<char>(Score)<<endl;
}
else
{
cout<<"F"<<endl;
}

A standard approach in situations when the number of input choices is limited is to use a look-up table:
cout << "FFFFFFDCBAA"[Score/10];
Demo.
(from comments) could you please explain what's going on in the code?
String literal "FFFFFFDCBAA" is treated as a const char* pointer, which allows application of indexer [] operator. Score is divided by ten in integers, producing a number between 0 and 10, inclusive. Eleven characters in the string correspond to letter grades of "raw" score divided by ten.

Code length is a bad criteria =) I suggest you to use custom mapping functions (integer to char or string) or class with switch / if for many reasons.
If we will follow the OOP approach we can define a class Grade with constructor from integer Grade(int) with method toString() or toChar. It's better to incapsulate grade transformation logic inside class from client code - because in the future you can add different locales (for example we in Russia have no A-C grade system, we just have 1-5) - and load locale from config, for example in XML. Also you can predefine ranges statically in some container and run for-each to assign char representation, but its unefficient in terms of time and memory.
I think it's better solution write code for humans (except for such cases when performance or other criteria are important - but as far as I can see, it's not the case)

Related

Is there a way to restrict string manipulation e.g substring?

The problem is that I'm processing some UTF8 strings and I would like to design a class or a way to prevent string manipulations.
String manipulation is not desirable for strings of multibyte characters as splitting the string at a random position (which is measured in bytes) may split a character half way.
I have thought about using const std::string& but the user/developer can create a substring by calling std::substr.
Another way would be create a wrapper around const std::string& and expose only the string through getters.
Is this even possible?
Another way would be create a wrapper around const std::string& and expose only the string through getters.
You need a class wrapping a std::string or std::u8string, not a reference to one. The class then owns the string and its contents, basically just using it as a storage, and can provide an interface as you see fit to operate on unicode code points or characters instead of modifying the storage directly.
However, there is nothing in the standard library that will help you implement this. So a better approach would be to use a third party library that already does this for you. Operating on code points in a UTF-8 string is still reasonably simple and you can implement that part yourself, but if you want to operate on characters (in the sense of grapheme clusters or whatever else is suitable) implementation is going to be a project in itself.
I would use a wrapper where your external interface provides access to either code points, or to characters. So, foo.substr(3, 4) (for example) would skip the first 3 code points, and give you the next 4 code points. Alternatively, it would skip the first 3 characters, and give you the next 4 characters.
Either way, that would be independent of the number of bytes used to represent those code points or characters.
Quick aside on terminology for anybody unaccustomed to Unicode terminology: ISO 10646 is basically a long list of code points, each assigned a name and a number from 0 to (about) 220-1. UTF-8 encodes a code point number in a sequence of 1 to 4 bytes.
A character can consist of a (more or less) arbitrary number of code points. It will consist of a base character (e.g., a letter) followed by some number of combining diacritical marks. For example, à would normally be encoded as an a followed by a "combining grave accent" (U+0300).
The a and the U+0300 are each a code point. When encoded in UTF-8, the a would be encoded in a single byte and the U+0300 would be encoded in three bytes. So, it's one character composed of two code points encoded in 4 characters.
That's not quite all there is to characters (as opposed to code points) but it's sufficient for quite a few languages (especially, for the typical European languages like Spanish, German, French, and so on).
There are a fair number of other points that become non-trivial though. For example, German has a letter "ß". This is one character, but when you're doing string comparison, it should (at least normally) compare as equal to "ss". I believe there's been a move to change this but at least classically, it hasn't had an upper-case equivalent either, so both comparison and case conversion with it get just a little bit tricky.
And that's fairly mild compared to situations that arise in some of the more "exotic" languages. But it gives a general idea of the fact that yes, if you want to deal intelligently with Unicode strings, you basically have two choices: either have your code use ICU1 to do most of the real work, or else resign yourself to this being a multi-year project in itself.
1. In theory, you could use another suitable library--but in this case, I'm not aware of such a thing existing.

Two reason why zipcode should be stored as a string data type

In the textbook "Starting Out In C++" by Gaddis in chapter 1 the author says that some numbers like zip codes are intended for humans to read, to be printed out on the screen to look at and to not calculate with so they should be stored in string data type not numeric data types. But there is a couple of other reasons why this statement is true. The only other reason why I can think this would be true is if you were to enter a zip code with an ending like 37217-1221 you may have to use string catenation to only use the first five digits chopping of the characters after the -1221. What would be some other reasons for the statement "If a number is not going to be used in an arithmetic operation, store it in a string data type". Any answers would be greatly appreciated.
Zipcodes simply are not numeric data. As you point out, zipcodes can contain extensions, which numeric data does not represent. They can also contain significant leading zeros. Some postal code schemes can also contain letters.
Your questions was a bit...not of a questions? That's the best I can explain it. Anyway, a string is text and an integer or number is numerical and should only be used for calculations or counting. For example:
A zip code is a number but you will never do calculations with it. A zip code is something you reference as a place and has no counting purpose. If you think this could confuse you later on try to give the variable with the zip code an assignment of a String so that you cannot try to do any sort of math with the variable.

Recognize a specific string from a string array without iteration

I'm writing a derivative calculator in C++, and in order to properly perform the derivation operations, I need to parse the input equation at various character indexes along the equation's string.
I'm using isdigit() to parse out the numerical values from the equation and then store them into a separate string array, however now I need to parse out the mathematical symbols from the equation to identify which operation I need to perform.
Is there any way I can modify (overwrite?) isdigit() to recognize custom values from a string array? I'd like to avoid iteration to make my code a little less cluttered, since I'm already going to be using plenty of loops for the rest of this program and I want my code to be easy to follow. Does overwriting and inheritance in C++ work similarly to inheritance in Java (with the exception of multiple inheritance/interfaces)?
Please refrain from posting solutions that are irrelevant to the scope of this question, IE; different approaches to deriving equations in C++, as I've used this approach for some fairly specific reasons.
Thanks
You can use the new powerful C++11 regular expressions library that does almost what ever parsing you want. This way, you'll avoid iterations and code cluttering.
You can just use strchr. (Not everyone will like the macros here, but they do make combining character classes easy.)
#define OPERATOR "+-*/"
#define DIGIT "0123456789"
// Is c an operator
if (strchr(OPERATOR, c)) {
// Yes it is
}
or:
// Is c an operator or a digit?
if (strchr(OPERATOR DIGIT, c)) {
// Yup
}
Overriding and Inheritance works more or less the same as in Java.
You need to define a function as virtual and redefine it in derived class.
I know the "Please refrain from posting...", but I've written a library that does function parsing and derivation.
It is available at https://github.com/B3rn475/MathParseKit
I hope you can find some tips there.

Is this an acceptable use of "ASCII arithmetic"?

I've got a string value of the form 10123X123456 where 10 is the year, 123 is the day number within the year, and the rest is unique system-generated stuff. Under certain circumstances, I need to add 400 to the day number, so that the number above, for example, would become 10523X123456.
My first idea was to substring those three characters, convert them to an integer, add 400 to it, convert them back to a string and then call replace on the original string. That works.
But then it occurred to me that the only character I actually need to change is the third one, and that the original value would always be 0-3, so there would never be any "carrying" problems. It further occurred to me that the ASCII code points for the numbers are consecutive, so adding the number 4 to the character "0", for example, would result in "4", and so forth. So that's what I ended up doing.
My question is, is there any reason that won't always work? I generally avoid "ASCII arithmetic" on the grounds that it's not cross-platform or internationalization friendly. But it seems reasonable to assume that the code points for numbers will always be sequential, i.e., "4" will always be 1 more than "3". Anybody see any problem with this reasoning?
Here's the code.
string input = "10123X123456";
input[2] += 4;
//Output should be 10523X123456
From the C++ standard, section 2.2.3:
In both the source and execution basic character sets, the value of each character after 0 in the
above list of decimal digits shall be one greater than the value of the previous.
So yes, if you're guaranteed to never need a carry, you're good to go.
The C++ language definition requres that the code-point values of the numerals be consecutive. Therefore, ASCII Arithmetic is perfectly acceptable.
Always keep in mind that if this is generated by something that you do not entirely control (such as users and third-party system), that something can and will go wrong with it. (Check out Murphy's laws)
So I think you should at least put on some validations before doing so.
It sounds like altering the string as you describe is easier than parsing the number out in the first place. So if your algorithm works (and it certainly does what you describe), I wouldn't consider it premature optimization.
Of course, after you add 400, it's no longer a day number, so you couldn't apply this process recursively.
And, <obligatory Year 2100 warning>.
Very long time ago I saw some x86 processor instructions for ASCII and BCD.
Those are AAA (ASCII Adjust for Addition), AAS (subtraction), AAM (mult), AAD (div).
But even if you are not sure about target platform you can refer to specification of characters set you are using and I guess you'll find that first 127 characters of ASCII is always have the same meaning for all characters set (for unicode that is first characters page).

How do I handle combinations of behaviours?

I am considering the problem of validating real numbers of various formats, because this is very similar to a problem I am facing in design.
Real numbers may come in different combinations of formats, for example:
1. with/without sign at the front
2. with/without a decimal point (if no decimal point, then perhaps number of decimals can be agreed beforehand)
3. base 10 or base 16
We need to allow for each combination, so there are 2x2x2=8 combinations. You can see that the complexity increases exponentially with each new condition imposed.
In OO design, you would normally allocate a class for each number format (e.g. in this case, we have 8 classes), and each class would have a separate validation function. However, with each new condition, you have to double the number of classes required and it soon becomes a nightmare.
In procedural programming, you use 3 flags (i.e. has_sign, has_decimal_point and number_base) to identify the property of the real number you are validating. You have a single function for validation. In there, you would use the flags to control its behaviour.
// This is part of the validation function
if (has_sign)
check_sign();
for (int i = 0; i < len; i++)
{
if (has_decimal_point)
// Check if number[i] is '.' and do something if it is. If not, continue
if (number_base = BASE10)
// number[i] must be between 0-9
else if (number_base = BASE16)
// number[i] must be between 0-9, A-F
}
Again, the complexity soon gets out of hand as the function becomes cluttered with if statements and flags.
I am sure that you have come across design problems of this nature before - a number of independent differences which result in difference in behaviour. I would be very interested to hear how have you been able to implement a solution without making the code completely unmaintainable.
Would something like the bridge pattern have helped?
In OO design, you would normally
allocate a class for each number
format (e.g. in this case, we have 8
classes), and each class would have a
separate validation function.
No no no no no. At most, you'd have a type for representing Numeric Input (in case String doesn't make it); another one for Real Number (in most languages you'd pick a built-in type, but anyway); and a Parser class, which has the knowledge to take a Numeric Input and transform it into a Real Number.
To be more general, one difference of behaviour in and by itself doesn't automatically map to one class. It can just be a property inside a class. Most importantly, behaviours should be treated orthogonally.
If (imagining that you write your own parser) you may have a sign or not, a decimal point or not, and hex or not, you have three independent sources of complexity and it would be ok to find three pieces of code, somewhere, that treat one of these issues each; but it would not be ok to find, anywhere, 2^3 = 8 different pieces of code that treat the different combinations in an explicit way.
Imagine that add a new choice: suddenly, you remember that numbers might have an "e" (such as 2.34e10) and want to be able to support that. With the orthogonal strategy, you'll have one more independent source of complexity, the fourth one. With your strategy, the 8 cases would suddenly become 16! Clearly a no-no.
I don't know why you think that the OO solution would involve a class for each number pattern. My OO solution would be to use a regular expression class. And if I was being procedural, I would probably use the standard library strtod() function.
You're asking for a parser, use one:
http://www.pcre.org/
http://www.complang.org/ragel/
sscanf
boost::lexical_cast
and plenty of other alternatives...
Also: http://en.wikipedia.org/wiki/Parser_generator
Now how do I handle complexity for this kind of problems ? Well if I can, I reformulate.
In your case, using a parser generator (or regular expression) is using a DSL (Domain Specific Language), that is a language more suited to the problem you're dealing with.
Design pattern and OOP are useful, but definitely not the best solution to each and every problem.
Sorry but since i use vb, what i do is a base function then i combine a evaluator function
so ill fake code it out the way i have done it
function getrealnumber(number as int){ return getrealnumber(number.tostring) }
function getrealnumber(number as float){ return getrealnumber(number.tostring) }
function getrealnumber(number as double){ return getrealnumber(number.tostring) }
function getrealnumber(number as string){
if ishex(){ return evaluation()}
if issigned(){ return evaluation()}
if isdecimal(){ return evaluation()}
}
and so forth up to you to figure out how to do binary and octal
You don't kill a fly with a hammer.
I realy feel like using a Object-Oriented solution for your problem is an EXTREME overkill. Just because you can design Object-Oriented solution , doesn't mean you have to force such one to every problem you have.
From my experience , almost every time there is a difficulty in finding an OOD solution to a problem , It probably mean that OOD is not appropiate. OOD is just a tool , its not god itself. It should be used to solve large scale problems , and not problems such one you presented.
So to give you an actual answer (as someone mentioned above) : use regular expression , Every solution beyond that is just an overkill.
If you insist using an OOD solution.... Well , since all formats you presented are orthogonal to each other , I dont see any need to create a class for every possible combination. I would create a class for each format and pass my input through each , in that case the complexity will grow linearly.