building a phone keypad to transform digits into character

For example, if you type 2,it will output a, 22for b,etc.
1 is for pause ,and 0 is a space.
And the program should read a sequence of non-empty keystrokes for example
4455666102288

I know my coding has huge problem. Please help ! Thanks

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
  #include <iostream>
using namespace std;
int main(){
	int n[17];
	char c[17];
	int i;
	cout<<"Please enter the message: ";
	for (i=0;i<17;i++){
		cin>>n[i];

		switch(n[i]){
		
		case'0':
			c[i]=' ';
			break;
		case'1':
			break;
		case'2':
			c[i]='A';
			break;
        case'22':
			c[i]='B';
			break;
		case'222':
			c[i]='C';
			break;
		case'3':
			c[i]='D';
			break;
		case'33':
			c[i]='E';
			break;
		case'333':
			c[i]='F';
			break;
		case'4':
			c[i]='G';
			break;
		case'44':
			c[i]='H';
			break;
		case'444':
			c[i]='I';
			break;
		case'5':
			c[i]='J';
			break;
        case'55':
			c[i]='K';
			break;
		case'555':
			c[i]='L';
			break;
		case'6':
			c[i]='M';
			break;
		case'66':
			c[i]='N';
			break;
		case'666':
			c[i]='O';
			break;
		case'7':
			c[i]='P';
			break;
		case'77':
			c[i]='Q';
			break;
		case'777':
			c[i]='R';
			break;
		case'7777':
			c[i]='S';
			break;
		case'8':
			c[i]='T';
			break;
		case'88':
			c[i]='U';
			break;
		case'888':
			c[i]='V';
			break;
        case'9':
			c[i]='W';
			break;
		case'99':
			c[i]='X';
			break;
		case'999':
			c[i]='Y';
			break;
		case'9999':
			c[i]='Z';
			break;
		}

		}
		cout<<"Output message: ";
		for(int x=0;x<17;x++)
			cout<<c[x];
		

return 0;
}
case'9999': Compiler should scream at you for whis, spewing warnings everywhere.

c is an aray of characters. A single chracter. You cannot stuff two characters in single variable.

'22' is not a char. It would be an error if not for multicharacter literals, which have virtually no use, are actually ints and any compiler should warn about their use.

YOu should drop the switch here and parse string completely differently.
Thanks! BTW there's actually no runtime or syntax error of my coding ,but the output is some awkward signs.

Actually i dun know how to use string to complete the task, should I use string type for both my input (i.e. those numbers) and output (those english characters)? If so , how could I split the string into separate group of number(e.g. 41443330667 --> 4 1 33 444 0 66 7) and transform them into the english character without using switch?

I'm new to C++ with very limited knowledge , please help ! Once again, tks!
Last edited on
syntax error of my coding
Those are not errors, as this syntax is allowed by standard for compatibility reasons. However it should emit a warning, or you do not have your compiler configured properly.

how could I split the string into separate group of number
Iterate over a string, as soon as you hit a different digit, extract what you have read to another substring.

transform them into the english character without using switch?
Cascade of ifs:
1
2
3
4
5
if (substring = "2")
  ///...
else if (substring = "22")
  //...
//... 
Or a map:
1
2
std::map<std::string, char> characters { {"2", 'A'}, {"22", 'B'}, /*...*/};
std::cout << characters["22"]; //Outputs B 
SORRY I'm so stupid I still don't know how to split the string,could u please give me examples on how should write the code for that part?

Now it outputs nothing. BTW i just searched the usage of map so i dun know if i use it right...

The amended version of code:

#include <iostream>
#include<map>
#include<string>;
using namespace std;
int main(){
string n;

map<string,char>character;{
character["2"]='A';
character["22"]='B';
character["222"]='C';
character["3"]='D';
character["33"]='E';
character["333"]='F';
character["4"]='G';
character["44"]='H';
character["444"]='I';
character["5"]='J';
character["55"]='K';
character["555"]='L';
character["6"]='M';
character["66"]='N';
character["666"]='O';
character["7"]='P';
character["77"]='Q';
character["777"]='R';
character["7777"]='S';
character["8"]='T';
character["88"]='U';
character["888"]='V';
character["9"]='W';
character["99"]='X';
character["999"]='Y';
character["999"]='Z';
character["0"]=' ';
}
cout<<"Please enter the message: ";
cin>>n;


cout<<"Output message: "<<character[n];



return 0;
}
Last edited on
Possible implementation:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
#include <algorithm>
#include <iostream>
#include <map>
#include <string>
#include <vector>

std::vector<std::string> separate(const std::string& input)
{
    std::vector<std::string> parts;
    auto prev = input.begin();
    do {
        //http://en.cppreference.com/w/cpp/algorithm/adjacent_find
        auto it = std::adjacent_find(prev, input.end(), std::not_equal_to<>());
        if(it != input.end()) ++it;
        parts.emplace_back(prev, it);
        prev = it;
    } while (prev != input.end());
    return parts;
}

std::string decypher(const std::string& input)
{
    static const std::map<std::string, char> chars {
        {"2", 'A'}, {"22", 'B'}, {"222", 'C'}, {"3", 'D'}, {"33", 'E'}, {"333", 'F'}, {"0", ' '},
        {"4", 'G'}, {"44", 'H'}, {"444", 'I'}, {"5", 'J'}, {"55", 'K'}, {"555", 'L'},
        {"6", 'M'}, {"66", 'N'}, {"666", 'O'}, {"7", 'P'}, {"77", 'Q'}, {"777", 'R'}, {"7777", 'S'},
        {"8", 'T'}, {"88", 'U'}, {"888", 'V'}, {"9", 'W'}, {"99", 'X'}, {"999", 'Y'}, {"9999", 'Z'},
    };
    std::string result;
    for(const auto& str: separate(input))
        if(chars.find(str) != chars.end())
            result += chars.at(str);
    return result;
}


int main()
{
    std::cout << decypher("44335551555666096667775553") << '\n';
}
HELLO WORLD
http://coliru.stacked-crooked.com/a/1f7f3a41328fe838
Implementing look-ahead with std::cin.peek() http://en.cppreference.com/w/cpp/io/basic_istream/peek
would perhaps be the simplest way to write this.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
#include <iostream>
#include <string>
#include <cctype>

int main()
{
    std::cout << "? " ;
    char current_char ;

    // set up our lookup table
    const std::string possible_chars[] = {  "-", " ", "ABC", "DEF", "GHI", "JKL", "MNO", "PQRS", "TUV", "WXYZ"  } ;

    std::string message ;

    while( std::cin.get(current_char) && current_char != '\n' ) // '\n' is end of input
    {
        if( !std::isdigit(current_char) )
        {
            std::cerr << "error: non-numeric input '" << current_char << "'\n" ;
            return 1 ;
        }

        const std::string& possibilities = possible_chars[ current_char - '0' ] ; // '2' - '0' == 2 etc.
        std::size_t repeats = 0 ;
        while( ( repeats < possibilities.size() - 1 ) && std::cin.peek() == current_char )
        {
            ++repeats ; // repeated character; increment repeat count
            std::cin.get() ; // extract it and discard it note: peek() did not extract it
        }

        message += possibilities[repeats] ; // append character to message
    }

    std::cout << "output message: '" << message << "'\n" ;
}

http://coliru.stacked-crooked.com/a/d3e8028069f95213
Thank you for you two's kind help, but can't really understand your coding sorry. I've fixed my
codes but now it triggers a run-time error and I dun even know why. Could u please check for me ?

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
#include <iostream>
#include<map>
#include<string>
#include<vector>
using namespace std;
int main(){
	string n;
	vector<string> o;
	int i,x(0);
	
	
	map<string,char>character;{
		character["2"]='A';
		character["22"]='B';
		character["222"]='C';
		character["3"]='D';
		character["33"]='E';
		character["333"]='F';
		character["4"]='G';
		character["44"]='H';
		character["444"]='I';
		character["5"]='J';
		character["55"]='K';
		character["555"]='L';
		character["6"]='M';
		character["66"]='N';
		character["666"]='O';
		character["7"]='P';
		character["77"]='Q';
		character["777"]='R';
		character["7777"]='S';
		character["8"]='T';
		character["88"]='U';
		character["888"]='V';
		character["9"]='W';
		character["99"]='X';
		character["999"]='Y';
		character["9999"]='Z';
		character["0"]=' ';
		
	}
	cout<<"Please enter the message: ";
    
	cin>>n;
	 	for(i=0;i<17;i++){

			if(n.at(i)==n.at(i+1)){
				o[x]=n.at(i)+n.at(i+1);				
			}
			else 
				x++;
			o[x]=n.at(i);

		}


	for(x=0;x<o.size();x++){	
		cout<<"Output message: "<<character[o[x]]<<endl;}
	cout<<"Count: "<<o.size()<<endl;
	
          
		

return 0;
}
o[x]=n.at(i)+n.at(i+1); o is empty right now, so o[anything] is illegal.

for(i=0;i<17;i++){ Why 17? What if string is shorter that than or longer?

character[o[x]] What if there no such element in map?
o[x]=n.at(i)+n.at(i+1); I've used push_back instead but still can't run and it popped up "Standard C++ Libraries Out of Range" && 0

for(i=0;i<17;i++) Actually it's an assignment and the instructions states that the maximum input digit is 17

character[o[x]] I haven't come up a solution for this....
Look at this: n.at(i+1); What if i is 16? You will try to access n[17] which is outside of string of 17 symbols range;

instructions states that the maximum input digit is 17
Somebody can enter 3 digits and it would fit in assigment requirement. Write input size independend code when it does not cost you anything. You can slap input size check later.

I haven't come up a solution for this
Look at my code lines 31-32. It adds character into output string only if they are in the map.


Try to understand JLBorges solution. It is the most efficient one, and it can be adapted to work with strings too (or you could just wrap string in stringstream)
I have fixed my codes and have everything right, but now if i input 1,it will output a space since I haven't include it in <map>. How could I fix it so that it will output nothing but only used to split the numbers for example 441444 for pause use?
if i input 1,it will output a space since I haven't include it in <map>.
Incorrect statement. Correct one: I output space for symbols not found in map.

Do not output anything for entries not in map.
MiiNiPaa wrote:
Look at my code lines 31-32. It adds character into output string only if they are in the map.
Anyway I fixed it by adding if statement before the cout and it will not cout when string equals to 1. Thanks for your kind help these few days . I'm so glad that i finally finished it.
Topic archived. No new replies allowed.