поведение с двойным указателем - PullRequest
0 голосов
/ 28 декабря 2018

Я выполняю упражнение на https://www.codingame.com/, чтобы попрактиковаться с некоторыми указателями C.

Задача состоит в том, чтобы перевести вводимые символы в искусство ASCII.Например, буква A:

 # 
# #
###
# #
# #

https://www.codingame.com/ide/puzzle/ascii-art

Весь алфавит ASCII предоставляется в виде одного ввода из разных строк (от A до Z плюс?):

 #  ##   ## ##  ### ###  ## # # ###  ## # # #   # # ###  #  ##   #  ##   ## ### # # # # # # # # # # ### ### 
# # # # #   # # #   #   #   # #  #    # # # #   ### # # # # # # # # # # #    #  # # # # # # # # # #   #   # 
### ##  #   # # ##  ##  # # ###  #    # ##  #   ### # # # # ##  # # ##   #   #  # # # # ###  #   #   #   ## 
# # # # #   # # #   #   # # # #  #  # # # # #   # # # # # # #    ## # #   #  #  # # # # ### # #  #  #       
# # ##   ## ##  ### #    ## # # ###  #  # # ### # # # #  #  #     # # # ##   #  ###  #  # # # #  #  ###  #  

Я пытаюсь сохранить алфавит в виде двойного указателя (alphabet_input).

char ** alphabet_input;

int main()
{
    int length = 4;
    int height = 5;

    alphabet_input = (char **)malloc(sizeof(char *)*height);

    for (int i = 0; i < height; i++) {
        char ROW[1025];
        fgets(ROW, 1025, stdin);

        alphabet_input[i] = ROW;

        // print alphabet lines for the first time
        printf("%s", alphabet_input[i]);
    }

    // print alphabet lines for the second time
    printf("%s", alphabet_input[0]);
    printf("%s", alphabet_input[1]);
    printf("%s", alphabet_input[2]);
    printf("%s", alphabet_input[3]);
    printf("%s", alphabet_input[4]);

    return 0;
}

Однако, когда я пытаюсь распечатать его, я неоднократно получаю последнюю строку.Вот что я получаю в результате:

 #  ##   ## ##  ### ###  ## # # ###  ## # # #   # # ###  #  ##   #  ##   ## ### # # # # # # # # # # ### ### 
# # # # #   # # #   #   #   # #  #    # # # #   ### # # # # # # # # # # #    #  # # # # # # # # # #   #   # 
### ##  #   # # ##  ##  # # ###  #    # ##  #   ### # # # # ##  # # ##   #   #  # # # # ###  #   #   #   ## 
# # # # #   # # #   #   # # # #  #  # # # # #   # # # # # # #    ## # #   #  #  # # # # ### # #  #  #       
# # ##   ## ##  ### #    ## # # ###  #  # # ### # # # #  #  #     # # # ##   #  ###  #  # # # #  #  ###  #  
# # ##   ## ##  ### #    ## # # ###  #  # # ### # # # #  #  #     # # # ##   #  ###  #  # # # #  #  ###  #  
# # ##   ## ##  ### #    ## # # ###  #  # # ### # # # #  #  #     # # # ##   #  ###  #  # # # #  #  ###  #  
# # ##   ## ##  ### #    ## # # ###  #  # # ### # # # #  #  #     # # # ##   #  ###  #  # # # #  #  ###  #  
# # ##   ## ##  ### #    ## # # ###  #  # # ### # # # #  #  #     # # # ##   #  ###  #  # # # #  #  ###  #  
# # ##   ## ##  ### #    ## # # ###  #  # # ### # # # #  #  #     # # # ##   #  ###  #  # # # #  #  ###  #  

Я ожидал, что входные данные будут напечатаны дважды:

 #  ##   ## ##  ### ###  ## # # ###  ## # # #   # # ###  #  ##   #  ##   ## ### # # # # # # # # # # ### ### 
# # # # #   # # #   #   #   # #  #    # # # #   ### # # # # # # # # # # #    #  # # # # # # # # # #   #   # 
### ##  #   # # ##  ##  # # ###  #    # ##  #   ### # # # # ##  # # ##   #   #  # # # # ###  #   #   #   ## 
# # # # #   # # #   #   # # # #  #  # # # # #   # # # # # # #    ## # #   #  #  # # # # ### # #  #  #       
# # ##   ## ##  ### #    ## # # ###  #  # # ### # # # #  #  #     # # # ##   #  ###  #  # # # #  #  ###  #  
 #  ##   ## ##  ### ###  ## # # ###  ## # # #   # # ###  #  ##   #  ##   ## ### # # # # # # # # # # ### ### 
# # # # #   # # #   #   #   # #  #    # # # #   ### # # # # # # # # # # #    #  # # # # # # # # # #   #   # 
### ##  #   # # ##  ##  # # ###  #    # ##  #   ### # # # # ##  # # ##   #   #  # # # # ###  #   #   #   ## 
# # # # #   # # #   #   # # # #  #  # # # # #   # # # # # # #    ## # #   #  #  # # # # ### # #  #  #       
# # ##   ## ##  ### #    ## # # ###  #  # # ### # # # #  #  #     # # # ##   #  ###  #  # # # #  #  ###  #  

Как мне манипулировать индексами alphabet_input для правильной печати каждой строкикак строка?

Я действительно запутался, потому что печать внутри цикла for работает нормально.Однако сразу после этого индексация, похоже, не работает.

1 Ответ

0 голосов
/ 28 декабря 2018
for (int i = 0; i < H; i++) {
    char ROW[1025];
    fgets(ROW, 1025, stdin);
    alphabet_input[i] = ROW;
}

Переменная ROW находится в области видимости тела for, поэтому она создается и уничтожается при каждой итерации.Вы указываете alphabet_input[i] на эту переменную, которая сразу же уничтожается в конце итерации, поэтому вы получаете висячие указатели.

Вместо того, чтобы указывать alphabet[i] на локальную переменную, вам нужно выделить место для нее изатем скопируйте в нее содержимое строки.

char ** alphabet_input;
alphabet_input = malloc(height * sizeof *alphabet_input);

for (int i = 0; i < height; i++) {
    char row[1025];
    fgets(row, 1025, stdin);

    size_t len = strlen(row);

    alphabet_input[i] = malloc(len + 1);
    strcpy(alphabet_input[i], row);
}

Возможно, вы захотите настроить приведенный выше код в зависимости от желаемой длины (например, 1025 вместо strlen, или удалить завершающую новую строку и т. д.)

Несколько замечаний, которые я хотел бы сделать:

  • именно так я бы рекомендовал написать malloc:

    pointer_var = <no cast> malloc(<num_elements> * sizeof *pointer_var);
    alphabet_input = malloc(height * sizeof *alphabet_input);
    
  • sizeof(char) гарантированно будет 1 по стандарту, поэтому вы можете пропустить sizeof(char) in malloc:

    alphabet_input[i] = malloc(len + 1);
    
  • , избегая всех переменных в верхнем регистре.Они обычно используются для макросов в C.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...