Как бы вы добавили символы в массив динамически? Без предопределения массива?

#c #arrays #char

#c #массивы #символ

Вопрос:

Если я хочу добавить символы в массив char, я должен сделать это следующим образом:

 #include <stdio.h>

int main() {
    int i;
    char characters[7] = "0000000";
    for (i = 0; i < 7; i  ) {
        characters[i] = (char)('a'   i);
        if (i > 2) {
            break;
        }
    }

    for (i = 0; i < 7; i  ) {
        printf("%cn", characters[i]);
    }
    return 0;
}
  

Чтобы предотвратить печать каких-либо странных символов, я должен инициализировать массив, но это не является гибким. Как я могу динамически добавлять символы в массив символов? Точно так же, как вы бы делали в Python:

 characters = []
characters.append(1)
...
  

Комментарии:

1. ` символы символа [7] = «0000000»;` не будут компилироваться (если вам повезет), поскольку "0000000" это массив из 8 символов, включая указатель null в конце строки. Если вам действительно нужен массив из 7 символов, используйте ` символы символа[7] = {‘0′,’0′,’0′,’0′,’0′,’0′,’0’}»;`

2. @mattnz: char a[7] = "1234567"; в C. Я понимаю, что это ошибка в C , но этот пост не помечен этим языком, и поэтому ваш комментарий вводит в заблуждение.

Ответ №1:

Для чистого C. не существует уродливого решения

 #include <stdio.h>

int main() {
    int i;
    size_t space = 1;                  // initial room for string
    char* characters = malloc(space);  // allocate
    for (i = 0; i < 7; i  ) {
        characters[i] = (char)('a'   i);
        space  ;                       // increment needed space by 1
        characters = realloc(characters, space); // allocate new space
        if (i > 2) {
            break;
        }
    }

    for (i = 0; i < 7; i  ) {
        printf("%cn", characters[i]);
    }
    return 0;
}
  

На практике вы хотите избежать использования realloc и, конечно, распределять память большими порциями, чем всего один байт, возможно, даже с экспоненциальной скоростью. Но, по сути, это то, что происходит под капотом std::string и тому подобного: вам нужен счетчик, который подсчитывает текущий размер, переменная текущего максимального размера (здесь это всегда текущий размер 1, для простоты) и некоторое перераспределение, если потребность в пространстве превышает максимальный текущий размер.

Комментарии:

1. Вы не освободили память!

2. @CJxD return из main неявно освобождает всю память

Ответ №2:

Да, конечно, вы можете добавлять символы динамически:

 quote char[100] = "The course of true love";
      strcat( quote, " never did run smooth.";
  

но только если в кавычках [ ] достаточно места для размещения добавленных символов. Или, может быть, вы спрашиваете, почему в C вы должны заранее организовать достаточное количество символьного хранилища, тогда как в Python хранилище выделяется динамически. Именно так был разработан язык в 197x.

разрешает ли C99 динамически выделяемое хранилище: хранилище, выделяемое системой во время выполнения. И это очень серьезная ошибка, имо.

Комментарии:

1. Почему вы думаете, что добавление возможности динамического выделения хранилища в C99 — плохая идея? У меня нет мнения по этому вопросу, просто любопытно…

2. 1 — Спасибо, что проинформировали меня об еще одной ошибке, допущенной C99. На самом деле это не C.

3. @equality — На случай, если вы не знаете, динамически выделяемое хранилище в C99 называется «массивами переменной длины» или VLAS. Просто IMO: (1) VLA размещаются в стеке, а не в куче, что позволяет легко взорвать стек по ошибке и без предупреждения. (2) ‘sizeof’ больше не обязательно должен выдавать константу; Я могу использовать ‘sizeof’ для VLA во время выполнения. Это меня смущает и пугает. (3) Поскольку C больше не является подмножеством C — в C нет VLAS — я больше не могу компилировать / связывать свои программы с помощью компилятора C ; таким образом, мои программы C трудно перенести на C . Я согласен с @Heath Hunnicutt: C99 — это не C.

Ответ №3:

Вы не сможете, если не используете связанные списки или какую-либо другую пользовательскую структуру данных.