Добавление как строковых, так и одиночных значений символов в один и тот же многомерный список - PullRequest
0 голосов
/ 17 апреля 2019

Так, как говорится в заголовке. Я хочу сделать многомерный список, где каждый столбец первого столбца представляет собой описание, а остальные столбцы - месяц, день и час описываемой встречи. Таким образом, в основном весь список представляет собой календарь, где каждая строка представляет собой одну встречу. У меня серьезные проблемы с обработкой того факта, что первый столбец другого типа, чем другие. Вместо этого я собирался создать связанный список, но позже мне пришлось отсортировать строки по времени и дате, и мысль о сравнении строк в связанном списке оказалась сложной.

Я думаю, что это сложнее, чем есть. Я думаю, что я испортил распределение памяти массива, так как я довольно новый с C.

char** add_appointment(char **calendar,int a){
    char **pointer;
    if(a != 0){
        calendar = realloc(calendar, (a+1)*sizeof(char **));
        calendar[0] = malloc(20 * sizeof(char));
        calendar[1] = malloc(1 * sizeof(char));
        calendar[2] = malloc(1 * sizeof(char));
        calendar[3] = malloc(1 * sizeof(char));
    }
    pointer = calendar;
    char* description;
    description = malloc(20*sizeof(char));
    char month;
    char day;
    char hour;
    int i;
    printf("Add description, month, day and hour of the appointment\n");
    fgets(description, 19, stdin);
    description = realloc(description, strlen(description)+1);
    description[strlen(description)+1] = '\0';
    scanf("%c", &month);
    scanf("%c", &day);
    scanf("%c", &hour);
    calendar[a][0] = *description;
    calendar[a][1] = month;
    calendar[a][2] = day;
    calendar[a][3] = hour;
    return pointer;

}

Итак, максимальный размер описания - 20. И я знаю, что должен добавить '\ 0', что я отчаянно пытаюсь сделать. «а» происходит из основной функции и сообщает текущее количество встреч в календаре. Цикл if существует, потому что выделение памяти для первого назначения выполняется основной функцией. Программа уже дает сбой после записи описания в командной строке и отказывается спрашивать даже через месяц после этого.

Ответы [ 2 ]

0 голосов
/ 18 апреля 2019

Вместо многомерного массива, я думаю, это было бы лучше подходит для struct: оно более четкое и расширяемое. Если вы хотите увеличить объем данных, то сохранение емкости, которая растет в геометрической прогрессии, имеет гораздо более приятное ограничение. Также хорошая идея отделить интерфейс от логики.

#include <stdlib.h> /* realloc, rand, EXIT_* */
#include <string.h> /* strncpy */
#include <stdio.h>  /* printf, perror */
#include <assert.h> /* assert */

struct Appointment {
    char desc[1024];
    unsigned year, month, day, hour, minute;
};

struct Appointments {
    struct Appointment *a;
    size_t capacity, next_capacity, number;
};

/** Ensures that {as} has at least {min} entries.
 @return Success. */
static int reserve(struct Appointments *const as, const size_t min) {
    struct Appointment *a;
    size_t c0, c1;
    assert(as);

    /* Already have enough. */
    if(min <= as->capacity) return 1;

    /* Calculate increase by Fibbinocci. */
    if(!as->a) c0 = 8, c1 = 13;
    else c0 = as->capacity, c1 = as->next_capacity;
    while(c0 < min) c0 ^= c1, c1 ^= c0, c0 ^= c1, c1 += c0;
    assert(c0 < c1);

    /* Grow the capacity. */
    if(!(a = realloc(as->a, sizeof *a * c0))) return 0;
    as->a = a;
    as->capacity = c0;
    as->next_capacity = c1;
    return 1;
}

/** Add to {as} an appointment with appointment values.
 @return Success. */
static struct Appointment *appointment(struct Appointments *const as,
    const char *desc, unsigned year, unsigned month, unsigned day,
    unsigned hour, unsigned minute) {
    struct Appointment *a;
    assert(as && desc && month && month <= 12 && day && day < 31
        && hour < 24 && minute < 60);

    /* Add a new entry. */
    if(!reserve(as, as->number + 1)) return 0;
    a = as->a + as->number++;

    /* Copy (part of?) the data. */
    strncpy(a->desc, desc, sizeof a->desc - 1);
    a->desc[sizeof a->desc - 1] = '\0';
    a->year   = year;
    a->month  = month;
    a->day    = day;
    a->hour   = hour;
    a->minute = minute;

    return a;
}

/** Adds a random appointment to {as}.
 @return Success. */
static struct Appointment *add_appointment(struct Appointments *const as) {
    char desc[64];
    /* Shhh, it's a Poisson distibuition. */
    const size_t desc_len = 31 + rand() / (RAND_MAX / 32 + 1);
    size_t i;
    for(i = 0; i < desc_len; i++) desc[i] = (i ? 'a' : 'A')
        + rand() / (RAND_MAX / 26 + 1);
    desc[i] = '\0';
    /* http://c-faq.com/lib/randrange.html */
    return appointment(as, desc, 2000 + rand() / (RAND_MAX / 100 + 1),
        1 + rand() / (RAND_MAX / 12 + 1), 1 + rand() / (RAND_MAX / 28 + 1),
        rand() / (RAND_MAX / 24 + 1), rand() / (RAND_MAX / 60 + 1));
}

int main(void) {
    struct Appointments as = { 0, 0, 0, 0 };
    size_t i = 99, j;
    while(--i) if(!add_appointment(&as)) break;
    for(j = 0; j < as.number; j++) {
        struct Appointment *a = as.a + j;
        printf("%04u-%02u-%02uT%02u:%02u %s\n", a->year, a->month, a->day,
            a->hour, a->minute, a->desc);
    }
    free(as.a), as.a = 0;
    return i ? perror("Appointments"), EXIT_FAILURE : EXIT_SUCCESS;
}

Лучший способ сохранить дату - это совсем другой вопрос. Например, Какой самый лучший тип данных для хранения даты .

0 голосов
/ 18 апреля 2019

Итак, несколько вещей. Во-первых, поскольку строки в c хранятся в виде массива символов, вам действительно понадобится календарь char ***, так как вам нужна строка для каждого номера встречи, затем 4 строки там char * для встречи. Во-вторых, вместо повторного выравнивания дважды, попробуйте прочитать входные данные в буфер, отсканировать буфер, а затем распределить его в соответствии с нужными размерами. Без реального знания спецификаций вашего проекта этот код должен дать вам представление о том, как вы можете форматировать объекты.

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

#define maxApt 3

void addApt(char *** cal, int aptNum){
   char month,day, hour,inBuf[20]="";
   printf("give input\n");
   if(fscanf(stdin, "%s %c %c %c", inBuf,&month, &day, &hour)!=4){
   fprintf(stderr,"poorly formatted input\n");
   return;
 }

 cal[aptNum][0]=(char*)malloc(strlen(inBuf));
 strncpy(cal[aptNum][0], inBuf,20);
 for(int i =1;i<4;i++){
 cal[aptNum][i]=(char*)malloc(1);

 }
  cal[aptNum][1][0]=month;
  cal[aptNum][2][0]=day;
  cal[aptNum][3][0]=hour;


 }
 int main(){
char ***calendar=(char***)malloc(maxApt*sizeof(char**));
for(int i =0;i<maxApt;i++){
 calendar[i]=(char**)malloc(4*sizeof(char*));
 addApt(calendar, i);
 }

  for(int j=0;j<maxApt;j++){
  for(int i =0;i<4;i++){
   printf("%s ", calendar[j][i]);
  }
  printf("\n");
  }



  }

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

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