20170925-20170930C#工作学习周总结

循环队列

C语言环境下实现循环队列,我采取了内存分配的方式,使用指针实现数据拷贝。这个问题本身并没有多大的难度,但有两个地方仍需要引起注意:换行读取和最大容量的设置。循环队列通用的两种区别空队列和满队列的方法:一是设置标记位;二是空一元素的位置出来。这次我使用了第二种方法,但是实际上并没有空出一个位置出来,只是将最大值和实际值相比大了1,比如,需要一个能存放8个元素的队列,我们在这里可以设置maxCount为9,这样在判满函数中也不会出现问题。这种情况下,入队出队均由内存分配完成,会省事很多,以下为主要代码和注释:

#include "stdafx.h"
#include<stdlib.h>
#include"malloc.h"

typedef struct queue
{
    void *pBase;
    size_t elemSize;  //元素大小
    int front;    //指向队列第一个元素  
    int rear;    //指向队列最后一个元素的下一个元素
    int occ;     //循环队列现有元素个数
    int maxCount; //循环队列的最大存储空间  
}Queue, *CirQ;

enum TYPE
{
    SHORT = 1,
    CHAR = 1,
    BOOL = 1,
    INT = 4,
    LONG = 4,
    FLOAT = 4,
    DOUBLE = 8,
};

//新建环形队列,count为元素个数;elemType为元素类型
CirQ CreateQ(int count, TYPE elemType);
//销毁队列,Q为指定队列
void DestroyQ(CirQ Q);

#pragma region 读写函数的声明
//将队列中cnt个数的元素读到buffer开始的内存中,读取失败返回false,成功返回true
bool ReadShort(CirQ Q, void* buffer, int cnt);
bool ReadChar(CirQ Q, void* buffer, int cnt);
bool ReadBool(CirQ Q, void* buffer, int cnt);
bool ReadInt(CirQ Q, void* buffer, int cnt);
bool ReadLong(CirQ Q, void* buffer, int cnt);
bool ReadFloat(CirQ Q, void* buffer, int cnt);
bool ReadDouble(CirQ Q, void* buffer, int cnt);
//将buffer中cnt个数的元素读到Q队列中
bool WriteBool(CirQ Q, void* buffer, int cnt);
bool WriteChar(CirQ Q, void* buffer, int cnt);
bool WriteBool(CirQ Q, void* buffer, int cnt);
bool WriteInt(CirQ Q, void* buffer, int cnt);
bool WriteLong(CirQ Q, void* buffer, int cnt);
bool WriteFloat(CirQ Q, void* buffer, int cnt);
bool WriteDouble(CirQ Q, void* buffer, int cnt);
#pragma endregion


//获取当前队列中指定类型可用元素个数
int GetAcc(CirQ Q);
//获取当前队列中指定类型已有元素个数
int GetElmCount(CirQ Q);
//判空
bool EmptyQueue(CirQ Q);
//判满
bool FullQueue(CirQ Q);

int main()
{
    CirQ p;
#pragma region int
    //创建一个可以装8个int的队列
    p = CreateQ(8, INT);

    int arr[8];
    for (int i = 0; i < 8; i++)
    {
        arr[i] = i;
    }
    int * p2 = (int *)malloc(sizeof(int) * 8);
    bool b = true;
    b = WriteInt(p, arr, 8);

    WriteInt(p, arr, 5);
    ReadInt(p, p2, 3);

#pragma endregion
    //销毁分配内存
    DestroyQ(p);
    free(p2);
    system("pause");
    return 0;
}

CirQ CreateQ(int maxCount, TYPE elemType)
{
    //结构体指针需要初始化
    CirQ NQ = (struct queue*)malloc(sizeof(struct queue));

    //pBase存放数据
    NQ->pBase = (void *)malloc(elemType *maxCount);
    if (NULL == NQ->pBase)
    {
        printf("Memory allocation failure");
        return NULL;        //退出程序  
    }
    NQ->front = 0;         //初始化参数  
    NQ->rear = 0;
    NQ->elemSize = elemType;
    NQ->maxCount = maxCount + 1;//预留一个空位置,为了取余并不预留实际位置
    NQ->occ = 0;

    return NQ;
}

void DestroyQ(CirQ Q)
{
    free(Q);
}

#pragma region reads
bool ReadInt(CirQ Q, void* buffer, int cnt)
{
    errno_t err;
    //对Q判空,若为空,直接返回false
    if (EmptyQueue(Q))
    {
        printf("Error!!!Empty Queue.\n");
        return false;
    }
    //读取元素个数大于现有元素个数,读取溢出
    if (cnt > Q->occ)
    {
        printf("Error!!!Overflow.\n");
        return false;
    }
    //以整数为例
    int * p = (int*)(Q->pBase);

    //判断是否需要读两次
    if ((Q->front + cnt) <= Q->maxCount)
    {
        //如果不需要换方向,一次性拷贝完全
        err = memcpy_s(buffer, (cnt * Q->elemSize), p + Q->front, (cnt * Q->elemSize));
        if (err)
        {
            printf("Error executing memcpy_s.\n");
            return false;
        }
        else
        {
            Q->occ = Q->occ - cnt;
            //向前移动指针
            Q->front = (Q->front + cnt) % Q->maxCount;

            return true;
        }
    }
    else
    {
        //换方向了分两次读
        int* bufferTmp = (int*)buffer;
        err = memcpy_s(buffer, ((Q->maxCount - 1 - Q->front) * Q->elemSize), p + Q->front, ((Q->maxCount-1 - Q->front) * Q->elemSize));
        int left = cnt - (Q->maxCount-1 - Q->front);

        if (err)
        {
            printf("Error executing memcpy_s.\n");
            return false;
        }
        else
        {
            Q->occ = Q->occ - (Q->maxCount - 1 - Q->front);

            //buffer也要往前移动,写入到接下来的起始位置

            bufferTmp = bufferTmp + (Q->maxCount - 1 - Q->front);
            //向前移动指针
            Q->front = (Q->front + (Q->maxCount - Q->front)) % Q->maxCount;


            //return true;
        }


        err = memcpy_s(bufferTmp, ((left * Q->elemSize) * Q->elemSize), p + Q->front, (left * Q->elemSize));
        if (err)
        {
            printf("Error executing memcpy_s.\n");
            return false;
        }
        else
        {
            Q->occ = Q->occ - left;
            //向前移动指针
            Q->front = (Q->front + left) % Q->maxCount;
            return true;
        }
    }
}
#pragma endregion


#pragma region 不同类型的写
bool WriteInt(CirQ Q, void* buffer, int cnt)
{
    errno_t err;
    //对Q判满,若为空,直接返回false
    if (FullQueue(Q))
    {
        printf("Error!!!Full Queue.\n");
        return false;
    }
    //存储元素个数大于可用元素个数,存储溢出
    if (cnt > (Q->maxCount - Q->occ - 1))
    {
        printf("Error!!!Overflow.\n");
        return false;
    }
    //以整数为例
    int * QTmp = (int*)(Q->pBase);
    //判断是否需要写两次
    if ((Q->rear + cnt) <= Q->maxCount)
    {
        //如果不需要换方向,一次性拷贝完全
        err = memcpy_s(QTmp + Q->rear, (cnt * Q->elemSize), buffer, (cnt * Q->elemSize));
        if (err)
        {
            printf("Error executing memcpy_s.\n");
            return false;
        }
        else
        {
            Q->occ = Q->occ + cnt;
            //向前移动指针
            Q->rear = (Q->rear + cnt) % Q->maxCount;
            return true;
        }
    }
    else
    {
        //换方向了分两次写
        int* bufferTmp = (int*)buffer;
        err = memcpy_s(QTmp + Q->rear, ((Q->maxCount - 1 - Q->rear) * Q->elemSize), buffer, ((Q->maxCount - 1 - Q->rear) * Q->elemSize));
        int left = cnt - (Q->maxCount-1 - Q->rear);

        if (err)
        {
            printf("Error executing memcpy_s.\n");
            return false;
        }
        else
        {
            Q->occ = Q->occ + (Q->maxCount-1 - Q->rear);


            //buffer也要往前移动,写入到接下来的起始位置

            bufferTmp = bufferTmp + (Q->maxCount-1 - Q->rear);

            //向前移动指针
            Q->rear = (Q->rear + (Q->maxCount - Q->rear)) % Q->maxCount;
            //return true;
        }


        err = memcpy_s(QTmp + Q->rear, (left * Q->elemSize), bufferTmp, (left * Q->elemSize));
        if (err)
        {
            printf("Error executing memcpy_s.\n");
            return false;
        }
        else
        {
            Q->occ = Q->occ + left;
            //向前移动指针
            Q->rear = (Q->rear + left) % Q->maxCount;
            return true;
        }
    }
}
#pragma endregion

//判断是否为空
bool EmptyQueue(CirQ Q)
{
    if (Q->front == Q->rear)
        return true;
    else
        return false;
}

//进队(以整数为例)
bool Enqueue(CirQ Q, int val)
{
    if (FullQueue(Q))
        return false;
    else
    {
        int * p = (int*)(Q->pBase);
        p[Q->rear] = val;

        //((int*)Q->pBase)[Q->rear] = val;这样是对的
        //Q->pBase[Q->rear] = val;//这样是错误的,原因:void*不能++
        Q->rear = (Q->rear + 1) % Q->maxCount;
        return true;
    }
}

//判满
bool FullQueue(CirQ Q)
{
    if (Q->front == (Q->rear + 1) % Q->maxCount)    //判断循环链表是否满,留一个预留空间不用  
        return true;
    else
        return false;
}

//获取当前队列中指定类型可用元素个数
int GetAcc(CirQ Q)
{
    return (Q->maxCount - Q->occ);
}

//获取当前队列中指定类型已有元素个数
int GetElmCount(CirQ Q)
{
    return (Q->occ);
}

网络协议之命名管道(Named Pipes)

Named Pipes 是为局域网而开发的协议。 内存的一部分被某个进程用来向另一个进程传递信息,因此一个进程的输出就是另一个进程的输入。 第二个进程可以是本地的(与第一个进程位于同一台计算机上),也可以是远程的(位于联网的计算机上)。

命名管道是管道通信的一种,另外一种是匿名管道。匿名管道只能用在父子进程之间;命名管道可以用在两个进程通信。【进程间通信

使用命名管道进行网络进程间通信

以上链接是MSDN关于C#下使用命名管道通信的示例。可供参考。

以及一篇比较有价值的博文C#命名管道通信

其次,有CodeProject上的源码在project文件夹,亦可参考。如果使用命名管道在进程之间传送文件,可以参考上次socket编程部分。


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值