Ошибка сегментации при работе с аргументом командной строки, программа C - PullRequest
0 голосов

Я работаю над программой, которая декодирует сообщение, предоставленное в виде кода Морзе в качестве аргумента командной строки. Если предоставленная строка содержит 7 пробелов, это означает, что мне нужно вывести пробел в декодированную строку. В настоящее время моя программа показывает все правильные буквы, но я не могу решить проблему с размещением 7 пробелов в строке и печатью одного пробела вместо этого.

Вот проблема и то, как я передаю закодированную строку:

e3r2p2% ./morse "..- -.. .-. .. .-- --.    ..- ....."
udriwg zsh: segmentation fault ./morse "..- -.. .-. .. .-- --.    ..- ....."

Программа работает нормально и печатает все расшифрованные буквы (udriwg), пока не встретит первое (или, возможно, второе) пробел из 7;

Вот код моей программы:

int find_morse(const char *s);
bool count_spaces(char *s);
bool is_valid_char(char *s);
bool is_valid_params(int argc, char *argv[]);
void mx_printchar(char c);
void mx_printerr(const char *s);
int mx_strcmp(const char *first, const char *second);
char* mx_strcpy(char* dest, const char* source);
int mx_strlen(const char *s)

  int main(int argc, char *argv[]){

  if (!is_valid_params(argc, argv)){
        mx_printerr("usage: ./morse \"str\"\n");
        exit(1);
      }
      char *output[27]= {"a","b","c","d","e","f","g","h","i","j","k","l","m","n","o",
                        "p","q","r","s","t","u","v","w","x","y","z","."};
      char *copy;
      copy = malloc(mx_strlen(argv[1]) + 1);
  if (copy != NULL) {
   mx_strcpy(copy, argv[1]);
  } else {
    mx_printerr("usage: ./morse \"str\"\n");
    exit(1);
  }
  int buff = 0;
  char temp[5];
  int index;
  int space = 0;
  int j;

  for (int i = 0, n = mx_strlen(copy); i < n; i++) {
    if (copy[i] == '.' && copy[i + 1] == '.' && copy[i + 2] == '.'
        && copy[i + 3] == '.' &&  copy[i + 4] == '.') {
      mx_printchar(*output[26]);
    }
    if (copy[i] != ' ') {
      temp[buff] = copy[i];
      buff++;
    }
    if (copy[i] == ' ') {
      index = find_morse(temp);
      //print letter converted from morse to ENG                                                                      
      mx_printchar(*output[index]);

      j = i;
      while (copy[j] == ' ') {
          space++;
          j++;
          if (space == 7) {
            mx_printchar(' ');
            space = 0;
            break;
          }
       }
       temp[buff] = '\0';
       buff = 0;
       for(int j = 0; j <4; j++) {
        temp[j] ='\0';
       }                                                                                                 
     }
   }
   mx_printchar('\n');

   free(copy);
   return 0;
 }

   int find_morse(const char *s) {
   char *input[27]={".-","-...","-.-.","-..",".","..-.","--.", "....", "..",
          ".---","-.-",".-..","--","-.", "---",".--.","--.-",".-.",
          "...","-","..-", "...-",".--","-..-","-.--","--..","....."};
     for (int i = 0; i < 27; i++) {
       if (mx_strcmp(s, input[i]) == 0) {
         return i;
       }
     }
   return -1;

   }


  bool count_spaces(char *s) {
   int space = 0;
   for (int i = 0; s[i] != '\0'; i++) {
     if (s[i] == ' ') {
       space++;
       if (s[i + 1] != ' ') {
         if (space != 1 && space != 7) {
          return false;
        } else {
          space = 0;
        }
      }
    }
  }
  return true;
}


bool is_valid_char(char *s){
  int i = 0;
  while (s[i] != '\0'){
    if (s[i] != ' ' && s[i] != '-' && s[i] != '.') {                                                                                                                      
      return false;
    }
    i++;
  }
  return true;
}


bool is_valid_params(int argc, char *argv[]){
  if (argc != 2) {
    return false;
  }
  if (!is_valid_char(argv[1])){
    return false;
  }
  if (!count_spaces(argv[1])){
    return false;
  }
  return true;
}


void mx_printchar(char c){
  write(1, &c, 1);
}


void mx_printerr(const char *s){
  write(2, s, mx_strlen(s));
}


int mx_strcmp(const char *first, const char *second) {
  while (*first) {
    if (*first != *second) break;
    first++;
    second++;
  }
  return *(const unsigned char*)first - *(const unsigned char*)second;
}


char* mx_strcpy(char* dest, const char* source){
  if (dest == NULL) {
    return NULL;
  }
  char *ptr = dest;
  while (*source != '\0') {
    *dest = *source;
    dest++;
    source++;
  }
  *dest = '\0';
  return ptr;
}


int mx_strlen(const char *s){
  int length = 0;
  while (s[length] != '\0'){
    length++;
  }
  return length;
}

Думаю, проблема начинается здесь:

      j = i;
      while (copy[j] == ' ') {
          space++;
          j++;
          if (space == 7) {
            mx_printchar(' ');
            space = 0;
            break;
          }
       }

Программа печатает описанную букву, затем пытается проверить эти пробелы, но что-то go неверно. Буду признателен за любые предложения, как решить эту проблему

1 Ответ

0 голосов
/ 29 мая 2020

При использовании программы из командной строки вы всегда ставите пробел в качестве разделителя между именем вашей программы и параметрами и другими параметрами. Итак, в вашем случае, если есть 7 пробелов, то дополнительный пробел будет добавлен в качестве разделителя между именем вашей программы и 7 пробелами, что сделает его 8 пробелами, как это ./morse. Поэтому я бы предложил использовать любой другой символ, например! или любой другой символ. Теперь для ошибки Segmentation fault, я думаю, что этого не происходит из-за того, что секция счетчика пробелов происходит из-за этой строки copy = malloc(mx_strlen(argv[1]) + 1);, поскольку вы должны знать, что malloc() возвращает void * в выделенное пространство .Теперь я не знаю, что это за mx_ functions. Также некоторые вопросы возникли у меня в голове, когда я отлаживал ваш код, эти ответы включены в модифицированный код (на несколько удовлетворительном уровне), который я помещаю ниже. Пожалуйста, ответьте на них в комментариях.

Код:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

/* Questions
** 1. What are these mx_ functions?
** 2. What is is_valid_params?
** 3. Can't we define *output[27] as *output = "abcdef...z." ?
** 4. In " for(j = 0; j < 4; j++) temp[j] ='\0'; " why j < 4 instead of j < 5?
*/

// Function Prototype
int find_morse(const char *s);

//main()
int main(int argc, char *argv[])
{
    char *output[27]= {"a","b","c","d","e","f","g","h","i","j","k","l","m","n","o","p","q","r","s","t","u","v","w","x","y","z","."};
    char *copy, temp[5];
    int buff = 0, index, space = 0, i, j, n;
    // Checking for valid parameters.
    if (argc != 2)
    {
        printf("usage: ./morse \"Invalid Parameters.\"\n");//mx_printerr("usage: ./morse \"str\"\n");
        exit(1);
    }

    copy = (char *)malloc(strlen(argv[1]) + 1);

    if (copy != NULL)
        strcpy(copy, argv[1]);
    else
    {
        printf("usage: ./morse \"Memory Unavailable.\"\n");
        exit(2);
    }

    for (i = 0, n = strlen(copy); i < n; i++)
    {
        if (copy[i] == '.' && copy[i + 1] == '.' && copy[i + 2] == '.' && copy[i + 3] == '.' &&  copy[i + 4] == '.')
            putchar(*output[26]);

        if (copy[i] != ' ')
            temp[buff++] = copy[i];
        else
        {
            j = i;
            while (copy[j] == ' ')
            {
                space++;
                j++;
                if (space == 7)
                {
                    putchar(' ');
                    space = 0;
                    break;
                }
            }
            temp[buff] = '\0';
            buff = 0;
            // Emptying temp[5]
            //for(j = 0; j < 5; j++)
            temp[0] = '\0'; // Rest elements will automatically be assigned to \0 by compiler.
        }
        if(index = find_morse(temp) != -1)
                putchar(*output[index]); //print letter converted from morse to ENG

    }
    putchar('\n');
    free(copy);
    return 0;
}

int find_morse(const char *s)
{
    char *input[27] = {".-","-...","-.-.","-..",".","..-.","--.", "....", "..",".---","-.-",".-..","--","-.", "---",".--.","--.-",".-.","...","-","..-", "...-",".--","-..-","-.--","--..","....."};
    for (int i = 0; i < 27; i++)
    {
        if (strcmp(s, input[i]) == 0)
            return i;
    }
    return -1;
}

Здесь, в этой программе, я не понял, как пользователь будет вводить азбуку Морзе по одному или в виде строки. Потому что при сопоставлении этих записей азбуки Морзе я уверен, что возникнет логическая ошибка.

...