环形buffer缓冲区
1 #include <stdio.h> 2 #include <string.h> 3 #include <malloc.h> 4 5 struct CircleBuf 6 { 7 char *pFirst;//指向循环表开始的位置 8 char *pLast;//指向循环表结尾的位置 9 char *plSave;//指向最后一个存数据的后一位,没有数据为NULL,或与pfsave相等 10 char *pfSave;//指向第一个存数据的位置,没有数据为NULL,或与plsave相等 11 int iSize;//循环表的大小 12 int iDataNum;//存数据的大小 13 }; 14 15 int InitCircleBuf(struct CircleBuf *buf, const int bufSize) 16 //初始化缓冲区。buf为目标缓冲区。字节数为bufSize,能存储bufSize 个字符 17 //操作成功返回1,操作失败返回0. 18 { 19 buf->pFirst = (char*)malloc((bufSize + 1)*(sizeof(char)));//初始化CiecleLink 20 if(NULL == buf->pFirst) 21 { 22 printf("\nMemory allocation failure !\n"); 23 return 0; 24 } 25 buf->iSize = bufSize; 26 buf->iDataNum = 0; 27 buf->pfSave = NULL; 28 buf->plSave = NULL; 29 buf->pLast = buf->pFirst + buf->iSize; 30 return 1; 31 } 32 33 void DestroyCircleBuf(struct CircleBuf *buf) 34 //销毁环形缓冲区 35 { 36 free(buf->pFirst); 37 buf->iDataNum = 0; 38 buf->iSize = 0; 39 buf->pFirst = NULL; 40 buf->pLast = NULL; 41 buf->plSave = NULL; 42 buf->pfSave = NULL; 43 } 44 45 void ClearCircleBuf(struct CircleBuf *buf) 46 //清空环形缓冲区 47 { 48 buf->plSave = NULL; 49 buf->pfSave = NULL; 50 buf->iDataNum = 0; 51 } 52 53 int InCircleBuf(struct CircleBuf *buf, char *str, int length) 54 //向循环表存入数据。buf为目标循环表,str为源字符串地址,存入的字节数为length 55 //操作成功返回 1, 操作失败返回 0 56 { 57 int i; 58 int j; 59 int len; 60 int lengthtem; 61 len = strlen(str); 62 if(len < length) 63 { 64 printf("the length is longer then the size of str !\n"); 65 return 0; 66 67 } 68 69 if((NULL == buf->pfSave) &&(NULL == buf->plSave))//CircleBuf为空时 70 { 71 if(length > (buf->iSize - 1)) 72 { 73 printf("length is longer then the size of Circlebuf !\n"); 74 return 0; 75 } 76 else 77 { 78 79 strncpy(buf->pFirst, str, length); 80 buf->pfSave = buf->pFirst; 81 buf->plSave = buf->pfSave + length; 82 buf->iDataNum += length; 83 84 } 85 } 86 else if(buf->pfSave <= buf->plSave)//pfsave小于或等于plsave,存数据没有超过结尾处 87 { 88 89 if(length < (buf->pLast - buf->plSave + 1))//存数据的length没有达到CircleBuf结尾 90 { 91 92 strncpy(buf->plSave, str, length); 93 buf->iDataNum += length; 94 buf->plSave += length; 95 } 96 else if(length == (buf->pLast - buf->plSave + 1))//存数据的length刚好到CircleBuf结尾处 97 { 98 99 if(buf->pfSave > buf->pFirst) 100 { 101 strncpy(buf->plSave, str, length); 102 buf->iDataNum += length; 103 buf->plSave = buf->pFirst; 104 } 105 else 106 { 107 printf("the length is longer then the unused space !\n"); 108 return 0; 109 } 110 } 111 else //存数据的length长度超过CircleBuf结尾 112 { 113 114 if(length > ((buf->pLast - buf->plSave)+(buf->pfSave - buf->pFirst))) 115 //存数据的length大于剩余空间大小 116 { 117 printf("length is too long then the unused space!\n"); 118 return 0; 119 } 120 else //存数据的length小于剩余空间大小,将length长度数据分两次存 121 { 122 123 lengthtem = length - (buf->pLast - buf->plSave + 1); 124 for(i=0; i<(buf->pLast - buf->plSave + 1); i++) 125 { 126 *(buf->plSave + i) = str[i]; 127 128 } 129 buf->plSave = buf->pFirst; 130 131 for(j=0; j<lengthtem; j++) 132 { 133 *(buf->plSave + j) = str[i + j]; 134 135 } 136 137 buf->plSave += j; 138 buf->iDataNum += length; 139 140 } 141 } 142 } 143 else if(buf->pfSave > buf->plSave)//pfsave大于plsave,存数据超过结尾处,至少绕了一圈 144 { 145 if(length > (buf->pfSave - buf->plSave))//存数据的length大于剩余空间大小 146 { 147 printf("length is too long then the unsued space!\n"); 148 return 0; 149 } 150 else 151 { 152 strncpy(buf->plSave, str, length); 153 buf->iDataNum += length; 154 buf->plSave += length; 155 } 156 } 157 return 1; 158 } 159 160 161 int OutCircleBuf(char *str, struct CircleBuf *buf, int length) 162 //从循环表中取数据。 str为目标字符串地址, buf为源循环表, 取出的字节数为length 163 //操作成功返回 1, 操作失败返回 0 164 { 165 int i; 166 int j; 167 int lengthtem; 168 169 if((NULL == buf->pfSave) &&(NULL == buf->plSave))//CircleBuf为空 170 { 171 printf("the Circlebuf is empty !\n"); 172 return 0; 173 } 174 175 if(buf->pfSave < buf->plSave)//pfsave小于plsave,存的数据没有超过结尾 176 { 177 if((buf->pfSave + length) > buf->plSave) 178 { 179 printf("length is longer then the used of Circlebuf !\n"); 180 return 0; 181 } 182 else 183 { 184 strncpy(str, buf->pfSave, length); 185 buf->pfSave += length; 186 buf->iDataNum -= length; 187 } 188 } 189 else if(buf->pfSave == buf->plSave)//pfsave等于plsave,CircleBuf为空 190 { 191 printf("there is no data in Circlebuf !\n"); 192 return 0; 193 } 194 else if(buf->pfSave > buf->plSave)//pfsave大于plsave,存的数据超过结尾,至少绕了一圈 195 { 196 197 if(length < (buf->pLast - buf->pfSave + 1))//取数据的length没到结尾 198 { 199 strncpy(str, buf->pfSave, length); 200 buf->pfSave += length; 201 buf->iDataNum -= length; 202 } 203 else if(length == (buf->pLast - buf->pfSave + 1))//取数据的length刚好达到结尾处 204 { 205 strncpy(str, buf->pfSave, length); 206 buf->pfSave = buf->pFirst; 207 buf->iDataNum -= length; 208 } 209 else //取数据的length超过结尾 210 { 211 212 if((length - (buf->pLast - buf->pfSave + 1)) > (buf->plSave - buf->pFirst)) 213 //取数据的length大于剩余数据的大小 214 { 215 printf("%d\n",(buf->plSave - buf->pFirst)); 216 printf("the used data is shorter then length !\n"); 217 return 0; 218 } 219 else //取数据的length小于剩余数据的大小,将数据分开两次取出来 220 { 221 lengthtem = length - (buf->pLast - buf->pfSave + 1); 222 for(i=0; i<(buf->pLast - buf->pfSave + 1); i++) 223 { 224 str[i] = *(buf->pfSave +i); 225 } 226 buf->pfSave = buf->pFirst; 227 for(j=0; j<lengthtem; j++) 228 { 229 str[i + j] = *(buf->pfSave + j); 230 } 231 buf->pfSave += j; 232 buf->iDataNum -= length; 233 } 234 } 235 } 236 str[length] = '\0'; 237 return 1; 238 } 239 240 int CalDataNumCB(struct CircleBuf *buf) 241 //计算循环表的数据个数。buf为目标循环表 242 //返回已存放数据的字节数 243 { 244 return buf->iDataNum; 245 } 246 247 int CalSpaceNumCB(struct CircleBuf *buf) 248 //计算循环表的剩余空间大小。 buf为目标循环表 249 //返回剩余空间字节数 250 { 251 return (buf->iSize - buf->iDataNum); 252 } 253 254 255 int OutCBtoFile(char *filename, struct CircleBuf *buf) 256 //将循环表中所有的数据都存到所给的文件中,filename为目标文件的路径及名称,buf为源循环表。 257 //操作成功返回 1, 操作失败返回 0 258 { 259 FILE *fp; 260 int i; 261 int length; 262 char ch[2]; 263 if(NULL == (fp = fopen(filename, "wt+")))//判断文件是否打开 264 { 265 printf("can't open %s !\n", filename); 266 return 0; 267 } 268 length = CalDataNumCB(buf); 269 270 271 for(i=0; i<length; i++) //将全部数据读入文件中 272 { 273 OutCircleBuf(ch, buf, 1); 274 printf("%d %c \n", strlen(ch), ch[0]); 275 fwrite(ch, 1, 1, fp); 276 277 } 278 279 fclose(fp); 280 return 1; 281 } 282 283 284 int InCBfromFile(struct CircleBuf *buf, char *filename) 285 //将文件中的数据读到循环链表中,clink为目标链表,filename为源文件的路径及名称。 286 //操作失败返回0, 文件数据全部存储完毕返回1, clink空间不足,只存入部分数据返回-1 287 { 288 FILE *fp; 289 int length; 290 char ch; 291 292 if(NULL == (fp = fopen(filename, "rt+")))// 文件打开失败 293 { 294 printf("can't open %s !\n", filename); 295 return 0; 296 } 297 else 298 { 299 length = CalSpaceNumCB(buf); 300 if(0 == length) //循环表数据已满 301 { 302 printf("CircleLink is full!\n"); 303 return 0; 304 } 305 else 306 { 307 while(1) 308 { 309 if(0 == length ) //循环表空间已满,还有部分数据未读入 310 { 311 printf("CircleBuf is full, some data still in file %s !\n", filename); 312 return -1; 313 } 314 else 315 { 316 ch = fgetc(fp); 317 if(ch == EOF) 318 { 319 printf("file %s is over, data are in Circlebuf now!\n", filename); 320 //文件数据全部读完,并存入表中 321 return 1; 322 } 323 else 324 { 325 326 InCircleBuf(buf, &ch, 1); 327 length--; 328 } 329 330 } 331 332 } 333 334 } 335 } 336 return 1; 337 }
----------------陌上阡头,草长莺飞-----------------
https://www.cnblogs.com/tyche116/
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】凌霞软件回馈社区,博客园 & 1Panel & Halo 联合会员上线
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】博客园社区专享云产品让利特惠,阿里云新客6.5折上折
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步