上一篇的分割字符串,在少量字符的情况下可以正常用,但是 字串在几万的时候就有问题,不清楚是什么情况
因此 去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 ", list->num_elems); 235 fprintf(fp, "Supports indexes -%d to %d. ", list->num_elems, list->num_elems - 1); 236 CSplitFragment_t* current_fragment = list->head; 237 while (current_fragment != NULL) { 238 fprintf(fp, "--%s-- ", 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 ", fragment->text); 256 if (fragment->next != NULL) fprintf(fp, "Fragment has next with text %s ", fragment->next->text); 257 if (fragment->prev != NULL) fprintf(fp, "Fragment has prev with text %s ", 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 * , , , 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 == '