对在C中使用缓冲区感到困惑

时间:2015-04-21 16:18:27

标签: c buffer lightweight-processes

对于我的任务,我必须使用轻量级进程和常量大小的缓冲区来解决简化的Conway问题。程序读取字符流,将流打包成10个字符的块,并将它们写成24个字符的行。井号('#')字符将用作数据结束(EOD)标记值。我们必须实施以下更改:

每个块后插入一个额外的空白。

每个相邻的星号对都被感叹号取代。只有当星号位于同一个区块内时,才认为它们是相邻的。

我从来没有在C中编程,这给了我适合。我们给了主程序三个进程和缓冲操作的原型。到目前为止,经过几个小时,我只是设法让缓冲区正常工作。这是主程序和函数原型和定义。

typedef struct {
    char *buf;         /* Buffer array */         
    int n;             /* Maximum number of slots */
    int front;         /* buf[(front+1)%n] is first item */
    int rear;          /* buf[rear%n] is last item */
    sem_t mutex;       /* Protects accesses to buf */
    sem_t slots;       /* Counts available slots */
    sem_t items;       /* Counts available items */
    } sbuf_t;

/* Function prototypes: */
void sbuf_init(sbuf_t *sp, int n);
void sbuf_deinit(sbuf_t *sp);
void sbuf_insert(sbuf_t *sp, char item);
char sbuf_remove(sbuf_t *sp);

void* ReadInput(void * vargp);    /* ReadInput thread routine prototype   */
void* Squash(void * vargp);       /* Squash thread routine prototype      */
void* PrintOutput(void * vargp);  /* PrintOutput thread routine prototype */


/* Global constants */
const int BLOCKMAX=10;      /* Length of input "blocks" */
const int LINEMAX=24;       /* Length of output "lines" */
const char EODsentinel='#'; /* End-Of-Data Sentinel value */


/* Global (shared) buffers */
sbuf_t rdbuf; /* Synchronized buffer between ReadInput and Squash   */
sbuf_t prbuf; /* Synchronized buffer between Squash and PrintOutput */


int main(int argc, char* argv[]) 
{
    pthread_t tidReadInput, tidSquash, tidPrintOutput;

    int rdbufsize;    /* buffer size between ReadInput and Squash   */
    int prbufsize;    /* buffer size between Squash and PrintOutput */


    /* Process input arguments */
    if (argc != 3) { 
        printf("usage: %s <rdbufsize> <prbufsize>\n", argv[0]);
        printf("  Using defaults: <rdbufsize=4> <prbufsize=7>\n");
       rdbufsize = 4;
       prbufsize = 7;
    }
    else
    {
        rdbufsize = atoi(argv[1]);
        prbufsize = atoi(argv[2]);
    }

    /* Create shared FIFO buffers */
    sbuf_init(&rdbuf, rdbufsize);
    sbuf_init(&prbuf, prbufsize);

    /* Create threads and wait for them to finish */
    Pthread_create(&tidReadInput,   NULL, ReadInput,   NULL);
    Pthread_create(&tidSquash,      NULL, Squash,      NULL);
    Pthread_create(&tidPrintOutput, NULL, PrintOutput, NULL);

    Pthread_join(tidPrintOutput, NULL);


    /* Clean up shared FIFO buffers */
    printf("\n---cleaning up---\n");
    sbuf_deinit(&rdbuf);
    sbuf_deinit(&prbuf);

    printf("\n---finished---\n");
    exit(0);
}

以下是缓冲操作。

/* Create an empty, bounded, shared FIFO buffer with n slots */
void sbuf_init(sbuf_t *sp, int n)
{
    sp->buf = Calloc(n, sizeof(char)); 
    sp->n = n;                       /* Buffer holds max of n items */
    sp->front = sp->rear = 0;        /* Empty buffer iff front == rear */
    Sem_init(&sp->mutex, 0, 1);      /* Binary semaphore for locking */
    Sem_init(&sp->slots, 0, n);      /* Initially, buf has n empty slots */
    Sem_init(&sp->items, 0, 0);      /* Initially, buf has zero data items */
}

/* Clean up buffer sp */
void sbuf_deinit(sbuf_t *sp)
{
    Free(sp->buf);
}

/* Insert item onto the rear of shared buffer sp */
void sbuf_insert(sbuf_t *sp, char item)
{
    P(&sp->slots);                   /* Wait for available slot */
    P(&sp->mutex);               /* Lock the buffer */
        sp->buf[(++sp->rear)%(sp->n)] = item;   /* Insert the item */
    V(&sp->mutex);               /* Unlock the buffer */
    V(&sp->items);                   /* Announce available item */
}

/* Remove and return the first item from buffer sp */
char sbuf_remove(sbuf_t *sp)
{
    char item;
    P(&sp->items);                   /* Wait for available item */
        P(&sp->mutex);               /* Lock the buffer */
            item = sp->buf[(++sp->front)%(sp->n)];  /* Remove the item */
        V(&sp->mutex);               /* Unlock the buffer */
    V(&sp->slots);                   /* Announce available slot */
    return item;
}

以下是我的3个例程以及到目前为止我所拥有的。

/* ReadInput thread routine */
void* ReadInput(void * vargp)
{
    char ch;
    char newline;

    scanf("%c%c", &ch, &newline);

    while (ch != EODsentinel)
    {
        sbuf_insert(&rdbuf, ch);

        scanf("%c%c", &ch, &newline);
    }
    sbuf_insert(&rdbuf, EODsentinel);

    printf("ReadInput finished\n");

    return NULL;
}

/* Squash thread routine */
void* Squash(void * vargp)
{
    char ch;

    ch = sbuf_remove(&rdbuf);
    while (ch != EODsentinel)
    {
        sbuf_insert(&prbuf, ch);

        ch = sbuf_remove(&rdbuf);
    }
    sbuf_insert(&prbuf, EODsentinel);

    printf("Squash finished\n");

    return NULL;
}

/* PrintOutput thread routine */
void* PrintOutput(void * vargp)
{
    char ch;

    ch = sbuf_remove(&prbuf);
    while (ch != EODsentinel)
    {
        printf("%c", ch);

        ch = sbuf_remove(&prbuf);
    }

    printf("\n");

    printf("PrintOutput finished\n");

    return NULL;
}

我的所有代码现在都是读取输入在缓冲区之间传递它并将其打印出来。我知道我需要做什么但不确定该怎么做。我需要将换行符逻辑添加到PrintOutput,将空间添加逻辑添加到ReadInput,并将星号感叹号逻辑添加到Squash。我的主要问题是使用缓冲区并在适当的位置添加逻辑。 C对我来说是新的,这非常令人困惑。

0 个答案:

没有答案