Go: /*
http://judge.u-aizu.ac.jp/onlinejudge/description.jsp?id=2006&lang=jp
Keitai Message
*/

package main

import (
	"bufio"
	"fmt"
	"os"
	"strconv"
	"strings"
)

// 標準入力を取得するScannerのインスタンスを作成
var scanner = bufio.NewScanner(os.Stdin)

// 標準入力で各行を読み込みstringとして返す
func readLine() string {
	if scanner.Scan() {
		return scanner.Text()
	}
	return ""
}

func main() {
	// 1: . , ! ? (スペース)
	// 2: a b c
	// 3: d e f
	// 4: g h i
	// 5: j k l
	// 6: m n o
	// 7: p q r s
	// 8: t u v
	// 9: w x y z
	// 0: 確定ボタン

	// 改行から空白区切りに変更
	scanner.Split(bufio.ScanWords)
	line, _ := strconv.Atoi(readLine()) // 5行標準入力が続く

	table := []string{
		"",      // 0 index調整ためダミーデータ
		".,!? ", // 1
		"abc",   // 2
		"def",   // 3
		"ghi",   // 4
		"jkl",   // 5
		"mno",   // 6
		"pqrs",  // 7
		"tuv",   // 8
		"wxyz"}  // 9

	// 5行分の標準入力を格納するsliceを作成する
	messages := make([]string, 0, line)

	// sliceに標準入力の内容を格納する
	for i := 0; i < line; i++ {
		messages = append(messages, readLine()) // messages=[20 220 222220 44033055505550666011011111090666077705550301110 000555555550000330000444000080000200004440000]
	}

	// 各行毎に解析する
	for _, message := range messages { // message=000555555550000330000444000080000200004440000
		// 0で分割する
		messageSlice := strings.Split(message, "0") // messageSlice=[   55555555    33    444    8    2    444    ]
		for _, word := range messageSlice {
			if word == "" {
				// NOP.
				// 0をセパレーターにしているので空文字がsliceに格納されてい箇所がある
				// 何もしない
			} else { // word=55555555
				// 一文字取り出しコード値をASCII文字に変換する
				ascii := string((word[0])) // word[0]=5

				// ASCII文字からintへ変換する(tableのindexになる)
				number, _ := strconv.Atoi(ascii)

				// 入力回数をカウントする
				count := len(word) // 5

				// 同じ数字を続けて入力すると変化する文字はループすることを考慮する
				for count > len(table[number]) { // 5 > 3
					count -= len(table[number]) // 2
				}

				// キー配列
				keys := table[number]                   //jkl
				fmt.Printf("%s", string(keys[count-1])) //k
			}
		}
		fmt.Println() // 改行
	}
}

C++: #include<bits/stdc++.h>

using namespace std;

string const c[]={"",".,!? ","abc","def","ghi","jkl","mno","pqrs","tuv","wxyz"};

int main(){
	
	int n;
	
	cin >> n;
	
	for(int i=0;i<n;i++){
		
		string s;
		
		cin >> s;
		
		int num=0;
		int cnt=0;
		
		for(int j=0;s[j];j++){
			if(s[j]=='0'){
				if(cnt!=0){
					num = s[j-1]-'0';
					cout << c[num][(cnt-1)%c[num].size()];
					cnt=0;
				}
			}else{
				cnt++;
			}
		}
	cout << endl;
	}
				
	return 0;
}

C++: #include <bits/stdc++.h>
using namespace std;

int n;

string a[10] = {"", ".,!? ", "abc", "def", "ghi", "jkl", "mno", "pqrs", "tuv", "wxyz"};

int main(){
//	cin.tie(0);
//	ios::sync_with_stdio(false);
	cin >> n;
	for(int i=0; i<n; ++i){
		string s;
		cin >> s;
		string t;
		for(int i=0; i<s.size(); ++i){
			char c = s[i];
			int j = i;
			while(c == s[i]) ++i;
			if(c != '0') t += a[c-'0'][(i-j-1)%(int)(a[c-'0'].size())];
			else --i;
		}
		cout << t << "\n";
	}
}

C++: #include <iostream>
using namespace std;
int main(void){
    char code[][5] = {
        {0,0,0,0,0},
        {'.',',','!','?',' '},
        {97,98,99,0,0},
        {100,101,102,0,0},
        {103,104,105,0,0},
        {106,107,108,0,0},
        {109,110,111,0,0},
        {112,113,114,115,0},
        {116,117,118,0,0},
        {119,120,121,122,0}
    };
    int n;
    cin >> n;
    for (int i = 0; i < n; ++i) {
        string input;
        cin >> input;
        int num = 0;
        int index = 0;
        for (int j = 0; j < input.length(); ++j) {
            if (input[j] == '0') {
                cout << code[num][index];
                num = 0;
                index = 0;
            } else if (!index && !num) {
                num = input[j] - '0';
            } else {
                while(num) {
                    if (++index == 5) index = 0;
                    if (code[num][index]) break;
                }
            }
        }
        cout << endl;
    }
    return 0;
}

C++: #include <cstdio>
char S[1025];
char ch[10][6]={"",".,!? ","abc","def","ghi","jkl","mno","pqrs","tuv","wxyz"};
int size[10]={1,5,3,3,3,3,3,4,3,4};
int main() {
	int n;
	scanf("%d",&n);
	for(int i=0;i<n;i++) {
		scanf("%s",S);
		int idx=0;
		while(S[idx]!='\0') {
			int nxt=idx;
			int len=0;
			while(S[nxt]==S[idx]) {
				nxt++;
				len++;
			}
			if(S[idx]>'0') {
				len--;
				len%=size[S[idx]-'0'];
				putchar(ch[S[idx]-'0'][len]);
			}
			idx=nxt;
		}
		putchar('\n');
	}
}

C++: #define  _CRT_SECURE_NO_WARNINGS
#include "bits/stdc++.h"
#pragma comment (linker, "/STACK:526000000")

using namespace std;
typedef string::const_iterator State;
#define eps 1e-11L
#define MAX_MOD 1000000007LL
#define GYAKU 500000004LL

#define MOD 998244353LL
#define seg_size 262144*2LL
#define pb push_back
#define mp make_pair
typedef long long ll;
#define REP(a,b) for(long long (a) = 0;(a) < (b);++(a))
#define ALL(x) (x).begin(),(x).end()

unsigned long xor128() {
	static unsigned long x = 123456789, y = 362436069, z = 521288629, w = time(NULL);
	unsigned long t = (x ^ (x << 11));
	x = y; y = z; z = w;
	return (w = (w ^ (w >> 19)) ^ (t ^ (t >> 8)));
}

void init() {
	iostream::sync_with_stdio(false);
	cout << fixed << setprecision(10);
}

#define int ll
void solve() {
		string s;
		cin >> s;
		string sup[10] = { "1111",".,!? ","abc" , "def","ghi","jkl","mno","pqrs","tuv","wxyz" };
		int now = -1;
		int target = -1;
		REP(q, s.length()) {
			if (s[q] == '0') {
				if (target != -1) {
					cout << sup[target][now % sup[target].length()];
				}
				target = -1;
				now = -1;
			}
			else {
				now++;
				target = s[q] - '0';
			}
		}
		cout << endl;
}
#undef int

int main() {
	init();
	int test;
	cin >> test;
	REP(te,test)
	solve();
}

C++: #include <iostream>
#include <bitset>
#include <fstream>
#include <string>
#include <cstring>
#include <cmath>
#include <cstdlib>
#include <ctime>
#include <vector>
#include <algorithm>
#include <numeric>
#include <map>
#include <set>
#include <stack>
#include <queue>
#include <deque>
#include <functional>
#include <cctype>
#include <list>
#include <limits>
#include <unordered_map>
#define Debug 0
//#include <boost/multiprecision/cpp_int.hpp>

const double EPS = (1e-10);


using namespace std;
using Int = long long;
//using namespace boost::multiprecision;

const Int MOD = 1000000007;

Int mod_pow(Int x, Int n) {
    Int res = 1;
    while(n > 0) {
        if(n & 1) res = (res * x) % MOD; //ビット演算(最下位ビットが1のとき)
        x = (x * x) % MOD;
        n >>= 1; //右シフト(n = n >> 1)
    }
    return res;
}

//最大公約数
template<typename T>
T gcd(T a, T b) {
    return b != 0 ? gcd(b, a % b) : a;
}

//最小公倍数
template<typename T>
T lcm(T a, T b) {
    return a * b / gcd(a, b);
}

vector<string> button;

void solve(string &ret){
    string s; cin >> s;
    int num = 0;
    int cnt = 0;
    for (int i = 0; i < s.length(); i++) {
        if (s[i] == '0') {
            if (num) {
                ret.push_back(button[num][(cnt-1)%button[num].length()]);
            }
            num = 0;
            cnt = 0;
        } else {
            num = (int)(s[i] - '0');
            cnt++;
        }
    }
    return;
}

void init() {
    button = vector<string>(10);
    button[1] = ".,!? ";
    button[2] = "abc";
    button[3] = "def";
    button[4] = "ghi";
    button[5] = "jkl";
    button[6] = "mno";
    button[7] = "pqrs";
    button[8] = "tuv";
    button[9] = "wxyz";
}

int main(){
    cin.tie(0);
    ios::sync_with_stdio(false);

    init();

    int N; cin >> N;
    vector<string> ans(N);
    for (int i = 0; i < N; i++) {
        string tmp;
        solve(tmp);
        ans[i] = tmp;
    }
    for (auto &i: ans) {
        cout << i << endl;
    }
}