Модераторы: bsa
  

Поиск:

Ответ в темуСоздание новой темы Создание опроса
> Генератор слова для телефонного номера 
V
    Опции темы
Crafty
Дата 8.7.2009, 03:03 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 319
Регистрация: 3.11.2008

Репутация: 12
Всего: 14



Задача. Каждая цифра на телефоне от 2 до 9 имеет связанные с ней три буквы, как в следующей таблице.

Цифра         Буква
     2              A B C
     3              D E F
     4             G H I
     5              M N O
     6              P R S
     7              T U V
     8              X Y Z

Нужно написать программу, которая для данного семизначного числа записывает в файл все возможные слова из семи букв, соответствующие этому номеру.

Вот что у меня получилось. 
Код

#include <stdio.h>

int main()
{
    FILE *fPtr;
    int i,j,k,l,m,n,p;
    char str[8] = "";
    char num[7];
    const char *mask[8] = {"ABC", "DEF", "GHI", "JKL", "MNO", "PRS", "TUV", "XYZ"};

    if ((fPtr = fopen("tel.dat", "w")) == NULL)
        printf("File could not be opened\n");
    else {
        printf("Input phone number ( ###-#### without 0 and 1): ");
        scanf("%c%c%c-%c%c%c%c", &num[0], &num[1], &num[2], &num[3], &num[4], &num[5], &num[6]);
        fprintf(fPtr, "%c%c%c-%c%c%c%c\n", num[0], num[1], num[2], num[3], num[4], num[5], num[6]);

        for(i = 0; i <= 2; i++)
            for(j = 0; j <= 2; j++)
                for(k = 0; k <= 2; k++)
                    for(l = 0; l <= 2; l++)
                        for(m = 0; m <= 2; m++)
                            for(n = 0; n <= 2; n++)
                                for(p = 0; p <= 2; p++){
                                    str[0] = mask[num[0]-50][i];
                                    str[1] = mask[num[1]-50][j];
                                    str[2] = mask[num[2]-50][k];
                                    str[3] = mask[num[3]-50][l];
                                    str[4] = mask[num[4]-50][m];
                                    str[5] = mask[num[5]-50][n];
                                    str[6] = mask[num[6]-50][p];
                                    fprintf(fPtr, "%s\n", str);
                                }
        fclose(fPtr);
    }
            
    return 0;
}

Знаю что код корявый. Возможно ли как-нибудь избавиться от такой вложенности циклов for?
И еще посоветуйте как можно улучшить код.
PM MAIL   Вверх
zim22
Дата 8.7.2009, 08:53 (ссылка)  | (голосов:1) Загрузка ... Загрузка ... Быстрая цитата Цитата


depict1
****


Профиль
Группа: Завсегдатай
Сообщений: 2682
Регистрация: 15.1.2009
Где: Украина

Репутация: 29
Всего: 69



Цитата(Crafty @  8.7.2009,  03:03 Найти цитируемый пост)
Возможно ли как-нибудь избавиться от такой вложенности циклов for?

на С++ вложенность довольно легко победить. достаточно каждую цифру номера представить как объект.
и реализовать функцию-член, которая будет возвращать множество сгененированных подстрок текста.

Пример:
номер 284 ввели
создался объект Number, внутри которого 3 подобъекта создалось: a1, a2, a3

Код

//Сложим(сгенерируем слова) для них:
std::set<std::string> result = a1 + a2 + a3;
//==>
temp_result1 = a1 /*2*/ + a2/*8*/ = 
                                   {AX, AY, AZ, 
                                    BX, BY, BZ,
                                    CX, CY, CZ};

result = temp_result1 /*28*/ + a3/*4*/ = 
                                   {AXG, AYG, AZG, 
                                    BXG, BYG, BZG,
                                    CXG, CYG, CZG};

                                   {AXH, AYH, AZH, 
                                    BXH, BYH, BZH,
                                    CXH, CYH, CZH};

                                   {AXI, AYI, AZI, 
                                    BXI, BYI, BZI,
                                    CXI, CYI, CZI};


Это сообщение отредактировал(а) zim22 - 8.7.2009, 08:55


--------------------
PM MAIL   Вверх
mes
Дата 8.7.2009, 12:15 (ссылка) |    (голосов:2) Загрузка ... Загрузка ... Быстрая цитата Цитата


любитель
****


Профиль
Группа: Участник Клуба
Сообщений: 7954
Регистрация: 14.1.2006

Репутация: 79
Всего: 250



Цитата(Crafty @  8.7.2009,  02:03 Найти цитируемый пост)
И еще посоветуйте как можно улучшить код. 


держи идею :
Код

/*
 для удобства мы допустили что на каждую клавишу приходится 4 соответсвия,
 для 2-8 цифра и 3 буквы, для 0,1,9  просто цифры (можно изменить) 
 использовал массив строк для удобства заполнения и наглядности,
 но можно заменить на набор одиночных символов :
*/
char Let[][5]= { "0000", "1111",  "2ABC",  "3DEF",  "4GHI",  "5MNO",  "6PRS",  "7TUV",   "8XYZ", "9999"};

int main() {

    int num[7] = { 2,3,5,6,4,8,7 };

    std::cout << "number: ";
    for (unsigned j=0; j<7; ++j) std::cout << num[j];
    std::cout << std::endl;

/*
4 ассоциации = 2 бита,  для 7 цифр-  2*7=14 битов, достаточно проинкрементировать переменную в диапозоне [ 0 ,  2^14 ) для перебора всех ассоциаций для 7 значного номера.
, что мы и делаем в цикле :
*/
    for (unsigned i=0; i < 1<<7*2; ++i) 
    {
/*
   мы хотим исключить из цикла первый ряд ассоциаций, для того чтоб более полноценно использовать буквенные сочетания,
   для этого мы должны исключить те значения из перебора, в которых любая из 7 пар равна нулю,
   мы делаем с помощью битовых масок :
*/
       if ( ( ( (i>>1) & 0x1555 ) | ( i & 0x1555 )  )  == 0x1555 ) ; else continue; // скобки для удобства чтения

/*
 для каждой порядковой цифры номера, выбираем ассоциацию, используя соответсвенную ей битовую пару :
*/
        for (unsigned j=0; j<7; ++j) 
        std::cout << Let[num[j]][(i >> 2*j) & 3] <<" ";
        std::cout << std::endl;
    }

  return 0;
}


P.S. код не тестировал, но по идеи ошибок быть не должно..(по крайней мере надеюсь) smile
В общем тестируйте и подгоняйте под свои нужды, из сложного только битовые операции.
Ax да, маска (0x1555) годится только для 7 значного номера.
Для другого кол-ва цифр аналогично ее  битовому представленнию : 0001 0101 0101 0101  (7 единичек через ноль)

P.S.S. можно также оптимизировать цикл, путем исключения начальных нулевых пар,
то есть началом диапозона будет уже известное нам 0х1555 smile

Это сообщение отредактировал(а) mes - 8.7.2009, 13:20


--------------------
PM MAIL WWW   Вверх
mes
Дата 8.7.2009, 14:55 (ссылка) |    (голосов:1) Загрузка ... Загрузка ... Быстрая цитата Цитата


любитель
****


Профиль
Группа: Участник Клуба
Сообщений: 7954
Регистрация: 14.1.2006

Репутация: 79
Всего: 250



предыдущий код завязан на длину ассоциативной цепочки, и наиболее подходящий для длины степени двойки.
вот немного измененный, для большей свободы действий, да и для понимания, думается, будет более легкий smile

Код

char Let[][4] = { "000", "111",  "ABC",  "DEF",  "GHI",  "MNO",  "PRS",  "TUV",   "XYZ", "999"};

const unsigned NumLen = 7; // длина номера
const unsigned ALen = 3;  // длина ассоциацивной цепочки
const unsigned ARange = pow (ALen, NumLen); // кол-во переборов для опр. длины номера при опр. длине ассоциат. цепочки.

int main() {

    int num[ NumLen ] = { 2,3,5,6,4,8,7 };

// Вывод номерa :
    std::cout <<ARange << "number: ";
    for (unsigned j=0; j< NumLen; ++j) std::cout << num[j];
    std::cout << std::endl;

// Перебор с выводом результата :
    for (unsigned i=0; i < ARange; ++i)
    {
        for (unsigned j=0, k=i; j<NumLen; ++j, k/=3)
          std::cout << Let[ num[j] ][ k % ALen ] <<" ";

        std::cout << std::endl;
    }

  return 0;
}


Это сообщение отредактировал(а) mes - 8.7.2009, 15:01


--------------------
PM MAIL WWW   Вверх
Crafty
Дата 9.7.2009, 16:11 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 319
Регистрация: 3.11.2008

Репутация: 12
Всего: 14



mes, спасибо за интересные решения.
PM MAIL   Вверх
  
Ответ в темуСоздание новой темы Создание опроса
Правила форума "C/C++: Для новичков"
JackYF
bsa

Запрещается!

1. Публиковать ссылки на вскрытые компоненты

2. Обсуждать взлом компонентов и делиться вскрытыми компонентами

  • Действия модераторов можно обсудить здесь
  • С просьбами о написании курсовой, реферата и т.п. обращаться сюда
  • Вопросы по реализации алгоритмов рассматриваются здесь


Если Вам понравилась атмосфера форума, заходите к нам чаще! С уважением, JackYF, bsa.

 
0 Пользователей читают эту тему (0 Гостей и 0 Скрытых Пользователей)
0 Пользователей:
« Предыдущая тема | C/C++: Для новичков | Следующая тема »


 




[ Время генерации скрипта: 0.0466 ]   [ Использовано запросов: 22 ]   [ GZIP включён ]


Реклама на сайте     Информационное спонсорство

 
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности     Powered by Invision Power Board(R) 1.3 © 2003  IPS, Inc.