online compiler and debugger for c/c++

code. compile. run. debug. share.
Source Code    Language
/****************************************************************************** Welcome to GDB Online. GDB online is an online compiler and debugger tool for C, C++, Python, PHP, Ruby, C#, VB, Perl, Swift, Prolog, Javascript, Pascal, HTML, CSS, JS Code, Compile, Run and Debug online from anywhere in world. *******************************************************************************/ #include <stdio.h> //-------------------------------------------// // // // Includes // // // //-------------------------------------------// #include <ctype.h> //< isdigit #include <errno.h> //< For strtol_s #include <stdarg.h> //< va_list, va_start, va_arg, va_end #include <stdbool.h> //< bool #include <stdint.h> //< *int*_t #include <stdio.h> //< TODO: DELERE #include <stdlib.h> //< strtol #include <string.h> //< Strsep #include <limits.h> //< LONG_MAX //-------------------------------------------// // // // Interface // // // //-------------------------------------------// int16_t strsepf(char mutStr[], char const* fmt, ...); int16_t vstrsepf(char mutStr[], char const* fmt, va_list arg); long strtol_s(const char* buff, uint8_t base, int8_t* err); //-------------------------------------------// // // // Implementation // // // //-------------------------------------------// /* * %d -> The format of the number is the same as expected by strtol() with the value 10 for the base * argument %s -> */ int16_t strsepf(char mutStr[], char const* fmt, ...) { int16_t rc; va_list arg; va_start(arg, fmt); rc = vstrsepf(mutStr, fmt, arg); va_end(arg); return rc; } /* * `vstrsepf` is string parsing utility function born from * the idea of using `strsep` with a `sscanf` interface. * * It is designed to be a safer `scanf` for embedded system application. * * Some key design choices: * - Will destroy its input string (by adding '\0'). * - No dynamic memory allocation * - No string copy, only pointer address are changed. * - No floating point support. * * ARGUMENTS: * @param: mutStr - mutable input string. * @param: fmt - format string. * @param: arg - Aguments lists (va_list) * * FORMAT SPECIFIER: * * | Specifier | Descriptions | * |-------------|-----------------------------------------------------------------| * | %i, %d, %u, | Any number of digits* | * | %o | Any number of octal digits (0-7)* | * | %x | Any number of hexadecimal digits (0-9, a-f, A-F* | * | %% | A % followed by another % matches a single %. | * | %s | A string with any character in it. A terminating null character | * | | is automatically added at the end of the stored sequence.# | * * FORMAT OPTIONAL SPECIFIER: * * | O Specifier | Descriptions | * |-------------|-----------------------------------------------------------------| * | * | An optional starting asterisk indicates that the data is to be | * | | read from the stream but ignored. | * | width | Specifies the maximum number of characters to be read in the | * | | current reading operation. | * * */ int16_t vstrsepf(char mutStr[], char const* fmt, va_list arg) { if (mutStr == NULL || fmt == NULL) { return -1; } #define SUPPORTED_SPECIFIER "dibouxs%" int count = 0; while (*mutStr && *fmt) { // printf("fmt = %c, s=%c\n", *fmt, *mutStr); if (*fmt == '%') { fmt++; // A format specifier follows this prototype: [=%[*][width][modifiers]type=] char specifierType = '\0'; bool noAssignFlag = false; size_t width = 0; for (; *fmt; fmt++) { if (strchr(SUPPORTED_SPECIFIER, *fmt)) { specifierType = *fmt; fmt++; break; //< Specifier type is always the last element of a specifier string } if (*fmt == '*') { noAssignFlag = true; } else if (*fmt >= '1' && *fmt <= '9') { char const* tc; for (tc = fmt; isdigit(*fmt); fmt++) ; width = strtol(tc, (char**)&fmt, 10); fmt--; } } if (specifierType == '%') { mutStr++; //< `%%` is just the `%` character. continue; } char* token; const bool continueUntilTheEnd = (*fmt == '\0'); if (continueUntilTheEnd) { token = mutStr; } else { char termination[] = { *fmt, '\0' }; token = strsep(&mutStr, termination); if (token == NULL) { return -1; //< no token found } fmt++; } if (noAssignFlag) { continue; //< ignore it. } if (width > 0) { if (width < strlen(token)) { return -1; } } int8_t strtolErr = 0; switch (specifierType) { /********************************* * Scan string *********************************/ case 's': { char** ptr = va_arg(arg, char**); if (ptr == NULL) { return -1; } *ptr = token; count++; } break; /********************************* * Scan int *********************************/ case 'd': /* FALLTHROUGH */ case 'i': /* FALLTHROUGH */ case 'u': { uint8_t base = 10; uint32_t* ptr = va_arg(arg, uint32_t*); if (ptr == NULL) { return -1; } *ptr = strtol_s(token, base, &strtolErr); if (strtolErr < 0) { return -1; } count++; } break; case 'x': { uint8_t base = 16; uint32_t* ptr = va_arg(arg, uint32_t*); if (ptr == NULL) { return -1; } *ptr = strtol_s(token, base, &strtolErr); if (strtolErr < 0) { return -1; } count++; } break; case 'o': { uint8_t base = 8; uint32_t* ptr = va_arg(arg, uint32_t*); if (ptr == NULL) { return -1; } *ptr = strtol_s(token, base, &strtolErr); if (strtolErr < 0) { return -1; } count++; } break; case 'b': { uint8_t base = 2; uint32_t* ptr = va_arg(arg, uint32_t*); if (ptr == NULL) { return -1; } *ptr = strtol_s(token, base, &strtolErr); if (strtolErr < 0) { return -1; } count++; } break; /********************************* * Scan default *********************************/ default: { return -1; } } } else { /* !(*fmt == '%') */ if (*fmt != *mutStr) { return -1; } else { fmt++; mutStr++; } } // END if (*fmt == '%') } // END while (*mutStr && *fmt) return count; } long strtol_s(const char* buff, uint8_t base, int8_t* err) { char* end; errno = 0; const long sl = strtol(buff, &end, base); if (end == buff) { *err = -1; //< not a decimal number } else if ('\0' != *end) { *err = -2; //< extra characters at end of input } else if ((LONG_MIN == sl || LONG_MAX == sl) && ERANGE == errno) { *err = -3; //< out of range of type long } else if (sl > INT_MAX) { *err = -4; //< greater than INT_MAX } else if (sl < INT_MIN) { *err = -5; //< less than INT_MIN } else { *err = 0; //< ok } return sl; } int main() { char test[] = "192.168.0.13"; char const* const format = "%3d.%3d.%3d.%3d"; uint32_t answer0 = 0; uint32_t answer1 = 0; uint32_t answer2 = 0; uint32_t answer3 = 0; int16_t n = strsepf(test, format, &answer0, &answer1, &answer2, &answer3); printf("Parsed %d.\n", n); return 0; }

Compiling Program...

Command line arguments:
Standard Input: Interactive Console Text
×

                

                

Program is not being debugged. Click "Debug" button to start program in debug mode.

#FunctionFile:Line
VariableValue
RegisterValue
ExpressionValue