0

I need to convert English letters and Arabic numbers to Morse code until enter is pressed. I used a do while loop to read letters until enter is pressed.

#include<iostream>
#include<stdio.h>
#include<stdlib.h>
using namespace std;

int j = 0;
char a[100];
const char *latin = "**ETIANMSURWDKGOHVF?L?PJBHCYZQ??54?3??2?????6????7??890";

void dash(){cout<<"-";}
void dot(){cout<<".";}

void conv(int decimal)
{
   if(decimal){
    conv(decimal/2);
    if(decimal!=1) decimal%2 ? dash() : dot();
   }
}

void morse(char a[], int lenght)
{
    for(int i = 0; i <= lenght; i++)
    {
        if(a[i] >= 'a' && a[i] <= 'z') a[i] -= 32;
        if(a[i] < 'A' && a[i] > 'Z') return;
        while(latin[++j] != a[i]);
            conv(j);

    }
}

int main()
{
    int lenght = 0;

    cout<<"letter=";

   do{
        cin>>a[lenght];
        lenght++;
    } while(0);


    morse(a, lenght);

    return 0;
}

When I return the length it is always one, so the function makes only one loop. Also, there are some extra symbols that appear when the code is compiled.

Alex Johnson
  • 958
  • 8
  • 23
  • 4
    "_I used a do..while loop to read letters until ENTER key is pressed._" No, you didn't. The only `do`..`while` loop in the shown code does a single iteration, since `0` in `while` condition is evaluated as `false`. – Algirdas Preidžius Aug 09 '18 at 16:06
  • 2
    Have you considered using a lookup table? Would make your life easier... – Aconcagua Aug 09 '18 at 16:06
  • 2
    Consider `std::getline` together with a `std::string`, much easier than your loop and additionally does not limit input length. – Aconcagua Aug 09 '18 at 16:08
  • Be aware that `-= 32` only works with ASCII and compatible character sets. While this is the vast majority, you still might want to keep in mind. – Aconcagua Aug 09 '18 at 16:11
  • 1
    You need to reset j for each character! Prefer having it a local variable of `morse` function. `strchr` does the same as your loop... – Aconcagua Aug 09 '18 at 16:14
  • 1
    It is hard in C++ to do something in real time until enter is pressed. C++ doesn't do much of anything UNTIL enter is pressed. If you don't care and are willing to wait on translation until enter is pressed, groovy take @Aconcagua 's advice about `getline` and `string`. If not, you'll need a console library like curses. I doubt that is what's expected of you though. – user4581301 Aug 09 '18 at 16:14
  • [The recommended C++ book list](https://stackoverflow.com/questions/388242/the-definitive-c-book-guide-and-list). – n. m. could be an AI Aug 09 '18 at 16:22
  • I can't use string because it is forbidden in the task. – Martina Georgieva Aug 09 '18 at 16:24
  • Have you been given a maximum valid input? In `char a[100];` you use 100. Does the assignment specify that input will not exceed 100? – user4581301 Aug 09 '18 at 16:36
  • I recommend @Aconcagua lookup table approach. Use `char * pattern[26] = {/*...*/};`. You could write `cout << pattern['E'];` as the simplest conversion. Modern desktop computers should have enough memory to support an array of 256 elements. – Thomas Matthews Aug 09 '18 at 19:05

1 Answers1

2

There are a few things going on here, but the reason that lenght is always 1 is because you only run through your while loop once:

do {
    cin>>a[lenght];
    lenght++;
} while (0); // this will always evaluate to false

The do block above only executes once because while (0) evaluates to false. This means that lenght is only incremented once, which would explain why its value is 1.

Here's a (potentially) better way:

while (cin.peek() != '\n') {
  cin >> a[lenght++];
}

And you can get the output you're looking for by modifying main():

int main()
{
    int length = 0;

    cout << "letter = ";

    while (cin.peek() != '\n') {
      cin >> a[length++];
    }

    int i = 0;
    while (i < length) {
      morse(a[i]);
      i++;
    }
    cout << endl;

    return 0;
}

Code

Here it is all assembled (along with a few minor changes to conv() and morse()):

#include<iostream>
#include<stdio.h>
#include<stdlib.h>
using namespace std;

int j = 0;
char a[100];
const char *latin = "**ETIANMSURWDKGOHVF?L?PJBHCYZQ??54?3??2?????6????7??890";

void dash(){cout<<"-";}
void dot(){cout<<".";}

void conv(int decimal) {
    if (decimal) {
        conv(decimal/2);
        if (decimal != 1) decimal%2 ? dash() : dot();   
    } 
}

void morse(char c) {
    if (c >= 'a' && c <= 'z') c -= 32;
    if (c < 'A' || c > 'Z') return;
    int i = 0;
    while (latin[++i] != c);
    conv(i);
}

int main()
{
    int length = 0;

    cout << "letter = ";

    while (cin.peek() != '\n') {
      cin >> a[length++];
    }

    int i = 0;
    while (i < length) {
      morse(a[i]);
      i++;
    }
    cout << endl;

    return 0;
}

Input

$ letter = sos

Output

$ ...---...

Edit

As pointed out by user4581301 below, this can be simplified further by removing a[] and the second loop:

int main()
{
    int length = 0;
    char c;

    cout << "letter = ";

    while (cin.peek() != '\n') {
      char c;
      cin >> c;
      morse(c);
    }
    cout << endl;

    return 0;
}
Alex Johnson
  • 958
  • 8
  • 23