How do I use the switch statement? - c++

I am trying to understand the switch statement better. I don't need the code but kinda a walkthrough on how it would be done.
If someone enters a 7 digit phone number EG. 555-3333 but enters it as "jkl-deff" as it would correspodnd to the letters on the dial pad, how would I change the output back to numbers?
Would this work:
switch (Digit[num1])
case 'j,k,l':
num1 = 5;
break;
case 'd,e,f':
num1 = 3;
break;

To do that with a switch statement, you'd have to walk through the char array, switching on each character. Group all the chars that have the same number together.
Something like
switch (phoneChar[i])
case 'a':
case 'b':
case 'c':
newChar[i] = '2';
break;
That said, I'm not sure that switch case is the best way to do that. I don't know what would be the best off the top of my head, but something feels wrong about this :)
Edit
The i would be the index of the current character under consideration. You'll have a 7 (or 8 or 10 or 12 character string depending on formatting) for a phone number. You'd have to take each character at a time.. so phone[0] = 'j' in the above example.

I would not use a switch!
// A,B,C => 2; D,E,F => 3 etc.
static int convert[] = {2,2,2,3,3,3,4,4,4,5,5,5,6,6,6,7,7,7,7,8,8,8,9,9,9,9};
for(int loop =0 ;loop < Digit.size(); ++loop)
{
num = convert[Digit[loop] - 'a'];
// Thus the character 'a' gets mapped to position 0
// the character 'b' gets mapped to position 1 etc.
// num is then the character mapped into the covert[] array above.
}

You could probably do it like this:
if (islower(c)) { num=(c-'a')/3; num = 2 + (num==8) ? 7 : num; }
to convert a character to a phone pad digit. The num==8 part at the end handles the exra digit on the 9 key.
Altogether it would look like this:
char c = getNextCharacterSomehow();
int num = -1;
if (isdigit(c)) num = c-'0';
else if (islower(c)) { num=(c-'a')/3; num = 2 + (num==8) ? 7 : num; }
else if (isupper(c)) { num=(c-'A')/3; num = 2 + (num==8) ? 7 : num; }
Also, a note about the switch statement: The item that comes between the "case" and the ":" has to have the same type as the thing specified by the "switch()" portion. And that type must be a scalar, which excludes things like strings.

Related

my run-length encoding doesn't work with big numbers

I have a assingment were I need to code and decode txt files, for example: hello how are you? has to be coded as hel2o how are you? and aaaaaaaaaajkle as a10jkle.
while ( ! invoer.eof ( ) ) {
if (kar >= '0' && kar <= '9') {
counter = kar-48;
while (counter > 1){
uitvoer.put(vorigeKar);
counter--;
}
}else if (kar == '/'){
kar = invoer.get();
uitvoer.put(kar);
}else{
uitvoer.put(kar);
}
vorigeKar = kar;
kar = invoer.get ( );
}
but the problem I have is if need to decode a12bhr, the answer is aaaaaaaaaaaabhr but I can't seem to get the 12 as number without problems, I also can't use any strings or array's.
c++
I believe that you are making following mistake: imagine you give a32, then you read the character a and save it as vorigeKar (previous character, I am , Flemish so I understand Dutch :-) ).
Then you read 3, you understand that it is a number and you repeat vorigeKar three times, which leads to aaa. Then you read 2 and repeat vorigeKar two times, leading to aaaaa (five times, five equals 3 + 2).
You need to learn how to keep on reading numeric characters, and translate them into complete numbers (like 32, or 12 in your case).
Like #Dominique said in his answers, You're doing it wrong.
Let me tell you my logic, you can try it.
Pesudo Code + Logic:
Store word as a char array or string, so that it'll be easy to print at last
Loop{
Read - a //check if it's number by subtracting from '0'
Read - 1 //check if number = true. Store it in int res[] = res*10 + 1
//Also store the previous index in an index array(ie) index of char 'a' if you encounter a number first time.
Read - 2 //check if number = true. Store it in res = res*10 + 2
Read - b , h and so on till "space" character
If you encounter another number, then store it's previous character's index in index array and then store the number in a res[] array.
Now using index array you can get the index of your repeating character to be printed and print it for it's corresponding times which we have stored in the result array.
This goes for the second, third...etc:- numbers in your word till the end of the word
}
First, even though you say you can't use strings, you still need to know the basic principle behind how to turn a stream of digit characters into an integer.
Assuming the number is positive, here is a simple function that turns a series of digits into a number:
#include <iostream>
#include <cctype>
int runningTotal(char ch, int lastNum)
{
return lastNum * 10 + (ch -'0');
}
int main()
{
// As a test
char s[] = "a123b23cd1/";
int totalNumber = 0;
for (size_t i = 0; s[i] != '/'; ++i)
{
char digit = s[i]; // This is the character "read from the file"
if ( isdigit( digit) )
totalNumber = runningTotal(digit, totalNumber);
else
{
if ( totalNumber > 0 )
std::cout << totalNumber << "\n";
totalNumber = 0;
}
}
std::cout << totalNumber;
}
Output:
123
23
1
So what was done? The character array is the "file". I then loop for each character, building up the number. The runningTotal is a function that builds the integer from each digit character encountered. When a non-digit is found, we output that number and start the total from 0 again.
The code does not save the letter to "multiply" -- I leave that to you as homework. But the code above illustrates how to take digits and create the number from them. For using a file, you would simply replace the for loop with the reading of each character from the file.

Keeping the order of operations while doing a sequential calculation

I am spending my evening doing some programming problems from Kattis. There is one part of the problem 4 thought that I am stuck on.
Given a number, the program is supposed to return the operations (+, -, * or /) required between 4 fours to achieve that number.
For example, the input
9
would result in the output
4 + 4 + 4 / 4 = 9
My solution (not efficient, but simple) is to evaluate all possible ways to combine the operators above and see if any of the combinations achieve the wanted result.
To do this I have written the function seen below. It takes in an array of chars which are the operators to be evaluated (uo[3], could look like {+, /, *}), and the wanted result as an integer (expRes).
bool check(char uo[3], int expRes) {
int res = 4;
for(int oPos = 2; oPos >= 0; oPos--) {
switch (uo[oPos]) {
case '+' : res += 4; break;
case '-' : res -= 4; break;
case '*' : res *= 4; break;
case '/' : res /= 4; break;
}
}
return res == expRes;
}
I realized that this "sequential" approach comes with a problem: it doesn't follow the order of operations. If I was to call the function with
uo = {+, -, /}
and
expRes = 7 it would return false since 4 + 4 = 8, 8 - 4 = 4, 4 / 4 = 1.
The real answer is obviously true, since 4 + 4 - 4 / 4 = 7.
Can any of you think of a way to rewrite the function so that the evaluation follows the order of operations?
Thanks in advance!
Its an easy problem if you look at it.
You are restricted with four 4's and three operators in between, that is you already know your search space. So one solution is to generate the complete search space which is O(n^3) = 4^3 = 64 total equations, where n is the number of operators. Keep the answer to these solutions as a <key, value> pair so that look up to the input of test case is O(1).
Step wise you'd do.
Generate Complete Sequence and store them as key, value pairs
Take Input from test cases
Check if key exists, if yes print the sequence, else print that the sequence doesn't exist
Solution would take 64*1000 operations, which can easily be computed with in a second and would avoid Time Limit Exceeded Error that usually these competitions have
in Code form (most of it is incomplete):
// C++ Syntax
map<int, string> mp;
void generateAll() {
// generate all equations
}
void main () {
generateAll();
int n, t; scanf("%d", &t);
while (t--) {
scanf("%d", &n);
if ( mp.find(n) != mp.end() )
// equation exists to the input
else
// equation doesn't exist for the input
}
}

Reading variable length user input in C++

How do I read in a variable number of characters? The user can input a positive or negative number that is too big to be stored in an integer. I am then checking to make sure the char is a number and storing it in an array of ints (although that will probably be changed to a short since I only need to be able to store 0-9).
istream& operator>>(istream &in, LargeInt &l)
{
char x;
do
{
cin >> x;
int v = (int)x;
switch( v )
{
case 48: v = 0;
case 49: v = 1;
case 50: v = 2;
case 51: v = 3;
case 52: v = 4;
case 53: v = 5;
case 54: v = 6;
case 55: v = 7;
case 56: v = 8;
case 57: v = 9;
default: v=10 /* END INPUT */;
}
l.largeInt[ l.usedLength ] = v;
l.usedLength++;
//need to check array length and make bigger if needed
}
while( (x == 45) || ((x > 47) && (x < 57)) );
}
If you wish to read digits, you need to do it a character at a time. E.g.
char ch;
while (std::cin.get(ch) && ch >= '0' && ch <= '9') {
// You have a digit to process (maybe you want to push_back it into a vector)
}
Notice that you need to use ch - '0' to get the value of the digit because ch contains the character code rather than the value. In ASCII this means that '0' is in fact 48, '1' is 49 and so on (and 'A' is 65). The values may be different for different character encodings but the digits are guaranteed by the standard to be sequential, so that subtracting zero works.
Why not input a string, and then convert it to a number?
A few points. First of all, if you only need to store values from 0 to 9, you might as well store them in a char (which is just a small integer type in C++).
Second, you probably need to add a break; to the end of all the cases in your switch statement -- in C++, execution falls through from one case to the next without a break to stop it. Then again, you should probably just get rid of the switch statement entirely. You'd probably be better off using isdigit from <ctype.h>. Since char is a small integer type in C++, you can also do math on it, so you could just subtract '0' from each digit after verifying that it is a digit. Edit: contrary to the later edit, I would strongly advise against subtracting 48 from each digit. First of all, it's not guaranteed to work (and won't with some character sets -- even if you don't think your code will ever be used on an IBM mainframe, it's a poor habit). Second, it makes the intent much more apparent. I don't think there's a good reason to expect the reader to have memorized the ASCII table so they'll know that 48 is equivalent to '0'.
Finally, to deal with the problem you knew you had, you'll probably want to look up std::vector.

I asked this yesterday, after the input given I'm still having trouble implementing

I'm not sure how to fix this or what I did wrong, but whenever I enter in a value it just closes out the run prompt.
So, seems I do have a problem somewhere in my coding. Whenever I run the program and input a variable, it always returns the same answer.."The content at location 76 is 0."
On that note, someone told me that "I don't know, but I suspect that Program A incorrectly has a fixed address being branched to on instructions 10 and 11." - mctylr but I'm not sure how to fix that..
I'm trying to figure out how to incorporate this idea from R Samuel Klatchko.. I'm still not sure what I'm missing but I can't get it to work..
const int OP_LOAD = 3;
const int OP_STORE = 4;
const int OP_ADD = 5;
...
const int OP_LOCATION_MULTIPLIER = 100;
mem[0] = OP_LOAD * OP_LOCATION_MULTIPLIER + ...;
mem[1] = OP_ADD * OP_LOCATION_MULTIPLIER + ...;
operand = memory[ j ] % OP_LOCATION_MULTIPLIER;
operation = memory[ j ] / OP_LOCATION_MULTIPLIER;
I'm new to programming, I'm not the best, so I'm going for simplicity. Also this is an SML program. Anyway, this IS a homework assignment and I'm wanting a good grade on this. So I was looking for input and making sure this program will do what I'm hoping they are looking for. Anyway, here are the instructions: Write SML (Simpletron Machine language) programs to accomplish each of the following task:
A) Use a sentinel-controlled loop to read positive number s and compute and print their sum. Terminate input when a neg number is entered.
B) Use a counter-controlled loop to read seven numbers, some positive and some negative, and compute + print the avg.
C) Read a series of numbers, and determine and print the largest number. The first number read indicates how many numbers should be processed.
Without further a due, here is my program. All together.
int main()
{
const int READ = 10;
const int WRITE = 11;
const int LOAD = 20;
const int STORE = 21;
const int ADD = 30;
const int SUBTRACT = 31;
const int DIVIDE = 32;
const int MULTIPLY = 33;
const int BRANCH = 40;
const int BRANCHNEG = 41;
const int BRANCHZERO = 41;
const int HALT = 43;
int mem[100] = {0}; //Making it 100, since simpletron contains a 100 word mem.
int operation; //taking the rest of these variables straight out of the book seeing as how they were italisized.
int operand;
int accum = 0; // the special register is starting at 0
int j;
// This is for part a, it will take in positive variables in a sent-controlled loop and compute + print their sum. Variables from example in text.
memory [0] = 1010;
memory [01] = 2009;
memory [02] = 3008;
memory [03] = 2109;
memory [04] = 1109;
memory [05] = 4300;
memory [06] = 1009;
j = 0; //Makes the variable j start at 0.
while ( true )
{
operand = memory[ j ]%100; // Finds the op codes from the limit on the memory (100)
operation = memory[ j ]/100;
//using a switch loop to set up the loops for the cases
switch ( operation ){
case 10: //reads a variable into a word from loc. Enter in -1 to exit
cout <<"\n Input a positive variable: ";
cin >> memory[ operand ]; break;
case 11: // takes a word from location
cout << "\n\nThe content at location " << operand << "is " << memory[operand]; break;
case 20:// loads
accum = memory[ operand ]; break;
case 21: //stores
memory[ operand ] = accum; break;
case 30: //adds
accum += mem[operand]; break;
case 31: // subtracts
accum-= memory[ operand ]; break;
case 32: //divides
accum /=(memory[ operand ]); break;
case 33: // multiplies
accum*= memory [ operand ]; break;
case 40: // Branches to location
j = -1; break;
case 41: //branches if acc. is < 0
if (accum < 0)
j = 5;
break;
case 42: //branches if acc = 0
if (accum == 0)
j = 5;
break;
case 43: // Program ends
exit(0); break;
}
j++;
}
return 0;
}
So, seems I do have a problem
somewhere in my coding. Whenever I run
the program and input a variable, it
always returns the same answer.."The
content at location 76 is 0."
Look at what your program is doing:
memory [0] = 1010; /* Read from user and store at address 10 */
memory [01] = 2009; /* Read garbage into acc from address 9 */
memory [02] = 3008; /* Add whatever garbage is in address 8 into accumulator */
memory [03] = 2109; /* Store garbage from accumulator into address 9 */
memory [04] = 1109; /* Print the contents of address 9, which is garbage */
memory [05] = 4300; /* Stop */
memory [06] = 1009; /* Read from user and store in address 9 */
So... yeah. To debug something like this, you just need to print out all the pertinent variables of your program to see whether they're what you think they are. For example, in case 10 you could have done cout << "10: operand is " << operand << endl; and then in case 11 you could have done cout << "11: operand is " << operand << endl; and you would have seen right away that the operand was 10 in the first instruction, 9 in the second, and 8 in the 3rd.
If you want to guarantee that memory always starts with the value 0, write a for loop (you can change your declaration to do it but there are subtleties you'd need to learn):
for( int i = 0; i < sizeof(memory); ++i ) { memory[i] = 0; }
Here's working program that adds 2 values the user enters and prints the result:
memory [0] = 1009;
memory [1] = 1008;
memory [2] = 2009;
memory [3] = 3008;
memory [4] = 2109;
memory [5] = 1109;
memory [6] = 4300;
As I suggested yesterday in your original question. I believe you may have an error in case 10 and 11 hard coded to modify the "stack pointer" (j) to 5 if I'm reading your code correctly.
The case statements for switch (operation) don't match your opcode constants (e.g. READ = 10, BRANCH = 40). (This has been fixed in your example)
For debugging at least having a default statement in the switch to catch unknown operations is recommended to catch mistakes.
Added:
I'd also suggest printing the operation and operand as they are being executed, to help you follow the Simpletron's program execution.
You still have not fixed the usage of leading zeros of memory addresses. The C/C++ compiler interprets the leading zero as meaning octal (base 8) number system.
Your example code as posted does not even compile. Please edit and fix the variable name usage (hint: mixing mem and memory).
Code fixes removed.
The values in the switch statement are incorrect. The operation values will be 10, 11, 20, 21 etc. not 1, 2, 3 etc as you check for in your cases. Which means none of your code gets executed as you don't have cases for these numbers.
Good luck!

Caesar cipher in C++

To start off, I'm four weeks into a C++ course and I don't even know loops yet, so please speak baby talk?
Okay, so I'm supposed to read a twelve character string (plus NULL makes thirteen) from a file, and then shift the letters backwards three, and then print my results to screen and file. I'm okay with everything except the shifting letters. I don't want to write miles of code to take each character individually, subtract three, and re-assemble the string, but I'm not sure how to work with the whole string at once. Can someone recommend a really simple method of doing this?
If you are dealing with simple letters (A to Z or a to z), then you can assume that the internals codes are linear.
Letters are coded as numbers, between 0 and 127. A is coded as 65, B as 66, C as 67, Z as 90.
In order to shift letters, you just have to change the internal letter code as if it were a number, so basically just substracting 3 from the character. Beware of edge cases though, because substracting 3 to 'A' will give you '>' (code 62) and not 'X' (code 88). You can deal with them using "if" statements or the modulo operator ("%").
Here is an ASCII characters table to help you
Once you've loaded your string in, you can use the modulous operator to rotate while keeping within the confines of A-Z space.
I'd keep track of whether the letter was a capital to start with:
bool isCaps = ( letter >= 'A' ) && ( letter <= 'Z' );
if( isCaps )
letter -= 'A'-'a';
and then just do the cipher shift like this:
int shift = -3;
letter -= 'a'; // to make it a number from 0-25
letter = ( letter + shift + 26 ) % 26;
// add 26 in case the shift is negative
letter += 'a'; // back to ascii code
finally finish off with
if( isCaps )
letter += 'A'-'a';
so, putting all this together we get:
char *mystring; // ciphertext
int shift = -3; // ciphershift
for( char *letter = mystring; letter; ++letter )
{
bool isCaps = ( *letter >= 'A' ) && ( *letter <= 'Z' );
if( isCaps )
*letter -= 'A'-'a';
letter -= 'a';
letter = ( letter + shift + 26 ) % 26;
letter += 'a';
if( isCaps )
letter += 'A'-'a';
}
You're going to have to learn loops. They will allow you to repeat some code over the characters of a string, which is exactly what you need here. You'll keep an integer variable that will be your index into the string, and inside the loop do your letter-shifting on the character at that index and increment the index variable by one until you reach NULL.
Edit: If you're not expected to know about loops yet in your course, maybe they want you to do this:
string[0] -= 3; // this is short for "string[0] = string[0] - 3;"
string[1] -= 3;
string[2] -= 3;
...
It will only result in 12 lines of code rather than miles. You don't have to "reassemble" the string this way, you can just edit each character in-place. Then I bet after making you do that, they'll show you the fast way of doing it using loops.
Iterate over the characters with a for loop. And do what you want with the char*. Then put the new char back.
for(int i=0; i<12; i++){
string[i] = string[i] - 3;
}
Where string is your character array (string). There is a bit more involved if you want to make it periodic (I.E. have A wrap round to Z, but the above code should help you get started)
I'm a little unclear what you mean by "shift the letters backwards 3"?
Does that mean D ==> A?
If so, here's a simple loop.
(I didn't do reading from the file, or writing to the file... Thats your part)
#include <string.h>
int main(void)
{
char input[13] = "ABCDEFGHIJKL";
int i;
int len = strlen(input);
for(i=0; i<len; ++i)
{
input[i] = input[i]-3;
}
printf("%s", input); // OUTPUT is: ">?#ABCDEFGHI"
}