纯C分割 字符串 devC++版本 vs各种奇怪的问题,
上一篇的分割字符串,在少量字符的情况下可以正常用,但是 字串在几万的时候就有问题,不清楚是什么情况
因此 去github上 https://github.com/jwlodek/csplit 看了下,感觉这个文件写的还可以,至少devc运行没有任何问题。但是 vs 会报错
vs 修改了下 其中 477 行 会报错 主要是因为
DEV-C++使用的编译器是GCC,它允许使用变量作为数组的长度定义数组。
VC的编译器不是GCC,它不允许你这样做。
1 /******************************************************************************** 2 * MIT License 3 * 4 * Copyright (c) 2019 Jakub Wlodek 5 * 6 * Permission is hereby granted, free of charge, to any person obtaining a copy 7 * of this software and associated documentation files (the "Software"), to deal 8 * in the Software without restriction, including without limitation the rights 9 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 * copies of the Software, and to permit persons to whom the Software is 11 * furnished to do so, subject to the following conditions: 12 * 13 * The above copyright notice and this permission notice shall be included in all 14 * copies or substantial portions of the Software. 15 * 16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 22 * SOFTWARE. 23 *********************************************************************************/ 24 25 /** 26 * @defgroup intern Internal 27 * @brief Internal functions, not intended to be used by users 28 * @defgroup set Setup 29 * @brief Setup and Diagnostic functions used by csplit 30 * @defgroup core csplit Core 31 * @brief Core functions included in csplit 32 */ 33 34 /** 35 * A single-header C library for string manipulation and splitting. 36 * 37 * Author: Jakub Wlodek 38 * Created: 02-Aug-2019 39 */ 40 41 #define _CRT_SECURE_NO_WARNINGS 42 #pragma warning(disable:4996) 43 // Include guard - avoid redefinition 44 #ifndef CSPLIT_H 45 #define CSPLIT_H 46 47 #ifdef __cplusplus 48 extern "C" { 49 #endif 50 51 // some basic includes 52 #include <stdio.h> 53 #include <string.h> 54 #include <stdlib.h> 55 #include <ctype.h> 56 57 #ifdef _MSC_VER 58 # define _CSPLIT_FUNC static __inline 59 #elif !defined __STDC_VERSION__ || __STDC_VERSION__ < 199901L 60 # define _CSPLIT_FUNC static __inline__ 61 #else 62 # define _CSPLIT_FUNC static inline 63 #endif 64 65 /** 66 * Enum type for error codes for csplit 67 * @ingroup set 68 */ 69 typedef enum CSPLIT_ERROR { 70 CSPLIT_SUCCESS = 0, /**< No Error */ 71 CSPLIT_TOO_SHORT = -1, /**< Input string is too short */ 72 CSPLIT_NO_SUCH_INDEX = -2, /**< Index out of range */ 73 CSPLIT_UNIMPLEMENTED = -3, /**< Function unimplemented */ 74 CSPLIT_BUFF_EXCEEDED = -4, /**< Buffer size exceeded */ 75 } CSplitError_t; 76 77 78 /** 79 * Struct for an individual string fragment result from csplit 80 * @ingroup intern 81 */ 82 typedef struct CSPLIT_FRAGMENT { 83 char* text; /**< Text of the fragment. */ 84 struct CSPLIT_FRAGMENT* next; /**< Next fragment in the linked list */ 85 struct CSPLIT_FRAGMENT* prev; /**< Previous fragment in the linked list */ 86 } CSplitFragment_t; 87 88 89 /** 90 * Struct that stores the csplit linked list. Can be used as an arbitrary linked list 91 * for strings, but is intended for use with csplit strtok replacement functions 92 * @ingroup core 93 */ 94 typedef struct CSPLIT_LIST { 95 int num_elems; /**< Number of elements in the list */ 96 CSplitFragment_t* head; /**< Head of the linked list (first element) */ 97 CSplitFragment_t* tail; /**< Tail of the linked list (last element) */ 98 } CSplitList_t; 99 100 101 /* Function Declarations */ 102 103 _CSPLIT_FUNC 104 CSplitList_t* csplit_init_list(); 105 106 _CSPLIT_FUNC 107 void csplit_clear_list(CSplitList_t* list); 108 109 _CSPLIT_FUNC 110 CSplitError_t csplit_push_to_list(CSplitList_t* list, CSplitFragment_t* fragment, int buff_size); 111 112 _CSPLIT_FUNC 113 void csplit_print_list_info(CSplitList_t* list, FILE* fp); 114 115 #ifdef CSPLIT_DEBUG 116 _CSPLIT_FUNC 117 void print_csplit_fragment_info(CSplitFragment_t* fragment, FILE* fp); 118 #endif 119 120 _CSPLIT_FUNC 121 char* csplit_get_fragment_at_index(CSplitList_t* list, int index); 122 123 _CSPLIT_FUNC 124 CSplitError_t csplit_reverse_list(CSplitList_t* list); 125 126 _CSPLIT_FUNC 127 char* csplit_strip(char* input_str); 128 129 _CSPLIT_FUNC 130 char* csplit_remove_whitespace(char* input_str); 131 132 _CSPLIT_FUNC 133 int csplit_startswith(char* input_str, char* starts_with); 134 135 _CSPLIT_FUNC 136 int csplit_endswith(char* input_str, char* ends_with); 137 138 _CSPLIT_FUNC 139 CSplitError_t csplit_rstr(CSplitList_t* list, char* input_str, char* token, int max_splits); 140 141 _CSPLIT_FUNC 142 CSplitError_t csplit_str(CSplitList_t* list, char* input_str, char* token, int max_splits); 143 144 _CSPLIT_FUNC 145 CSplitError_t csplit_lim(CSplitList_t* list, char* input_str, char* token, int max_splits); 146 147 _CSPLIT_FUNC 148 CSplitError_t csplit(CSplitList_t* list, char* input_str, char* token); 149 150 _CSPLIT_FUNC 151 CSplitError_t rcsplit(CSplitList_t* output_list, char* input_str, char* token); 152 153 154 /* Function Definitions */ 155 156 157 /** 158 * @brief Function for initializing a csplit list 159 * @ingroup set 160 * 161 * @params[in]: buff_size -> user set buffer size. Make sure this is large enough for your largest fragment 162 * @return: list -> an allocated csplit list 163 */ 164 _CSPLIT_FUNC 165 CSplitList_t* csplit_init_list() { 166 CSplitList_t* list = (CSplitList_t*)calloc(1, sizeof(CSplitList_t)); 167 list->num_elems = 0; 168 return list; 169 } 170 171 172 /** 173 * @brief Clears all memory for an allocated csplit list 174 * @ingroup set 175 * 176 * @params[in]: list -> a previously allocated csplit list to be freed 177 */ 178 _CSPLIT_FUNC 179 void csplit_clear_list(CSplitList_t* list) { 180 CSplitFragment_t* current_fragment = list->head; 181 while (current_fragment != NULL) { 182 CSplitFragment_t* temp = current_fragment->next; 183 free(current_fragment->text); 184 free(current_fragment); 185 current_fragment = temp; 186 } 187 free(list); 188 } 189 190 191 /** 192 * @brief Function that pushes a new CSplitFragment to the end of the list, and allocates memory for the text, 193 * with size list->BUFF_SIZE 194 * @ingroup intern 195 * 196 * @params[out]: list -> The list with fragment appended to the tail 197 * @params[in]: fragment -> fragment to append to the list. fragment->text will be allocated based on list->BUFF_SIZE 198 */ 199 _CSPLIT_FUNC 200 CSplitError_t csplit_push_to_list(CSplitList_t* list, CSplitFragment_t* fragment, int buff_size) { 201 // first make sure neither is null 202 if (list == NULL || fragment == NULL) { 203 return CSPLIT_TOO_SHORT; 204 } 205 else { 206 // then update the number of elements, and the pointers 207 list->num_elems = list->num_elems + 1; 208 if (list->head == NULL) { 209 list->head = fragment; 210 list->tail = fragment; 211 } 212 else { 213 list->tail->next = fragment; 214 fragment->prev = list->tail; 215 list->tail = fragment; 216 } 217 // allocate fragment text field 218 fragment->text = (char*)calloc(1, buff_size); 219 } 220 return CSPLIT_SUCCESS; 221 } 222 223 224 /** 225 * @brief Function that prints information about a csplit list 226 * @ingroup set 227 * 228 * @params[in]: list -> list for which to print info 229 * @params[in]: fp -> file pointer to print into. 230 */ 231 _CSPLIT_FUNC 232 void csplit_print_list_info(CSplitList_t* list, FILE* fp) { 233 if (list == NULL || fp == NULL) return; 234 fprintf(fp, "List contains %d elements\n", list->num_elems); 235 fprintf(fp, "Supports indexes -%d to %d.\n", list->num_elems, list->num_elems - 1); 236 CSplitFragment_t* current_fragment = list->head; 237 while (current_fragment != NULL) { 238 fprintf(fp, "--%s--\n", current_fragment->text); 239 current_fragment = current_fragment->next; 240 } 241 } 242 243 244 #ifdef CSPLIT_DEBUG 245 /** 246 * @brief Function that prints information about a csplit fragment - intended for internal use only 247 * @ingroup intern 248 * 249 * @params[in]: fragment -> fragment for which to print info 250 * @params[in]: fp -> file pointer to print into 251 */ 252 _CSPLIT_FUNC 253 void print_csplit_fragment_info(CSplitFragment_t* fragment, FILE* fp) { 254 if (fragment == NULL || fp == NULL) return; 255 fprintf(fp, "Fragment has text %s\n", fragment->text); 256 if (fragment->next != NULL) fprintf(fp, "Fragment has next with text %s\n", fragment->next->text); 257 if (fragment->prev != NULL) fprintf(fp, "Fragment has prev with text %s\n", fragment->prev->text); 258 } 259 #endif 260 261 262 /** 263 * @brief Function that returns the string fragment at a certain index in the list 264 * @ingroup core 265 * 266 * @params[in]: list -> list generated by csplit 267 * @params[in]: index -> index to search for (can be negative for getting at index from back of list) 268 * @return: text -> string at the given index or NULL if index out of range. 269 */ 270 _CSPLIT_FUNC 271 char* csplit_get_fragment_at_index(CSplitList_t* list, int index) { 272 // convert index into absolute index (if negative); 273 int target_index; 274 if (index < 0) { 275 target_index = index + list->num_elems; 276 } 277 else { 278 target_index = index; 279 } 280 // if index is out of range return null 281 if (list->num_elems <= target_index || target_index < 0) { 282 return NULL; 283 } 284 else { 285 // iterate over list until index found 286 int counter = 0; 287 CSplitFragment_t* current_fragment = list->head; 288 while (counter < target_index) { 289 current_fragment = current_fragment->next; 290 counter++; 291 } 292 // return the text field 293 return current_fragment->text; 294 } 295 } 296 297 298 /** 299 * @brief Function that reverses the list generated by csplit 300 * @ingroup set 301 * 302 * @params[out]: list -> list to reverse 303 * @return: err -> error code if there is an error 304 */ 305 _CSPLIT_FUNC 306 CSplitError_t csplit_reverse_list(CSplitList_t* list) { 307 int i; 308 // iterate over list and swap next and previous fields 309 CSplitFragment_t* temp = list->head; 310 for (i = 0; i < list->num_elems; i++) { 311 CSplitFragment_t* temp2 = temp->next; 312 temp->next = temp->prev; 313 temp->prev = temp2; 314 temp = temp2; 315 } 316 // swap head and tail 317 temp = list->head; 318 list->head = list->tail; 319 list->tail = temp; 320 return CSPLIT_SUCCESS; 321 } 322 323 324 /** 325 * @brief Function that strips a given string into an output string. Will remove whitespace character: 326 * \n, \r, \t, space will be removed from the start and end of each string. 327 * @ingroup core 328 * 329 * @params[in]: input_str -> the input string to strip 330 * @return: output_str -> the string with whitespace removed from the ends. Must be freed. 331 */ 332 _CSPLIT_FUNC 333 char* csplit_strip(char* input_str) { 334 char* output_str; 335 // check if input is null 336 if (input_str == NULL) 337 output_str = NULL; 338 else { 339 int len = strlen(input_str); 340 char* end = input_str + len - 1; 341 char* start = input_str; 342 while (isspace(*start)) { 343 if (*start == '\0' || start == end) return NULL; 344 else start++; 345 } 346 while (isspace(*end)) 347 end--; 348 349 int buff_size = end - start + 1; 350 output_str = (char*)calloc(1, buff_size + 1); 351 strncpy(output_str, start, buff_size); 352 } 353 return output_str; 354 } 355 356 357 /** 358 * @breifFunction that removes all whitespace characters of a given string into an output string. 359 * Note that resulting char* must be free'd after it is no longer used 360 * @ingroup core 361 * 362 * @params[in]: input_str -> the input string to strip 363 * @return: output_str -> the string with whitespace removed. 364 */ 365 _CSPLIT_FUNC 366 char* csplit_remove_whitespace(char* input_str) { 367 char* output_str; 368 if (input_str == NULL) 369 output_str = NULL; 370 else { 371 int len = strlen(input_str); 372 output_str = (char*)calloc(1, len); 373 int counter = 0; 374 int output_counter = 0; 375 // read through but don't copy whitespace 376 while (counter < len) { 377 if (!isspace(input_str[counter])) { 378 output_str[output_counter] = input_str[counter]; 379 output_counter++; 380 } 381 counter++; 382 } 383 } 384 return output_str; 385 } 386 387 388 /** 389 * @brief Function that checks if a given string starts with another given string. 390 * @ingroup core 391 * 392 * @params[in]: input_str -> string to check against 393 * @params[in]: starts_with -> string to try to match with start of input string 394 * @return: int -> -2 if input is invalid, -1 if doesn't start with given string, or 0 if it does 395 */ 396 _CSPLIT_FUNC 397 int csplit_startswith(char* input_str, char* starts_with) { 398 if (input_str == NULL || starts_with == NULL) return -2; 399 else if (strstr(input_str, starts_with) == input_str) return 0; 400 else return -1; 401 } 402 403 404 /** 405 * @brief Function that checks if a given string ends with another given string. 406 * @ingroup core 407 * 408 * @params[in]: input_str -> string to check against 409 * @params[in]: ends_with -> string to try to match with end of input string 410 * @return: int -> -2 if input is invalid, -1 if doesn't end with given string, or 0 if it does 411 */ 412 _CSPLIT_FUNC 413 int csplit_endswith(char* input_str, char* ends_with) { 414 if (input_str == NULL || ends_with == NULL) { 415 return -2; 416 } 417 else { 418 int ewith_len = strlen(ends_with); 419 int istr_len = strlen(input_str); 420 if (ewith_len > istr_len) return -1; 421 else if (strcmp(input_str + istr_len - ewith_len, ends_with) == 0) return 0; 422 else return -1; 423 } 424 } 425 426 427 /** 428 * @brief Function that runs csplit on a particular string from the end of the input. Called if max_splits < 0 429 * @ingroup intern 430 * 431 * @params[out]: list -> split input string into this list structure 432 * @params[in]: input_str -> input string 433 * @params[in]: token -> character on which to split 434 * @params[in]: max_splits -> maximum number of splits. If negative will split from end of string 435 * @return: err -> error code if there was a problem with csplitting. 436 */ 437 _CSPLIT_FUNC 438 439 CSplitError_t csplit_rstr(CSplitList_t* list, char* input_str, char* token, int max_splits) { 440 CSplitError_t err = CSPLIT_SUCCESS; 441 //unsigned int in_len = 1; 442 int in_len = strlen(input_str) > 0 ? strlen(input_str) : 1; 443 int counter = 0; 444 int num_splits = 0; 445 int token_len = strlen(token); 446 char* current_location = input_str; 447 char* arr = malloc(in_len); ///char* arr[in_len]; Vs编译器 会报错 448 while ((arr[counter] = strstr(current_location, token)) != NULL) { 449 current_location = arr[counter] + 1; 450 counter++; 451 } 452 char* last_location = input_str + in_len; 453 while (counter >= 0 && num_splits >= max_splits) { 454 current_location = arr[counter - 1] + token_len; 455 CSplitFragment_t* fragment = (CSplitFragment_t*)calloc(1, sizeof(CSplitFragment_t)); 456 int req_buff_size; 457 if (num_splits == max_splits || counter == 0) { 458 req_buff_size = in_len - strlen(last_location); 459 current_location = input_str; 460 } 461 else 462 req_buff_size = last_location - current_location; 463 err = csplit_push_to_list(list, fragment, req_buff_size); 464 strncpy(fragment->text, current_location, req_buff_size); 465 last_location = current_location - token_len; 466 num_splits--; 467 counter--; 468 } 469 err = csplit_reverse_list(list); 470 free(arr); 471 return err; 472 } 473 474 475 /** 476 * @brief Function that splits a given input string based on another string. 477 * @ingroup intern 478 * 479 * @params[out]: list -> output list splitting input str on string token 480 * @params[in]: input_str -> input string which will be split 481 * @params[in]: token -> string on which to split 482 * @params[in]: max_splits -> max number of splits to perform. Negative if starting from end of string. 483 * @return: err -> error code if there was a problem with csplitting. 484 */ 485 _CSPLIT_FUNC 486 CSplitError_t csplit_str(CSplitList_t* list, char* input_str, char* token, int max_splits) { 487 if (max_splits < 0) 488 return 0;//csplit_rstr(list, input_str, token, max_splits); 489 CSplitError_t err = CSPLIT_SUCCESS; 490 int in_len = strlen(input_str); 491 int num_splits = 0; 492 int token_len = strlen(token); 493 char* current_location = input_str; 494 char* next_location; 495 496 while (current_location != NULL && num_splits <= max_splits) { 497 CSplitFragment_t* fragment = (CSplitFragment_t*)calloc(1, sizeof(CSplitFragment_t)); 498 next_location = strstr(current_location, token); 499 int req_buff_size; 500 if (next_location == NULL || (num_splits == max_splits)) 501 req_buff_size = in_len - (current_location - input_str); 502 else if (next_location != NULL) 503 req_buff_size = next_location - current_location; 504 err = csplit_push_to_list(list, fragment, req_buff_size); 505 strncpy(fragment->text, current_location, req_buff_size); 506 if (next_location != NULL) 507 current_location = next_location + token_len; 508 else { 509 510 current_location = next_location; 511 } 512 num_splits++; 513 } 514 return err; 515 } 516 517 518 519 /** 520 * @brief Function that allows user to split based on a limited number of splits, either forward 521 * or in reverse. A max_splits >= len(input_str) will guarantee all possible splits 522 * @ingroup core 523 * 524 * @params[out]: list -> output list splitting input str on string token 525 * @params[in]: input_str -> input string which will be split 526 * @params[in]: token -> string on which to split 527 * @params[in]: max_splits -> max number of splits to perform. Negative if starting from end of string. 528 * @return: err -> error code if there was a problem with csplitting. 529 */ 530 _CSPLIT_FUNC 531 CSplitError_t csplit_lim(CSplitList_t* list, char* input_str, char* token, int max_splits) { 532 CSplitError_t err = CSPLIT_SUCCESS; 533 // first check to see if input string is valid and token is valid 534 if (strlen(input_str) < 1 || strlen(token) < 1) { 535 err = CSPLIT_TOO_SHORT; 536 } 537 else { 538 // otherwise we split on the given string 539 err = csplit_str(list, input_str, token, max_splits); 540 } 541 return err; 542 } 543 544 545 /** 546 * @brief Top level csplit function call. Outputs a csplit list split on a string token. Calls 547 * csplit_lim with max_splits = len(input_str), ensuring that all possible splits will be made. 548 * @ingroup core 549 * 550 * @params[out]: list -> output list splitting input str on string token 551 * @params[in]: input_str -> input string which will be split 552 * @params[in]: token -> string on which to split 553 * @return: err -> error code if there was a problem with csplitting. 554 */ 555 _CSPLIT_FUNC 556 CSplitError_t csplit(CSplitList_t* list, char* input_str, char* token) { 557 return csplit_lim(list, input_str, token, (int)strlen(input_str)); 558 } 559 560 561 /** 562 * @brief Function that runs csplit and then reverses the output. 563 * @ingroup core 564 * 565 * @params[out]: output_list -> output list splitting input str on string token 566 * @params[in]: input_str -> input string which will be split 567 * @params[in]: token -> string on which to split 568 * @return: err -> error code if there was a problem with csplitting. 569 */ 570 _CSPLIT_FUNC 571 CSplitError_t rcsplit(CSplitList_t* output_list, char* input_str, char* token) { 572 CSplitError_t err = csplit(output_list, input_str, token); 573 if (err != CSPLIT_SUCCESS) 574 return err; 575 err = csplit_reverse_list(output_list); 576 return err; 577 } 578 579 #ifdef __cplusplus 580 } 581 #endif 582 583 #endif
main 可以正常运行
1 #include <stdio.h> 2 #include <stdlib.h> 3 #include "csplit.h" 4 5 6 /* run this program using the console pauser or add your own getch, system("pause") or input loop */ 7 8 #define BUFFSIZE 4016*11*1 9 static char tab[] = "0123456789ABCDEF"; 10 11 12 13 void Change(char* bin, size_t size, char* asc) 14 { 15 16 unsigned char* src = (unsigned char*)bin; 17 unsigned char* dst = (unsigned char*)asc; 18 while (size-- > 0) 19 { 20 *dst++ = tab[*src >> 4]; 21 *dst++ = tab[*src & 0xF]; 22 ++src; 23 } 24 } 25 26 27 28 29 30 31 32 int main(int argc, char* argv[]) { 33 // our test string 34 unsigned char* test_string = "F5A60000C71DE12901000C0000000000110068001E005E0020008B008FFF0200100067001D005D0021008A0090FF0200100066001F005E0020008A008FFF0100100067001E005D001F0089008FFF0100100068001D005F001F0089008FFF0100100068001E005F0020008A008FFF0200110068001F005E0020008A0090FF0200110068001F005F001F008A008FFF0200110069001F005D001F008A008FFF0200110068001E005F002000890090FF0200100067001E005F0020008A008FFF02000F0067001D005E001F008A0090FF0100100068001E005E0020008A008FFF0200110068001E005E001F0089008EFF02000F0067001F005D00200089008FFF0100110067001E005F001F008A008EFF0200110067001F005E0020008B008FFF02001100680020005E0020008A0090FF0100110068001E005E001E008A0090FF0100100068001F005F0020008A008FFF0200100066001F005D001F0089008FFF0200100067001F005F00200089008FFF0000100067001E005F001F008A008FFF0100100067001E005E0020008A008FFF0200100067001E005E0020008A008FFF0200110069001F005E0021008A0090FF0200120067001E005F001F0088008FFF0100100068001F005D00200089008EFF0100100067001E005E001E0089008FFF0200100067001E005D00200089008FFF0200100068001E005F001F0089008EFF0100100067001E005E001F008A008DFF01001100690020005E002000890090FF0300110068001F005F0021008B0090FF0200100067001F005E00200089008FFF0200100068001F005E001F008A0090FF0200100067001F005E00200089008EFF0200100068001D005E00200089008FFF0100100067001E005D00200089008FFF0200100068001E005D0020008A008FFF0100100068001F0060001F008A0090FF0200110068001F005F0020008A008FFF0100120067001E005E002000890090FF02000F0068001F005E00200088008FFF0100100067001F005E0020008A008FFF0100100068001E005D00200089008FFF02000F0068001E005E001F008A008FFF02000F0067001F005F00200089008EFF0100100067001F005D00200089008FFF0200110068001F005F0021008B008FFF0100110068001F005E002000890090FF0200100068001F005D001F0089008EFF0200100068001E005E0020008A008FFF0100110066001F005D00200088008FFF0300100067001E005E0020008A008EFF0200110068001E005E002000890090FF0100110067001F005D00200089008FFF0200110068001F005E0020008A008FFF0200120068001F005F002100890090FF01000F0067001F005F0021008A008FFF0100100067001F005F0020008A008EFF0200100067001E005E001F0089008EFF0100110067001F005E0020008A0090FF0100110067001F005E00200089008FFF0100100067001E005D002100890090FF0200100067001D005E0020008A008FFF0200120068001F005F0021008A0091FF0200100068001E005D0021008A008FFF0100100067001E005D001F0089008FFF0100110067001E005E001F008B008FFF0200100067001D005E001F008A0090FF0200110068001F005D0020008A0091FF0100100068001E005D00200088008EFF0200100067001E005E0020008B0090FF0200100069001F005E002100890091FF0100120067001F005F002000890090FF0200110067001E005E00200089008FFF0200100068001D005E0021008A008FFF0200100067001E005E001F0089008EFF0100100068001E005E001F008B008FFF0100110068001E005E001F0089008FFF01001100670020005D0020008A008FFF02001100680020005E001F008A008FFF0100100069001E005E0021008A008FFF0200110068001F005D0020008A008EFF0200110067001F005E00200089008FFF0200110068001E005D00200089008FFF0100110067001E005D00200089008FFF0200110067001E005E001F008A008FFF0200100068001E005D0020008A008EFF0200100068001F005E0021008A008EFF0100100069001F005F0021008A008FFF0200100067001E005E00200089008FFF0100100067001C005E001F008A008EFF0100100067001E005D001F008A008EFF02000F0068001E005E001F008A0090FF0100110068001D005E001F008A008FFF0100100068001E005F0020008A008EFF0200110067001D005D0020008A0090FF0100100068001F005E0020008B0090FF0200110067001F005E0021008A008EFF0200100066001E005E0020008A008FFF0100100067001E005D0020008A008FFF0200110067001D005E001F0089008FFF02000F0068001F005D001F00890090FF0100100067001E005D001F0089008FFF0100100068001E005E00200089008FFF0200100067001F005E0020008A008FFF0100110067001E005D001F008A008FFF0200110067001E005E001F0089008FFF0100100066001E005D00200089008FFF0200100066001F005E001F00890090FF0200100067001E005E00200089008FFF0100120068001F005E00200089008FFF0200110067001D005E001F0089008FFF0200110069001E005E00200089008FFF0200100067001F005E0021008A0090FF0200110067001F005F0020008A008FFF0100100068001E005D0020008A008EFF0200110067001E005E001F008A008EFF0100110067001E005D0020008A008FFF0200110068001F005D001F008A008FFF01000F0067001D005E0020008A008EFF0200110068001E005F002000890090FF01000F0066001E005E001F008A008FFF0200110069001E005E0021008A0090FF02000F0068001F005D0020008A008FFF02000F0068001E005D0020008A0090FF0200100068001E005F001F008A008EFF02000F0068001E005E00200089008FFF0200100067001F005E00200089008FFF0200100068001F005E0020008A008EFF0200100068001E005D00200089008EFF0200120068001E005E0020008A008FFF0300110067001F005D00200089008EFF0200100067001F005D001F008A008EFF0200110068001D005E0020008A008FFF0200100067001F005E001F0088008FFF0100100067001F005E001F0089008DFF0200120068001E005F00200089008EFF0100110069001F005E0020008A008EFF0100110067001F005F0020008A0090FF0100100067001F005E0020008A0091FF01001100680020005E0020008A008FFF0200100067001E005E0020008A008EFF0200100067001E005D00200089008FFF0200100067001D005F001F008A0090FF0200110067001F005E00200089008EFF0100110068001F005E001F0089008FFF0200110068001F005E0020008A008FFF0200110068001E005D001F008B0090FF0200110067001E005D001F008A008EFF0100100067001D005D0020008A008FFF0300110067001E005F00200089008EFF0200120068001E005E001F00890090FF0200100066001E005C00200089008EFF0300110067001E005D001F0089008FFF0300110068001F005D0020008A0090FF0100110068001E005E0021008A008FFF0200110067001F005D001F008A0090FF0200100066001D005E001F0089008FFF0200110066001F005E00200089008FFF0200100067001E005D002000890090FF0200100067001E005D0020008A0090FF0100100067001E005E0020008A008FFF0200100068001F005E002000890090FF0200110067001F005F0020008A0090FF0200120068001F005F0020008A008FFF0200110067001F005E0020008A0090FF01000F0067001E005E00200089008FFF0100100068001E005E001F008A008FFF0200100068001E005E001F008B0090FF0200110067001E005D001F0089008FFF0200110067001E005E00200088008FFF0300110067001F005E001F008A008FFF0200110068001D005F0021008A008FFF01001100680020005E00200089008EFF0200100068001F005E00200089008FFF0100100067001E005F00200089008EFF0200110068001E005D001F0089008FFF0200100068001F005E0020008A008FFF0200110067001D005F001E008B008FFF0100110069001F005D00200089008FFF0100110068001E005F0020008B0090FF0200110068001E005F001F0088008FFF01000F0067001E005D001F008A008EFF0100100067001E005E001F0089008FFF0200110067001F005D0020008A008FFF0200120067001E005E001F0089008FFF0100110067001E005F001F0089008EFF0200100068001F005E002000890090FF0200100068001F005E00200089008FFF0100110067001F005E0021008A008FFF0200120068001E005E00200089008EFF0200110067001F005E001F0089008FFF0200100068001D005D00200088008FFF0200110068001E005E00200089008EFF0100100068001E005E00220089008FFF0300110067001F005E00200089008FFF01000F0068001F005E002000890090FF0200110068001F005F0021008A008EFF0100100068001E005E0020008B0090FF02000F0067001E005E002000890091FF0200110068001F005E001F0089008FFF02000F0068001F005D001E0089008FFF0100100067001E005E001F008A0090FF0100110068001E005E002000890091FF0200110067001E005D00200089008FFF0200100068001F005E0020008B008FFF0200110066001E005E00200089008FFF0100110066001E005E0020008B008EFF01000F0068001E005E0020008A008FFF0200110068001D005D001F0089008FFF0100100067001E005D001F008A0090FF0100110067001E005D002000890090FF0200110068001F005E0020008A008FFF0200110068001E005E0020008A008FFF0200120067001D005E0020008A008FFF0100110068001E005E00200089008FFF0100110067001E005F00200088008FFF0200100068001E005F0021008A008FFF0200100067001E005E001F008A008FFF0200100068001F005F00200089008FFF01001000670020005D001F0089008FFF02001200680020005E0020008A008FFF02001100680020005D0020008A008FFF0200110067001F005F001F008A008FFF0100110067001F005D001F008A008EFF0100100068001F005E0020008A008FFF0100110067001E005E0020008B008EFF0200110067001F005D001F008A008FFF0100110067001F005E001F008A008EFF02000F0067001E005E0020008A008FFF0100110068001E005F0020008A008FFF0200110068001E005E00210089008FFF0200100068001E005E001F0089008EFF0200110068001E005E0020008A008FFF0200100067001F005E0020008A0090FF0200120068001F005E001F0089008EFF0200100069001F005F001F0089008FFF0200100068001E005D00200089008FFF0100110067001F005F002000890090FF0200100067001E005E001F008B008FFF0200110068001D005E0020008A008EFF0200100066001E005E00200089008EFF0200100067001E005D001E008A008FFF0200100068001E005E0020008A008FFF0200100068001E005E00200089008FFF0200110068001E005E001F00890090FF0100100068001F005D002000890090FF0200"; 35 // printf("Our demo string is: %s\n", test_string); 36 37 38 FILE* filestr = fopen("FS_2020_0925_1241_45_12.txt", "rb"); 39 //unsigned char buff[BUFFSIZE]; 40 // unsigned char buff2[BUFFSIZE]; 41 char* buff = NULL; 42 char* buff2 = NULL; 43 buff = (char*)malloc(BUFFSIZE); 44 buff2 = (char*)malloc(BUFFSIZE * 2); 45 int count = 0; 46 int errnor = 0; 47 48 memset(buff, 0, BUFFSIZE); 49 //char ptemp[BUFFSIZE]; 50 memset(buff2, 0, BUFFSIZE * 2); 51 int a = 0; 52 while (!feof(filestr)) { 53 count = fread(buff, sizeof(char), BUFFSIZE, filestr); 54 if (count > 0) 55 { 56 Change(buff, BUFFSIZE, buff2); 57 } 58 // initialize our output list. 59 CSplitList_t* list = csplit_init_list(); 60 // split on the " " (space) character 61 CSplitError_t err = csplit(list,(char *)buff2, "F5A6"); 62 if (list == NULL) return; 63 CSplitFragment_t* current_fragment = list->head; 64 while (current_fragment != NULL) { 65 printf("--%s", current_fragment->text); 66 //current_fragment->text>>32; 67 // printf( "--%s", current_fragment->text); 68 current_fragment = current_fragment->next; 69 } 70 // free memory 71 csplit_clear_list(list); 72 } 73 74 75 76 77 78 return 0; 79 //// print the list of split fragments to stdout 80 //csplit_print_list_info(list, stdout); 81 82 //// print a separator 83 //printf("----------------------------\n"); 84 85 //// demo of getting fragment string at an index, 3 index will give us "you" 86 //char* test_get_index = csplit_get_fragment_at_index(list, 3); 87 88 //// demo of getting fragment string using reverse index, -1 will give us the last 89 //// fragment, in this case "doing?" 90 //char* test_get_r_index = csplit_get_fragment_at_index(list, -1); 91 92 //// print results 93 //printf("Get index: %s\n", test_get_index); 94 //printf("Get reverse index: %s\n", test_get_r_index); 95 96 //// free memory 97 //csplit_clear_list(list); 98 99 100 101 // 102 // char* test_string = "Hello how are you doing?\n\n"; 103 // printf("Our demo string is: --%s--\n", test_string); 104 // 105 // // strip outermost whitespace (2 newlines) 106 // char* stripped_str = csplit_strip(test_string); 107 // printf("The stripped string is --%s--\n", stripped_str); 108 // printf("Note the disappeared newline characters.\n"); 109 // 110 // // startswith command 111 // int temp = csplit_startswith(test_string, "Hello"); 112 // if(temp == 0){ 113 // printf("The input started with 'Hello'\n"); 114 // } 115 // 116 // // endswith - will fail here because of newlines, but succeed on the stripped one. 117 // temp = csplit_endswith(test_string, "doing?"); 118 // if(temp == 0){ 119 // printf("The input string ended with 'doing?'\n"); 120 // } 121 // temp = csplit_endswith(stripped_str, "doing?"); 122 // if(temp == 0){ 123 // printf("After stripping away newlines, the string ends with 'doing?'\n"); 124 // } 125 // 126 // // remove all whitespace and print 127 // char* no_whitespace = csplit_remove_whitespace(test_string); 128 // printf("The input string without any whitespace: --%s--\n", no_whitespace); 129 // 130 // // free memory. 131 // free(stripped_str); 132 // free(no_whitespace); 133 134 135 136 137 printf("%s", "777"); 138 return 0; 139 }
/******************************************************************************** * MIT License * * Copyright (c) 2019 Jakub Wlodek * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in all * copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE * SOFTWARE. *********************************************************************************/ /** * @defgroup intern Internal * @brief Internal functions, not intended to be used by users * @defgroup set Setup * @brief Setup and Diagnostic functions used by csplit * @defgroup core csplit Core * @brief Core functions included in csplit */ /** * A single-header C library for string manipulation and splitting. * * Author: Jakub Wlodek * Created: 02-Aug-2019 */ // Include guard - avoid redefinition #ifndef CSPLIT_H #define CSPLIT_H #ifdef __cplusplus extern "C" { #endif // some basic includes #include <stdio.h> #include <string.h> #include <stdlib.h> #include <ctype.h> #ifdef _MSC_VER # define _CSPLIT_FUNC static __inline #elif !defined __STDC_VERSION__ || __STDC_VERSION__ < 199901L # define _CSPLIT_FUNC static __inline__ #else # define _CSPLIT_FUNC static inline #endif /** * Enum type for error codes for csplit * @ingroup set */ typedef enum CSPLIT_ERROR { CSPLIT_SUCCESS = 0, /**< No Error */ CSPLIT_TOO_SHORT = -1, /**< Input string is too short */ CSPLIT_NO_SUCH_INDEX = -2, /**< Index out of range */ CSPLIT_UNIMPLEMENTED = -3, /**< Function unimplemented */ CSPLIT_BUFF_EXCEEDED = -4, /**< Buffer size exceeded */ } CSplitError_t; /** * Struct for an individual string fragment result from csplit * @ingroup intern */ typedef struct CSPLIT_FRAGMENT { char* text; /**< Text of the fragment. */ struct CSPLIT_FRAGMENT* next; /**< Next fragment in the linked list */ struct CSPLIT_FRAGMENT* prev; /**< Previous fragment in the linked list */ } CSplitFragment_t; /** * Struct that stores the csplit linked list. Can be used as an arbitrary linked list * for strings, but is intended for use with csplit strtok replacement functions * @ingroup core */ typedef struct CSPLIT_LIST { int num_elems; /**< Number of elements in the list */ CSplitFragment_t* head; /**< Head of the linked list (first element) */ CSplitFragment_t* tail; /**< Tail of the linked list (last element) */ } CSplitList_t; /* Function Declarations */ _CSPLIT_FUNC CSplitList_t* csplit_init_list(); _CSPLIT_FUNC void csplit_clear_list(CSplitList_t* list); _CSPLIT_FUNC CSplitError_t csplit_push_to_list(CSplitList_t* list, CSplitFragment_t* fragment, size_t buff_size); _CSPLIT_FUNC void csplit_print_list_info(CSplitList_t* list, FILE* fp); #ifdef CSPLIT_DEBUG _CSPLIT_FUNC void print_csplit_fragment_info(CSplitFragment_t* fragment, FILE* fp); #endif _CSPLIT_FUNC char* csplit_get_fragment_at_index(CSplitList_t* list, int index); _CSPLIT_FUNC CSplitError_t csplit_reverse_list(CSplitList_t* list); _CSPLIT_FUNC char* csplit_strip(char* input_str); _CSPLIT_FUNC char* csplit_remove_whitespace(char* input_str); _CSPLIT_FUNC int csplit_startswith(char* input_str, char* starts_with); _CSPLIT_FUNC int csplit_endswith(char* input_str, char* ends_with); _CSPLIT_FUNC CSplitError_t csplit_rstr(CSplitList_t* list, char* input_str, char* token, int max_splits); _CSPLIT_FUNC CSplitError_t csplit_str(CSplitList_t* list, char* input_str, char* token, int max_splits); _CSPLIT_FUNC CSplitError_t csplit_lim(CSplitList_t* list, char* input_str, char* token, int max_splits); _CSPLIT_FUNC CSplitError_t csplit(CSplitList_t* list, char* input_str, char* token); _CSPLIT_FUNC CSplitError_t rcsplit(CSplitList_t* output_list, char* input_str, char* token); /* Function Definitions */ /** * @brief Function for initializing a csplit list * @ingroup set * * @params[in]: buff_size -> user set buffer size. Make sure this is large enough for your largest fragment * @return: list -> an allocated csplit list */ _CSPLIT_FUNC CSplitList_t* csplit_init_list(){ CSplitList_t* list = (CSplitList_t*) calloc(1, sizeof(CSplitList_t)); list->num_elems = 0; return list; } /** * @brief Clears all memory for an allocated csplit list * @ingroup set * * @params[in]: list -> a previously allocated csplit list to be freed */ _CSPLIT_FUNC void csplit_clear_list(CSplitList_t* list){ CSplitFragment_t* current_fragment = list->head; while(current_fragment != NULL){ CSplitFragment_t* temp = current_fragment->next; free(current_fragment->text); free(current_fragment); current_fragment = temp; } free(list); } /** * @brief Function that pushes a new CSplitFragment to the end of the list, and allocates memory for the text, * with size list->BUFF_SIZE * @ingroup intern * * @params[out]: list -> The list with fragment appended to the tail * @params[in]: fragment -> fragment to append to the list. fragment->text will be allocated based on list->BUFF_SIZE */ _CSPLIT_FUNC CSplitError_t csplit_push_to_list(CSplitList_t* list, CSplitFragment_t* fragment, size_t buff_size){ // first make sure neither is null if(list == NULL || fragment == NULL){ return CSPLIT_TOO_SHORT; } else{ // then update the number of elements, and the pointers list->num_elems = list->num_elems + 1; if(list->head == NULL){ list->head = fragment; list->tail = fragment; } else{ list->tail->next = fragment; fragment->prev = list->tail; list->tail = fragment; } // allocate fragment text field fragment->text = (char*) calloc(1, buff_size); } return CSPLIT_SUCCESS; } /** * @brief Function that prints information about a csplit list * @ingroup set * * @params[in]: list -> list for which to print info * @params[in]: fp -> file pointer to print into. */ _CSPLIT_FUNC void csplit_print_list_info(CSplitList_t* list, FILE* fp){ if(list == NULL || fp == NULL) return; fprintf(fp, "List contains %d elements\n", list->num_elems); fprintf(fp, "Supports indexes -%d to %d.\n", list->num_elems, list->num_elems -1); CSplitFragment_t* current_fragment = list->head; while(current_fragment != NULL){ fprintf(fp, "--%s--\n", current_fragment->text); current_fragment = current_fragment->next; } } #ifdef CSPLIT_DEBUG /** * @brief Function that prints information about a csplit fragment - intended for internal use only * @ingroup intern * * @params[in]: fragment -> fragment for which to print info * @params[in]: fp -> file pointer to print into */ _CSPLIT_FUNC void print_csplit_fragment_info(CSplitFragment_t* fragment, FILE* fp){ if(fragment == NULL || fp == NULL) return; fprintf(fp, "Fragment has text %s\n", fragment->text); if(fragment->next != NULL) fprintf(fp, "Fragment has next with text %s\n", fragment->next->text); if(fragment->prev != NULL) fprintf(fp, "Fragment has prev with text %s\n", fragment->prev->text); } #endif /** * @brief Function that returns the string fragment at a certain index in the list * @ingroup core * * @params[in]: list -> list generated by csplit * @params[in]: index -> index to search for (can be negative for getting at index from back of list) * @return: text -> string at the given index or NULL if index out of range. */ _CSPLIT_FUNC char* csplit_get_fragment_at_index(CSplitList_t* list, int index){ // convert index into absolute index (if negative); int target_index; if(index < 0){ target_index = index + list->num_elems; } else{ target_index = index; } // if index is out of range return null if(list->num_elems <= target_index || target_index < 0){ return NULL; } else{ // iterate over list until index found int counter = 0; CSplitFragment_t* current_fragment = list->head; while(counter < target_index){ current_fragment = current_fragment->next; counter++; } // return the text field return current_fragment->text; } } /** * @brief Function that reverses the list generated by csplit * @ingroup set * * @params[out]: list -> list to reverse * @return: err -> error code if there is an error */ _CSPLIT_FUNC CSplitError_t csplit_reverse_list(CSplitList_t* list){ int i; // iterate over list and swap next and previous fields CSplitFragment_t* temp = list->head; for(i = 0; i < list->num_elems; i++){ CSplitFragment_t* temp2 = temp->next; temp->next = temp->prev; temp->prev = temp2; temp = temp2; } // swap head and tail temp = list->head; list->head = list->tail; list->tail = temp; return CSPLIT_SUCCESS; } /** * @brief Function that strips a given string into an output string. Will remove whitespace character: * \n, \r, \t, space will be removed from the start and end of each string. * @ingroup core * * @params[in]: input_str -> the input string to strip * @return: output_str -> the string with whitespace removed from the ends. Must be freed. */ _CSPLIT_FUNC char* csplit_strip(char* input_str){ char* output_str; // check if input is null if(input_str == NULL) output_str = NULL; else{ int len = strlen(input_str); char* end = input_str + len - 1; char* start = input_str; while(isspace(*start)){ if(*start == '\0' || start == end) return NULL; else start++; } while(isspace(*end)) end--; size_t buff_size = end - start + 1; output_str = (char*) calloc(1, buff_size + 1); strncpy(output_str, start, buff_size); } return output_str; } /** * @breifFunction that removes all whitespace characters of a given string into an output string. * Note that resulting char* must be free'd after it is no longer used * @ingroup core * * @params[in]: input_str -> the input string to strip * @return: output_str -> the string with whitespace removed. */ _CSPLIT_FUNC char* csplit_remove_whitespace(char* input_str){ char* output_str; if(input_str == NULL) output_str = NULL; else{ int len = strlen(input_str); output_str = (char*) calloc(1, len); int counter = 0; int output_counter = 0; // read through but don't copy whitespace while(counter < len){ if(!isspace(input_str[counter])){ output_str[output_counter] = input_str[counter]; output_counter++; } counter++; } } return output_str; } /** * @brief Function that checks if a given string starts with another given string. * @ingroup core * * @params[in]: input_str -> string to check against * @params[in]: starts_with -> string to try to match with start of input string * @return: int -> -2 if input is invalid, -1 if doesn't start with given string, or 0 if it does */ _CSPLIT_FUNC int csplit_startswith(char* input_str, char* starts_with){ if(input_str == NULL || starts_with == NULL) return -2; else if(strstr(input_str, starts_with) == input_str) return 0; else return -1; } /** * @brief Function that checks if a given string ends with another given string. * @ingroup core * * @params[in]: input_str -> string to check against * @params[in]: ends_with -> string to try to match with end of input string * @return: int -> -2 if input is invalid, -1 if doesn't end with given string, or 0 if it does */ _CSPLIT_FUNC int csplit_endswith(char* input_str, char* ends_with){ if(input_str == NULL || ends_with == NULL){ return -2; } else{ int ewith_len = strlen(ends_with); int istr_len = strlen(input_str); if(ewith_len > istr_len) return -1; else if(strcmp(input_str + istr_len - ewith_len, ends_with) == 0) return 0; else return -1; } } /** * @brief Function that runs csplit on a particular string from the end of the input. Called if max_splits < 0 * @ingroup intern * * @params[out]: list -> split input string into this list structure * @params[in]: input_str -> input string * @params[in]: token -> character on which to split * @params[in]: max_splits -> maximum number of splits. If negative will split from end of string * @return: err -> error code if there was a problem with csplitting. */ _CSPLIT_FUNC CSplitError_t csplit_rstr(CSplitList_t* list, char* input_str, char* token, int max_splits){ CSplitError_t err = CSPLIT_SUCCESS; int in_len = strlen(input_str); int counter = 0; int num_splits = 0; int token_len = strlen(token); char* current_location = input_str; char* arr[in_len]; while((arr[counter] = strstr(current_location, token)) != NULL){ current_location = arr[counter] + 1; counter++; } char* last_location = input_str + in_len; while(counter >= 0 && num_splits >= max_splits){ current_location = arr[counter - 1] + token_len; CSplitFragment_t* fragment = (CSplitFragment_t*) calloc(1, sizeof(CSplitFragment_t)); size_t req_buff_size; if(num_splits == max_splits || counter == 0){ req_buff_size = in_len - strlen(last_location); current_location = input_str; } else req_buff_size = last_location - current_location; err = csplit_push_to_list(list, fragment, req_buff_size); strncpy(fragment->text, current_location, req_buff_size); last_location = current_location - token_len; num_splits--; counter--; } err = csplit_reverse_list(list); return err; } /** * @brief Function that splits a given input string based on another string. * @ingroup intern * * @params[out]: list -> output list splitting input str on string token * @params[in]: input_str -> input string which will be split * @params[in]: token -> string on which to split * @params[in]: max_splits -> max number of splits to perform. Negative if starting from end of string. * @return: err -> error code if there was a problem with csplitting. */ _CSPLIT_FUNC CSplitError_t csplit_str(CSplitList_t* list, char* input_str, char* token, int max_splits){ if(max_splits < 0) return csplit_rstr(list, input_str, token, max_splits); CSplitError_t err = CSPLIT_SUCCESS; int in_len = strlen(input_str); int num_splits = 0; int token_len = strlen(token); char* current_location = input_str; char* next_location; while(current_location != NULL && num_splits <= max_splits){ CSplitFragment_t* fragment = (CSplitFragment_t*) calloc(1, sizeof(CSplitFragment_t)); next_location = strstr(current_location, token); size_t req_buff_size; if(next_location == NULL || (num_splits == max_splits)) req_buff_size = in_len - (current_location - input_str); else if(next_location != NULL) req_buff_size = next_location - current_location; err = csplit_push_to_list(list, fragment, req_buff_size); strncpy(fragment->text, current_location, req_buff_size); if(next_location != NULL) current_location = next_location + token_len; else{ current_location = next_location; } num_splits++; } return err; } /** * @brief Function that allows user to split based on a limited number of splits, either forward * or in reverse. A max_splits >= len(input_str) will guarantee all possible splits * @ingroup core * * @params[out]: list -> output list splitting input str on string token * @params[in]: input_str -> input string which will be split * @params[in]: token -> string on which to split * @params[in]: max_splits -> max number of splits to perform. Negative if starting from end of string. * @return: err -> error code if there was a problem with csplitting. */ _CSPLIT_FUNC CSplitError_t csplit_lim(CSplitList_t* list, char* input_str, char* token, int max_splits){ CSplitError_t err = CSPLIT_SUCCESS; // first check to see if input string is valid and token is valid if(strlen(input_str) < 1 || strlen(token) < 1){ err = CSPLIT_TOO_SHORT; } else{ // otherwise we split on the given string err = csplit_str(list, input_str, token, max_splits); } return err; } /** * @brief Top level csplit function call. Outputs a csplit list split on a string token. Calls * csplit_lim with max_splits = len(input_str), ensuring that all possible splits will be made. * @ingroup core * * @params[out]: list -> output list splitting input str on string token * @params[in]: input_str -> input string which will be split * @params[in]: token -> string on which to split * @return: err -> error code if there was a problem with csplitting. */ _CSPLIT_FUNC CSplitError_t csplit(CSplitList_t* list, char* input_str, char* token){ return csplit_lim(list, input_str, token, (int) strlen(input_str)); } /** * @brief Function that runs csplit and then reverses the output. * @ingroup core * * @params[out]: output_list -> output list splitting input str on string token * @params[in]: input_str -> input string which will be split * @params[in]: token -> string on which to split * @return: err -> error code if there was a problem with csplitting. */ _CSPLIT_FUNC CSplitError_t rcsplit(CSplitList_t* output_list, char* input_str, char* token){ CSplitError_t err = csplit(output_list, input_str, token); if(err != CSPLIT_SUCCESS) return err; err = csplit_reverse_list(output_list); return err; } #ifdef __cplusplus } #endif #endif
#include <stdio.h> #include <stdlib.h> #include "csplit.h" /* run this program using the console pauser or add your own getch, system("pause") or input loop */ int main(int argc, char *argv[]) { // our test string char* test_string = "F5A60000C71DE12901000C0000000000110068001E005E0020008B008FFF0200100067001D005D0021008A0090FF0200100066001F005E0020008A008FFF0100100067001E005D001F0089008FFF0100100068001D005F001F0089008FFF0100100068001E005F0020008A008FFF0200110068001F005E0020008A0090FF0200110068001F005F001F008A008FFF0200110069001F005D001F008A008FFF0200110068001E005F002000890090FF0200100067001E005F0020008A008FFF02000F0067001D005E001F008A0090FF0100100068001E005E0020008A008FFF0200110068001E005E001F0089008EFF02000F0067001F005D00200089008FFF0100110067001E005F001F008A008EFF0200110067001F005E0020008B008FFF02001100680020005E0020008A0090FF0100110068001E005E001E008A0090FF0100100068001F005F0020008A008FFF0200100066001F005D001F0089008FFF0200100067001F005F00200089008FFF0000100067001E005F001F008A008FFF0100100067001E005E0020008A008FFF0200100067001E005E0020008A008FFF0200110069001F005E0021008A0090FF0200120067001E005F001F0088008FFF0100100068001F005D00200089008EFF0100100067001E005E001E0089008FFF0200100067001E005D00200089008FFF0200100068001E005F001F0089008EFF0100100067001E005E001F008A008DFF01001100690020005E002000890090FF0300110068001F005F0021008B0090FF0200100067001F005E00200089008FFF0200100068001F005E001F008A0090FF0200100067001F005E00200089008EFF0200100068001D005E00200089008FFF0100100067001E005D00200089008FFF0200100068001E005D0020008A008FFF0100100068001F0060001F008A0090FF0200110068001F005F0020008A008FFF0100120067001E005E002000890090FF02000F0068001F005E00200088008FFF0100100067001F005E0020008A008FFF0100100068001E005D00200089008FFF02000F0068001E005E001F008A008FFF02000F0067001F005F00200089008EFF0100100067001F005D00200089008FFF0200110068001F005F0021008B008FFF0100110068001F005E002000890090FF0200100068001F005D001F0089008EFF0200100068001E005E0020008A008FFF0100110066001F005D00200088008FFF0300100067001E005E0020008A008EFF0200110068001E005E002000890090FF0100110067001F005D00200089008FFF0200110068001F005E0020008A008FFF0200120068001F005F002100890090FF01000F0067001F005F0021008A008FFF0100100067001F005F0020008A008EFF0200100067001E005E001F0089008EFF0100110067001F005E0020008A0090FF0100110067001F005E00200089008FFF0100100067001E005D002100890090FF0200100067001D005E0020008A008FFF0200120068001F005F0021008A0091FF0200100068001E005D0021008A008FFF0100100067001E005D001F0089008FFF0100110067001E005E001F008B008FFF0200100067001D005E001F008A0090FF0200110068001F005D0020008A0091FF0100100068001E005D00200088008EFF0200100067001E005E0020008B0090FF0200100069001F005E002100890091FF0100120067001F005F002000890090FF0200110067001E005E00200089008FFF0200100068001D005E0021008A008FFF0200100067001E005E001F0089008EFF0100100068001E005E001F008B008FFF0100110068001E005E001F0089008FFF01001100670020005D0020008A008FFF02001100680020005E001F008A008FFF0100100069001E005E0021008A008FFF0200110068001F005D0020008A008EFF0200110067001F005E00200089008FFF0200110068001E005D00200089008FFF0100110067001E005D00200089008FFF0200110067001E005E001F008A008FFF0200100068001E005D0020008A008EFF0200100068001F005E0021008A008EFF0100100069001F005F0021008A008FFF0200100067001E005E00200089008FFF0100100067001C005E001F008A008EFF0100100067001E005D001F008A008EFF02000F0068001E005E001F008A0090FF0100110068001D005E001F008A008FFF0100100068001E005F0020008A008EFF0200110067001D005D0020008A0090FF0100100068001F005E0020008B0090FF0200110067001F005E0021008A008EFF0200100066001E005E0020008A008FFF0100100067001E005D0020008A008FFF0200110067001D005E001F0089008FFF02000F0068001F005D001F00890090FF0100100067001E005D001F0089008FFF0100100068001E005E00200089008FFF0200100067001F005E0020008A008FFF0100110067001E005D001F008A008FFF0200110067001E005E001F0089008FFF0100100066001E005D00200089008FFF0200100066001F005E001F00890090FF0200100067001E005E00200089008FFF0100120068001F005E00200089008FFF0200110067001D005E001F0089008FFF0200110069001E005E00200089008FFF0200100067001F005E0021008A0090FF0200110067001F005F0020008A008FFF0100100068001E005D0020008A008EFF0200110067001E005E001F008A008EFF0100110067001E005D0020008A008FFF0200110068001F005D001F008A008FFF01000F0067001D005E0020008A008EFF0200110068001E005F002000890090FF01000F0066001E005E001F008A008FFF0200110069001E005E0021008A0090FF02000F0068001F005D0020008A008FFF02000F0068001E005D0020008A0090FF0200100068001E005F001F008A008EFF02000F0068001E005E00200089008FFF0200100067001F005E00200089008FFF0200100068001F005E0020008A008EFF0200100068001E005D00200089008EFF0200120068001E005E0020008A008FFF0300110067001F005D00200089008EFF0200100067001F005D001F008A008EFF0200110068001D005E0020008A008FFF0200100067001F005E001F0088008FFF0100100067001F005E001F0089008DFF0200120068001E005F00200089008EFF0100110069001F005E0020008A008EFF0100110067001F005F0020008A0090FF0100100067001F005E0020008A0091FF01001100680020005E0020008A008FFF0200100067001E005E0020008A008EFF0200100067001E005D00200089008FFF0200100067001D005F001F008A0090FF0200110067001F005E00200089008EFF0100110068001F005E001F0089008FFF0200110068001F005E0020008A008FFF0200110068001E005D001F008B0090FF0200110067001E005D001F008A008EFF0100100067001D005D0020008A008FFF0300110067001E005F00200089008EFF0200120068001E005E001F00890090FF0200100066001E005C00200089008EFF0300110067001E005D001F0089008FFF0300110068001F005D0020008A0090FF0100110068001E005E0021008A008FFF0200110067001F005D001F008A0090FF0200100066001D005E001F0089008FFF0200110066001F005E00200089008FFF0200100067001E005D002000890090FF0200100067001E005D0020008A0090FF0100100067001E005E0020008A008FFF0200100068001F005E002000890090FF0200110067001F005F0020008A0090FF0200120068001F005F0020008A008FFF0200110067001F005E0020008A0090FF01000F0067001E005E00200089008FFF0100100068001E005E001F008A008FFF0200100068001E005E001F008B0090FF0200110067001E005D001F0089008FFF0200110067001E005E00200088008FFF0300110067001F005E001F008A008FFF0200110068001D005F0021008A008FFF01001100680020005E00200089008EFF0200100068001F005E00200089008FFF0100100067001E005F00200089008EFF0200110068001E005D001F0089008FFF0200100068001F005E0020008A008FFF0200110067001D005F001E008B008FFF0100110069001F005D00200089008FFF0100110068001E005F0020008B0090FF0200110068001E005F001F0088008FFF01000F0067001E005D001F008A008EFF0100100067001E005E001F0089008FFF0200110067001F005D0020008A008FFF0200120067001E005E001F0089008FFF0100110067001E005F001F0089008EFF0200100068001F005E002000890090FF0200100068001F005E00200089008FFF0100110067001F005E0021008A008FFF0200120068001E005E00200089008EFF0200110067001F005E001F0089008FFF0200100068001D005D00200088008FFF0200110068001E005E00200089008EFF0100100068001E005E00220089008FFF0300110067001F005E00200089008FFF01000F0068001F005E002000890090FF0200110068001F005F0021008A008EFF0100100068001E005E0020008B0090FF02000F0067001E005E002000890091FF0200110068001F005E001F0089008FFF02000F0068001F005D001E0089008FFF0100100067001E005E001F008A0090FF0100110068001E005E002000890091FF0200110067001E005D00200089008FFF0200100068001F005E0020008B008FFF0200110066001E005E00200089008FFF0100110066001E005E0020008B008EFF01000F0068001E005E0020008A008FFF0200110068001D005D001F0089008FFF0100100067001E005D001F008A0090FF0100110067001E005D002000890090FF0200110068001F005E0020008A008FFF0200110068001E005E0020008A008FFF0200120067001D005E0020008A008FFF0100110068001E005E00200089008FFF0100110067001E005F00200088008FFF0200100068001E005F0021008A008FFF0200100067001E005E001F008A008FFF0200100068001F005F00200089008FFF01001000670020005D001F0089008FFF02001200680020005E0020008A008FFF02001100680020005D0020008A008FFF0200110067001F005F001F008A008FFF0100110067001F005D001F008A008EFF0100100068001F005E0020008A008FFF0100110067001E005E0020008B008EFF0200110067001F005D001F008A008FFF0100110067001F005E001F008A008EFF02000F0067001E005E0020008A008FFF0100110068001E005F0020008A008FFF0200110068001E005E00210089008FFF0200100068001E005E001F0089008EFF0200110068001E005E0020008A008FFF0200100067001F005E0020008A0090FF0200120068001F005E001F0089008EFF0200100069001F005F001F0089008FFF0200100068001E005D00200089008FFF0100110067001F005F002000890090FF0200100067001E005E001F008B008FFF0200110068001D005E0020008A008EFF0200100066001E005E00200089008EFF0200100067001E005D001E008A008FFF0200100068001E005E0020008A008FFF0200100068001E005E00200089008FFF0200110068001E005E001F00890090FF0100100068001F005D002000890090FF0200"; // printf("Our demo string is: %s\n", test_string); // initialize our output list. CSplitList_t* list = csplit_init_list(); // split on the " " (space) character CSplitError_t err = csplit(list, test_string, "F5A6"); if(list == NULL ) return; CSplitFragment_t* current_fragment = list->head; while(current_fragment != NULL){ printf( "--%s", current_fragment->text); //current_fragment->text>>32; // printf( "--%s", current_fragment->text); current_fragment = current_fragment->next; } return 0; // print the list of split fragments to stdout csplit_print_list_info(list, stdout); // print a separator printf("----------------------------\n"); // demo of getting fragment string at an index, 3 index will give us "you" char* test_get_index = csplit_get_fragment_at_index(list, 3); // demo of getting fragment string using reverse index, -1 will give us the last // fragment, in this case "doing?" char* test_get_r_index = csplit_get_fragment_at_index(list, -1); // print results printf("Get index: %s\n", test_get_index); printf("Get reverse index: %s\n", test_get_r_index); // free memory csplit_clear_list(list); // // char* test_string = "Hello how are you doing?\n\n"; // printf("Our demo string is: --%s--\n", test_string); // // // strip outermost whitespace (2 newlines) // char* stripped_str = csplit_strip(test_string); // printf("The stripped string is --%s--\n", stripped_str); // printf("Note the disappeared newline characters.\n"); // // // startswith command // int temp = csplit_startswith(test_string, "Hello"); // if(temp == 0){ // printf("The input started with 'Hello'\n"); // } // // // endswith - will fail here because of newlines, but succeed on the stripped one. // temp = csplit_endswith(test_string, "doing?"); // if(temp == 0){ // printf("The input string ended with 'doing?'\n"); // } // temp = csplit_endswith(stripped_str, "doing?"); // if(temp == 0){ // printf("After stripping away newlines, the string ends with 'doing?'\n"); // } // // // remove all whitespace and print // char* no_whitespace = csplit_remove_whitespace(test_string); // printf("The input string without any whitespace: --%s--\n", no_whitespace); // // // free memory. // free(stripped_str); // free(no_whitespace); printf("%s","777"); return 0; }