0

I want to write a C program, where I have an array of 10 strings, where each string denotes the license plate number of the car parked at spot i. A spot is picked at random and if it is vacant, a random license plate number is generated and assigned to that spot, and if it is occupied, then the spot is vacated and the license plate number is deleted. However, the program is going into an infinite loop, which is what I want, but it is not printing any statements I have written to debug the program. The code is as follows:

#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <time.h>
#include <stdint.h>

char * generateLicense()
{
    srand((unsigned)time(NULL));
    char const *code[] = {"AN","AP","AR","AS","BR","CG","CH","DD","DL","DN","GA","GJ","HR","HP","JH","JK","KA","KL","LD","MH","ML","MP","MN","MZ","NL","OD","PB","PY","RJ","SK","TN","TR","TS","UK","UP","WB"};
    char const *alphabets[] = {"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 const *numbers[] = {"0","1","2","3","4","5","6","7","8","9"};  
    char *licensePlate = (char *)malloc(100*sizeof(char));
    strcpy(licensePlate,code[rand()%36]);
    strcat(licensePlate,"-");
    strcat(licensePlate,numbers[rand()%10]);
    strcat(licensePlate,numbers[rand()%10]);
    strcat(licensePlate,"-");
    strcat(licensePlate,alphabets[rand()%26]);
    strcat(licensePlate,alphabets[rand()%26]);
    strcat(licensePlate,"-");
    strcat(licensePlate,numbers[rand()%10]);
    strcat(licensePlate,numbers[rand()%10]);
    strcat(licensePlate,numbers[rand()%10]);
    strcat(licensePlate,numbers[rand()%10]);
    return licensePlate;    
}

int main()
{
    char *messagebody = (char *)malloc(100*sizeof(char));
    char *licensePlate = (char *)malloc(100*sizeof(char));
    char *currentSpot = (char *)malloc(10*sizeof(char));
    char *by = ", by: ";
    char *client = "From client 1, ";
    char *spots[] = {"00-00-00-0000","00-00-00-0000","00-00-00-0000","00-00-00-0000","00-00-00-0000","00-00-00-0000","00-00-00-0000","00-00-00-0000","00-00-00-0000","00-00-00-0000"};
    int spot;
    printf("variables declared\n");
    srand((unsigned)time(NULL));
    while(1)
    {
        printf("in while loop\n");
        //messagebody = "";
        //licensePlate = "";
        spot = rand()%10;
        //currentSpot = "";
        sprintf(currentSpot, "%d", spot);
        printf("%s",currentSpot);
        strcpy(messagebody,client);
        printf("%s",messagebody);
        if(spots[spot] == "00-00-00-0000")
        {
            printf("%s",messagebody);
            strcpy(licensePlate, generateLicense());
            printf("%s",licensePlate);
            strcpy(spots[spot], licensePlate);
            strcat(messagebody,"spot occupied: ");
            printf("%s",messagebody);
            strcat(messagebody,currentSpot);
            printf("%s",messagebody);
            strcat(messagebody,by);
            printf("%s",messagebody);
            strcat(messagebody,licensePlate);
            printf("%s",messagebody);
        }
        else
        {
            printf("%s",messagebody);
            strcpy(licensePlate, spots[spot]);
            strcpy(spots[spot],"00-00-00-0000");
            strcat(messagebody,"spot vacated: ");
            printf("%s",messagebody);
            strcat(messagebody,currentSpot);
            printf("%s",messagebody);
            strcat(messagebody,by);
            printf("%s",messagebody);
            strcat(messagebody,licensePlate);
            printf("%s",messagebody);
        }
        printf("%s",messagebody);
        sleep(5);
    }
    return 0;
}

I have included the statements I wrote to debug the program as well. What am I doing wrong here?

  • 1
    At first sight: Please call `srand` only once at the beginning of `main`. Calling it repeatedly won't make it "more random". On the contrary, with one-second granularity you will repeatedly reset the seed to the same value. – M Oehm Aug 23 '17 at 05:53
  • 1
    [Please see this discussion on why not to cast the return value of malloc() and family in C..](https://stackoverflow.com/q/605845/2173917) – Sourav Ghosh Aug 23 '17 at 05:54
  • on which system/os do you run your program? did you try to reduce the printf calls and in increase loop time ? – twooBeers Aug 23 '17 at 05:54
  • 4
    `if(spots[spot] == "00-00-00-0000")` -- This doesn't do what you think it does. It compares pointers. It might be useful to initialise all `spots`to `NULL` – M Oehm Aug 23 '17 at 05:55
  • 2
    I suggest flushing the output buffer, either by adding a newline `\n` at the end of each message, or with `fflush(stdout);` – Weather Vane Aug 23 '17 at 06:00
  • 2
    You have a memory leak: you allocate memory for `char *licensePlate` but never `free` it. – Weather Vane Aug 23 '17 at 06:07

1 Answers1

4

Your program has an access violation: spots is an array of ten string literals:

char *spots[] = {
    "00-00-00-0000",
    "00-00-00-0000",
    "00-00-00-0000",
    ...
};

These literals are immutable and it is an arror to try to change them.

Instead, define an array of ten char arrays that can hold your number plates. You need space for your pattern 2-2-2-4 plus one char for the null terminator:

char spots[10][14] = {""};

Now spotsare ten empty strings of max. length 13. You can testwhether you have overwritten them already with:

if (*spots[spot] == '\0') ... // string is empty

There are more problems to your code:

  • The dynamic memory allocation is really unnecessary for such a small program and make it complicated. You have 10 slots with 13-letter licence plates, which can easily be created in automatic memory.
  • Dont allocate memory forthe licence plate and then strcpy. Create the licence plate directly by passing the 14-char buffer to a function that fills it.
  • The longish strcat sequences are very clumsy. Consider using snprintf, which will create a licence plate in nearly one go.

Here's a concise implementation of your problem that is limited to 30 parking actions:

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

void make_license(char str[])
{
    static const char *code[] = {
        "AN", "AP", "AR", "AS", "BR", "CG", "CH", "DD", "DL",
        "DN", "GA", "GJ", "HR", "HP", "JH", "JK", "KA", "KL",
        "LD", "MH", "ML", "MP", "MN", "MZ", "NL", "OD", "PB",
        "PY", "RJ", "SK", "TN", "TR", "TS", "UK", "UP", "WB"
    };

    snprintf(str, 14, "%s-%02d-%c%c-%04d",
        code[rand() % 36], rand() % 100, 
        'A' + rand() % 26, 'A' + rand() % 26,
        rand() % 10000);    
}

int main()
{
    char spots[10][14] = {""};
    int n = 30;

    srand(time(NULL));

    while (n--) {
        int spot = rand() % 10;

        if (*spots[spot]) {
            printf("Car %s leaves spot %d.\n", spots[spot], spot + 1);

            *spots[spot] = '\0';            // remove licence plate
        } else {
            make_license(spots[spot]);      // create licence plate

            printf("Car %s arrives at spot %d.\n", spots[spot], spot + 1);
        }
    }

    puts("");
    puts("Final arrangement");

    for (n = 0; n < 10; n++) {
        printf("%4d %s\n", n + 1, spots[n]);
    }

    return 0;
}

If you want to use dynamic allocation (perhaps it was a requirement of the assignment), you should Make the licenseplates pointers to strings. Initialise them to NULL, free them if you remove them from the list and also be sure to free any remaining strings after you're done:

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

char *make_license(void)
{
    static const char *code[] = {
        "AN", "AP", "AR", "AS", "BR", "CG", "CH", "DD", "DL",
        "DN", "GA", "GJ", "HR", "HP", "JH", "JK", "KA", "KL",
        "LD", "MH", "ML", "MP", "MN", "MZ", "NL", "OD", "PB",
        "PY", "RJ", "SK", "TN", "TR", "TS", "UK", "UP", "WB"
    };

    char *str = malloc(14);

    snprintf(str, 14, "%s-%02d-%c%c-%04d",
        code[rand() % 36], rand() % 100, 
        'A' + rand() % 26, 'A' + rand() % 26,
        rand() % 10000);

    return str; 
}

int main()
{
    char *spots[10] = {NULL};
    int n = 30;

    srand(time(NULL));

    while (n--) {
        int spot = rand() % 10;

        if (spots[spot]) {
            printf("Car %s leaves spot %d.\n", spots[spot], spot + 1);

            free(spots[spot]);
            spots[spot] = NULL;             // remove licence plate
        } else {
            spots[spot] = make_license();   // create licence plate

            printf("Car %s arrives at spot %d.\n", spots[spot], spot + 1);
        }
    }

    puts("");
    puts("Final arrangement");

    for (n = 0; n < 10; n++) {
        printf("%4d %s\n", n + 1, spots[n] ? spots[n] : "--");
        free(spots[n]);
    }

    return 0;
}

But you should clearly decide which approach you take. Your program ist a bit in between: It allocates memory and then tries to strcpy around the data as if you were using automatic memory buffers.

M Oehm
  • 28,726
  • 3
  • 31
  • 42