Форум программистов, компьютерный форум CyberForum.ru
Наши страницы

С++ для начинающих

Войти
Регистрация
Восстановить пароль
 
 
Рейтинг: Рейтинг темы: голосов - 34, средняя оценка - 4.88
easybudda
Модератор
Эксперт CЭксперт С++
9627 / 5575 / 947
Регистрация: 25.07.2009
Сообщений: 10,710
#1

Морзянка... - C++

20.08.2009, 04:40. Просмотров 4408. Ответов 29
Метки нет (Все метки)

В одном из учебников наткнулся на задачу - написать переводчик англ. букв и цифр в азбуку Морзе. Сделал так:
C++
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
#include <stdio.h>
#include <ctype.h>
#include <string.h>
 
/* Транслятор азбуки морзе. Версия 0.03b */
 
/* str2morse - перевод строки в морзянку. str - исходная строка, mstr - конвертированная, max - макс. длинна конвертированной строки 
для наглядности между "буквами" вставляется пробел, между "словами" три пробела */
char *str2morse(char *str, char *mstr, int max){
    static char *letters[] = {".-", "-...", "-.-.", "-..", ".", "..-.", "--.", "....", "..", ".---", "-.-", ".-..", "--", "-.", "---", ".--.", "--.-", ".-.", "...", "-", "..-", "...-", ".--", "-..-", "-.--", "--.."};
    static char *digits[] = {"-----", ".----", "..---", "...--", "....-", ".....", "-....", "--...", "---..", "----."};
    static char space[] = " ";
    int c;
    int index;
    
    *mstr = '\0';
    while ( *str ){
        /* Вставить пробел, если не первый символ */
        if ( strlen(mstr) > 0 ) {
            if ( strlen(mstr) + strlen(space) < max )
                strcat(mstr, space);
            else 
                break;
        }   
        
        c = toupper(*str);
        /* Если с - буква */
        if ( c >= 'A' && c <= 'Z' ){
            index = c - 'A';
            if ( strlen(mstr) + strlen(letters[index]) < max ) 
                strcat(mstr, letters[index]);
            else 
                break;
        }
        /* Если с - цифра */
        else if ( c >= '0' && c <= '9' ){
            index = c - '0';
            if ( strlen(mstr) + strlen(digits[index]) < max ) 
                strcat(mstr, digits[index]);
            else 
                break;
        }
        /* Если с - пробел */
        else if ( c == ' ' ) {
            if ( strlen(mstr) + strlen(space) < max )
                strcat(mstr, space);
            else 
                break;
        }
        
        str++;
    }
 
    return mstr;
}
 
int main(){
    char text[BUFSIZ];
    char morse[BUFSIZ];
    
    while ( fgets(text, BUFSIZ, stdin) ) {
        if ( str2morse(text, morse, BUFSIZ) == NULL ) {
            fprintf(stderr, "Can't convert string!\n");
            return 1;
        }
        else {
            printf("%s\n", morse);
        }
    }
    
    printf("Good bye!\n");
    return 0;
}
Прокомментируйте, пожалуйста, кому не сложно.
0
Similar
Эксперт
41792 / 34177 / 6122
Регистрация: 12.04.2006
Сообщений: 57,940
20.08.2009, 04:40
Здравствуйте! Я подобрал для вас темы с ответами на вопрос Морзянка... (C++):

Морзянка - C++
Ребят, помогите пожалуйста! нужно в borland c++ написать программу чтобы вводимый текст переводился в последовательность точек и тире с...

Морзянка - C++
Короч дела такие..... Все вроде работает.... но мне нужно что бы руссие буковки переводи, и как наоборот сделать, не пойму... и еще...

Морзянка - C++
Всем привет !! Написал программу которая переводит слова в морзянка. Теперь мне надо написать программу которая будет все делать наоборот...

Морзянка. Вводимый с клавиатуры текст перевести в последовательность точек и тире с помощью азбуки Морзе. - C++
Народ, помогите плз решить 2 задачки на С оч надо... 1)Морзянка. Вводимый с клавиатуры текст перевести в последовательность...

Морзянка - PascalABC.NET
Заданный текст(вводимый с клавиатуры) представить последовательностью точек и тире с помощью азбуки морзе. Если возможно , сопроводить...

Морзянка - C#
Задание: &quot;Реализовать возможность кодирования открытого текста и декодирования шифрограммы по правилам азбуки Морзе. Предусмотреть...

Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
skvor
640KB мне хватило на всё.
118 / 49 / 2
Регистрация: 07.06.2009
Сообщений: 442
20.08.2009, 05:09 #2
А оно работает? Если работает, то и ладно, чего спрашивать.

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

После этого можно использовать стандартные функции (методы) поиска и копирования подстрок C(C++).
Т.е. в одной строке ищем нужный символ или код, из другой копируем (выделяем) подстроку начиная с определённого номера позиции, до ближайшего пробела.
Только итераторы использовать не получится, т.е. только индексация как в массиве по номерам символов [n]
0
easybudda
Модератор
Эксперт CЭксперт С++
9627 / 5575 / 947
Регистрация: 25.07.2009
Сообщений: 10,710
20.08.2009, 05:20  [ТС] #3
Цитата Сообщение от skvor Посмотреть сообщение
А оно работает? Если работает, то и ладно, чего спрашивать.
Ага, работает... А спрашивал - так учусь. Меня вот в самой функции вызов strlen чуть ли не через строку смущает. А с другой стороны - так вроде проще, чем счётчик количества символов в выходной строке приделывать...
0
skvor
640KB мне хватило на всё.
118 / 49 / 2
Регистрация: 07.06.2009
Сообщений: 442
20.08.2009, 05:32 #4
C++
1
2
3
4
5
6
7
8
9
10
std::string E="a   b   c  ";
std::string M="... ___ ._."; //конечно от балды
std::string In,Out;
std::cout<<"Введите строку\n";
std::cin>>In;
for (std::string::size_type i=0; i<In.length(); ++i)
{ std::string::size_type Pos=E.find(In[i]);
  Out+=M.substr(Pos,M.find(" ",Pos+1)-Pos+1);
}
std::cout<<Out<<std::endl;
Естественно, нет и защиты от левых символов.
0
snake32
1386 / 1029 / 139
Регистрация: 26.02.2009
Сообщений: 3,851
Записей в блоге: 5
20.08.2009, 12:29 #5
Цитата Сообщение от easybudda Посмотреть сообщение
C++
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
#include <stdio.h>
#include <ctype.h>
#include <string.h>
*
/* Транслятор азбуки морзе. Версия 0.03b */
*
/* str2morse - перевод строки в морзянку. str - исходная строка, mstr - конвертированная, max - макс. длинна конвертированной строки 
для наглядности между "буквами" вставляется пробел, между "словами" три пробела */
char *str2morse(char *str, char *mstr, int max){
* * * * static char *letters[] = {".-", "-...", "-.-.", "-..", ".", "..-.", "--.", "....", "..", ".---", "-.-", ".-..", "--", "-.", "---", ".--.", "--.-", ".-.", "...", "-", "..-", "...-", ".--", "-..-", "-.--", "--.."};
* * * * static char *digits[] = {"-----", ".----", "..---", "...--", "....-", ".....", "-....", "--...", "---..", "----."};
* * * * static char space[] = " ";
* * * * int c;
* * * * int index;
* * * * 
* * * * *mstr = '\0';/*обнуляем выходную строку*/
* * * * while ( *str ){/*пока не конец строки*/
* * * * * * * * /* Вставить пробел, если не первый символ */
* * * * * * * * if ( strlen(mstr) > 0 ) {
                        /*добавить пробел если он влезет, те меньше максимальной длины выходного буфера mstr (п)*/
* * * * * * * * * * * * if ( strlen(mstr) + strlen(space) < max )
* * * * * * * * * * * * * * * * strcat(mstr, space);
* * * * * * * * * * * * else /*иначе выход из цикла*/
* * * * * * * * * * * * * * * * break;
* * * * * * * * } * * * 
* * * * * * * * 
* * * * * * * * c = toupper(*str);/* сохраняем символ как заглавную букву в с*/
* * * * * * * * /* Если с - буква */
* * * * * * * * if ( c >= 'A' && c <= 'Z' ){
                        /*тк индексация letters начинается с нуля, необходимо вычесть самый первый символ заглавных букв из с*/
* * * * * * * * * * * * index = c - 'A';
                        /*опять проверка (п) */
* * * * * * * * * * * * if ( strlen(mstr) + strlen(letters[index]) < max ) 
* * * * * * * * * * * * * * * * strcat(mstr, letters[index]);
* * * * * * * * * * * * else 
* * * * * * * * * * * * * * * * break;
* * * * * * * * }
* * * * * * * * /* Если с - цифра */
* * * * * * * * else if ( c >= '0' && c <= '9' ){
* * * * * * * * * * * * index = c - '0';/*аналогично получаем индекс, только для цифр*/
                        /*опять проверка (п) */
* * * * * * * * * * * * if ( strlen(mstr) + strlen(digits[index]) < max ) 
* * * * * * * * * * * * * * * * strcat(mstr, digits[index]);
* * * * * * * * * * * * else 
* * * * * * * * * * * * * * * * break;
* * * * * * * * }
* * * * * * * * /* Если с - пробел */
* * * * * * * * else if ( c == ' ' ) {
                        /*опять проверка (п) */
* * * * * * * * * * * * if ( strlen(mstr) + strlen(space) < max )
* * * * * * * * * * * * * * * * strcat(mstr, space);
* * * * * * * * * * * * else 
* * * * * * * * * * * * * * * * break;
* * * * * * * * }
* * * * * * * * 
* * * * * * * * str++;/*переходим к следующиму символу*/
* * * * }
*
* * * * return mstr;
}
Собственно почти по шагам описание функции. Только вот подтверждение слов
между "словами" три пробела
я не нашёл. Ставится только один пробел.
0
easybudda
Модератор
Эксперт CЭксперт С++
9627 / 5575 / 947
Регистрация: 25.07.2009
Сообщений: 10,710
20.08.2009, 12:43  [ТС] #6
Цитата Сообщение от snake32 Посмотреть сообщение
Собственно почти по шагам описание функции. Только вот подтверждение слов я не нашёл. Ставится только один пробел.
Один пробел вставляется перед каждым новым символом, если он не первый в строке mstr. Второй - если символ в str и есть пробел и третий перед следующим символом.
0
-=ЮрА=-
Заблокирован
Автор FAQ
20.08.2009, 12:47 #7
easybudda я думаю ошибка здесь
C++
1
2
3
char text[BUFSIZ];
char morse[BUFSIZ];//Строка из морзянок длиннее строки букв и цифр
//на букву у тебя как минимум два символа нуна
Для простоты вбей morse[15*BUFSIZ]; Множитель потом подберёшь
Прога вылетает от переполнения блока памяти отведенной под строчку морзянки...
0
easybudda
Модератор
Эксперт CЭксперт С++
9627 / 5575 / 947
Регистрация: 25.07.2009
Сообщений: 10,710
20.08.2009, 13:22  [ТС] #8
Цитата Сообщение от skvor Посмотреть сообщение
C++
1
2
3
4
5
6
7
8
9
10
std::string E="a   b   c  ";
std::string M="... ___ ._."; //конечно от балды
std::string In,Out;
std::cout<<"Введите строку\n";
std::cin>>In;
for (std::string::size_type i=0; i<In.length(); ++i)
{ std::string::size_type Pos=E.find(In[i]);
  Out+=M.substr(Pos,M.find(" ",Pos+1)-Pos+1);
}
std::cout<<Out<<std::endl;
Естественно, нет и защиты от левых символов.
Не знаю, как на счёт "проще", но как вариант решения - интересно, спасибо!

Добавлено через 12 минут 34 секунды
Цитата Сообщение от -=ЮрА=- Посмотреть сообщение
easybudda я думаю ошибка здесь
C++
1
2
3
char text[BUFSIZ];
char morse[BUFSIZ];//Строка из морзянок длиннее строки букв и цифр
//на букву у тебя как минимум два символа нуна
Для простоты вбей morse[15*BUFSIZ]; Множитель потом подберёшь
Прога вылетает от переполнения блока памяти отведенной под строчку морзянки...
Это какую же ей строку подсунуть надо, чтоб вылетала от переполнения морзяночной строки? У меня BUFSIZ аж в 8192 символа определён (gcc 4.3.2). К тому же проверка на превышение max символов везде присутствует и strcat 0 в конце строки добавляет. Короче странно - у меня работает, 0 сучков 0 задоринок...
0
snake32
1386 / 1029 / 139
Регистрация: 26.02.2009
Сообщений: 3,851
Записей в блоге: 5
20.08.2009, 13:35 #9
Цитата Сообщение от easybudda Посмотреть сообщение
Один пробел вставляется перед каждым новым символом, если он не первый в строке mstr. Второй - если символ в str и есть пробел и третий перед следующим символом.
Ой! Облажался...
Цитата Сообщение от easybudda Посмотреть сообщение
Короче странно - у меня работает, 0 сучков 0 задоринок...
Так что тебя конкретно интересует? Если знаешь как алгоритм работает? Что ещё то надо? Оптимизация что ли?
0
easybudda
Модератор
Эксперт CЭксперт С++
9627 / 5575 / 947
Регистрация: 25.07.2009
Сообщений: 10,710
20.08.2009, 13:49  [ТС] #10
Цитата Сообщение от snake32 Посмотреть сообщение
Ой! Облажался...

Так что тебя конкретно интересует? Если знаешь как алгоритм работает? Что ещё то надо? Оптимизация что ли?
Да, вот в плане производительности есть сомнения. Ну с морзянкой-то просто, но примерно тот же алгоритм думаю применить при замене строк по шаблону в больших файлах "на лету" (для чего, собственно, морзянкой и заморочился - можно сказать частный случай)...
0
snake32
1386 / 1029 / 139
Регистрация: 26.02.2009
Сообщений: 3,851
Записей в блоге: 5
20.08.2009, 14:16 #11
easybudda, я читал книгу (Автор: Джоэл Спольски "Джоэл о программировании") где автор, один из разработчиков MS Excel, призывает не пользоватся строками типа ASCIIZ. Ведь каждая ф-ия работающая с таким типом, будь то strlen или strcat должна пробежаться по всему массиву символов в поисках нуля, что очень накладно выходит. В этом плане Паскалевсий тип string выглядит более привлекательнее, тк там уже "за ранее" известно сколько символов в строке, но как и везде есть свои минусы длина строки не может быть длинее 255 символов.

Я не знаю, может есть нечто среднее среди С-ишным char* и Паскалевским string-ом. Наверняка придумано куча классов.
0
-=ЮрА=-
Заблокирован
Автор FAQ
20.08.2009, 15:09 #12
Цитата Сообщение от easybudda Посмотреть сообщение
Не знаю, как на счёт "проще", но как вариант решения - интересно, спасибо!

Добавлено через 12 минут 34 секунды

Это какую же ей строку подсунуть надо, чтоб вылетала от переполнения морзяночной строки? У меня BUFSIZ аж в 8192 символа определён (gcc 4.3.2). К тому же проверка на превышение max символов везде присутствует и strcat 0 в конце строки добавляет. Короче странно - у меня работает, 0 сучков 0 задоринок...
Попробуй strcat вот так юзнуть

C++
1
2
3
char string[126] = "сюда вбей символов 123 штучки";
и сделай
strcat(string,"Строка из числа символов больше 2-х");
А лучше два или три раза стркат забей и погляди что с прогой станет, у меня к примеру прога вылетела
0
easybudda
Модератор
Эксперт CЭксперт С++
9627 / 5575 / 947
Регистрация: 25.07.2009
Сообщений: 10,710
20.08.2009, 16:09  [ТС] #13
Цитата Сообщение от -=ЮрА=- Посмотреть сообщение
Попробуй strcat вот так юзнуть

C++
1
2
3
char string[126] = "сюда вбей символов 123 штучки";
и сделай
strcat(string,"Строка из числа символов больше 2-х");
А лучше два или три раза стркат забей и погляди что с прогой станет, у меня к примеру прога вылетела
Ну так-то конечно за предел string[126] перепрыгнешь. У меня же как-раз с этой целью
C++
1
2
3
4
if ( strlen(mstr) + strlen(add_str) < max )
strcat(mstr, add_str);
else
break;
То есть возвращается строка не длиннее max символов
0
-=ЮрА=-
Заблокирован
Автор FAQ
20.08.2009, 16:18 #14
Я думал прога вылеиает а так нормальный алгоритм...Шо коментить скомпилилтвой код вроде не вылетала програмулина, больше ничего сказать не могу
0
easybudda
Модератор
Эксперт CЭксперт С++
9627 / 5575 / 947
Регистрация: 25.07.2009
Сообщений: 10,710
21.08.2009, 03:34  [ТС] #15
Цитата Сообщение от snake32 Посмотреть сообщение
easybudda, я читал книгу (Автор: Джоэл Спольски "Джоэл о программировании") где автор, один из разработчиков MS Excel, призывает не пользоватся строками типа ASCIIZ. Ведь каждая ф-ия работающая с таким типом, будь то strlen или strcat должна пробежаться по всему массиву символов в поисках нуля, что очень накладно выходит. В этом плане Паскалевсий тип string выглядит более привлекательнее, тк там уже "за ранее" известно сколько символов в строке, но как и везде есть свои минусы длина строки не может быть длинее 255 символов.

Я не знаю, может есть нечто среднее среди С-ишным char* и Паскалевским string-ом. Наверняка придумано куча классов.
Да вот и я о том же. Работать-то оно работает, но как-то накладных расходов много... А на счёт паскалевских строк - так строка может и меньше 255 символов быть. Так или иначе, а длинну как-то получать прийдётся. У меня ещё вариант был ввести переменную, которая длинну mstr считает, но проблема решается только частично, да и корявенько оно как-то...
Вспомнил - в паскале как-раз первый байт длинну строки и определяет... Да, надо будет и тут что-то похожее придумывать...

Добавлено через 11 часов 12 минут 0 секунд
...И лучше выдумать не смог! (с)

Так, наверное, быстрее будет:
C++
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
106
107
108
109
#include <stdio.h>
#include <ctype.h>
#include <string.h>
 
/* Транслятор азбуки морзе. Версия 0.04b */
 
typedef struct {
    int len;
    char *str;
} Str_t;
 
/* Str_t Str(char *) Возвращает структуру Str_t. str - указатель на существующую строку, тупо копируется */
Str_t Str(char *str){
    Str_t s;
    s.len = strlen(str);
    s.str = str;
    
    return s;
}
 
/* Str_t *catStr(Str_t *target, const Str_t *source) Дописывает source.str в конец target.str. target.str должна быть достаточно большой,
чтобы вместить source.str. Ноль в конце строки неявно копируется. 
target.len увеличивается на source.len */
Str_t *catStr(Str_t *target, const Str_t *source){
    char *tt; /* target tail */
    char *ss; /* source start */
    
    tt = target->str + target->len;
    ss = source->str;
    while ( *tt++ = *ss++ )
        ;
    target->len += source->len;
    
    return target;
}
    
 
/* str2morse - перевод строки в морзянку. str - исходная строка, mstr - конвертированная, max - макс. длинна конвертированной строки 
для наглядности между "буквами" вставляется пробел, между "словами" три пробела */
char *str2morse(char *str, char *mstr, int max){
    static Str_t letters[] = { {2, ".-"}, {4, "-..."}, {4, "-.-."}, {3, "-.."}, {1, "."}, {4, "..-."}, {3, "--."}, {4, "...."}, {2, ".."},
        {4, ".---"}, {3, "-.-"}, {4, ".-.."}, {2, "--"}, {2, "-."}, {3, "---"}, {4, ".--."}, {4, "--.-"}, {3, ".-."}, {3, "..."}, {1, "-"}, 
        {3, "..-"}, {4, "...-"}, {3, ".--"}, {4, "-..-"}, {4, "-.--"}, {4, "--.."} };
    static Str_t digits[] = { {5, "-----"}, {5, ".----"}, {5, "..---"}, {5, "...--"}, {5, "....-"}, {5, "....."}, {5, "-...."}, {5, "--..."}, 
        {5, "---.."}, {5, "----."} };
    static Str_t space = {1, " "};
    int c;
    int index;
    Str_t s;
    
    *mstr = '\0';
    s = Str(mstr);
    while ( *str ){
        /* Вставить пробел, если не первый символ */
        if ( s.len > 0 ) {
            if ( s.len + space.len < max )
                catStr(&s, &space);
            else 
                break;
        }   
        
        c = toupper(*str);
        /* Если с - буква */
        if ( c >= 'A' && c <= 'Z' ){
            index = c - 'A';
            if ( s.len + letters[index].len < max ) 
                catStr(&s, &letters[index]);
            else 
                break;
        }
        /* Если с - цифра */
        else if ( c >= '0' && c <= '9' ){
            index = c - '0';
            if ( s.len + digits[index].len < max ) 
                catStr(&s, &digits[index]);
            else 
                break;
        }
        /* Если с - пробел */
        else if ( c == ' ' ) {
            if ( s.len + space.len < max )
                catStr(&s, &space);
            else 
                break;
        }   
        
        str++;
    }
 
    return mstr;
}
 
int main(){
    char text[BUFSIZ];
    char morse[BUFSIZ];
    
    while ( fgets(text, BUFSIZ, stdin) ) {
        if ( str2morse(text, morse, BUFSIZ) == NULL ) {
            fprintf(stderr, "Can't convert string!\n");
            return 1;
        }
        else {
            printf("%s\n", morse);
        }
    }
    
    printf("Good bye!\n");
    return 0;
}
0
MoreAnswers
Эксперт
37091 / 29110 / 5898
Регистрация: 17.06.2006
Сообщений: 43,301
21.08.2009, 03:34
Привет! Вот еще темы с ответами:

Морзянка (Азбука морзе) и ее перевод - Pascal ABC
Может кто помочь? Есть программа uses crt; const mrz:array of string= ...

Курсовая "Морзянка" - Visual C++
Задание: Разработать программу, которая считывает текст из файла (*.txt), выводит его в этом виде на экран, переводит его согласно азбуке...

"Морзянка" - Free Pascal
Доброго времени суток. Думаю, многие знакомы с этой задачей. Так вот, мне нужно ввести доп/элементы в азбуку, которая распознает(пока) лишь...


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
Yandex
Объявления
21.08.2009, 03:34
Ответ Создать тему
Опции темы

КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin® Version 3.8.9
Copyright ©2000 - 2017, vBulletin Solutions, Inc.
Рейтинг@Mail.ru