简体   繁体   中英

Adding both string and single char values to same multi-dimensional list

So as the title says. I want to do a multi-dimensional list where each rows first column is a description and rest of the columns are month, day and hour of the descripted appointment. So basically the whole list is a calendar where each row is one appointment. Where I'm having serious trouble is handling the fact that the first column is of a different type than the others. I was considering making a linked list instead but I later have to sort out the rows by time and date and the thought of comparing those on a linked list felt difficult.

I think this feels harder than it is. I think I'm messing the memory allocation of the array since I'm pretty new with 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;

}

So description max size is 20. And I know I should add '\\0' which I desperately try to do. "a" comes from main function and tells the current number of appointments in the calendar. The if loop is there because the memory allocation for the first appointment is being made on the main function. The program already fails after writing the description on the command line and refuses to ask even the month after that.

So a few things. First, since strings in c are stored as an array of characters you will really need an char*** calendar as you need a row for each appointment number, then 4 rows of there of char* for appointment. Second, instead of reallocing twice, try to read the input into a buffer, scan the buffer, then allocate according to the sizes you need. Without really knowing your project specifications this code should give you an idea of how you could format things.

#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");
  }



  }

Note if you want peoples description to be able to have spaces you will need to parse in a more sophisticated way.

Instead of a multidimensional array, I think this would be better suited to a struct : it's clearer and more extensible. If you want to grow the data, than keeping a capacity that grows exponentially has a much nicer limiting behaviour. As well, separating the interface from the logic behind is a good idea.

#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;
}

The best way to store a date is a whole different question. For example, What is the best datatype to store a date .

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM