From 7a3fedfb3e1764c6c803e70d6f4aeb01cd18a2ca Mon Sep 17 00:00:00 2001 From: "ivanleu14@gmail.com" Date: Sat, 11 May 2024 23:33:37 +0300 Subject: [PATCH 1/5] stringToInt feature implemented --- cstring.h | 78 ++++++++++++++++++++++++++++++++++++++++++++++++++-- tests/main.c | 17 ++++++++++++ 2 files changed, 93 insertions(+), 2 deletions(-) diff --git a/cstring.h b/cstring.h index ba1bf2d..b3b0b76 100644 --- a/cstring.h +++ b/cstring.h @@ -5,6 +5,7 @@ #include #include #include +#include typedef enum EErrorCode { ERR_NO_ERROR, @@ -15,6 +16,7 @@ typedef enum EErrorCode { ERR_INVALID_STATE, ERR_NULL_POINTER, ERR_NUMBER_OVERFLOW, + ERR_INVALID_NUMBER_REPR, } EErrorCode; #define MAX_ERROR_MSG_LEN 300 @@ -40,6 +42,9 @@ bool stringCharIsAlphanum(char c); char stringCharToLower(char c); char stringCharToUpper(char c); +int stringCharToInt(char c); +int64_t stringCharToInt64(char c); + bool stringStartWith(TString s, TString pref); bool stringStartWithCharArr(TString s, char *pref); bool stringEndWith(TString s, TString pref); @@ -60,6 +65,7 @@ int stringCompare(TString s1, TString s2); int64_t stringFindFirst(TString s, TString pattern); int64_t stringFindFirstCharArr(TString s, const char *pattern); +int64_t stringToInt(TString s); TString stringRand(size_t size); TString stringInit(size_t capacity); @@ -75,6 +81,7 @@ TString stringJoinCharArr(TString s1, TString s2, const char *delim); TString stringArrJoin(const TString *s, size_t count, TString delim); TString stringArrJoinCharArr(const TString *s, size_t count, const char *delim); +char* stringConvertToCharArr(const TString s); void stringScan(TString *s); void stringPrint(TString s); @@ -218,8 +225,6 @@ void stringIncreaseCap(TString *s) { s->capacity = newCap; } - - // import bool stringCharIsDigit(char c) { @@ -243,6 +248,16 @@ char stringCharToUpper(char c) { return c; } +int stringCharToInt(char c) { + if ('0' <= c && c <= '9') return c - '0'; + return -1; +} + +int64_t stringCharToInt64(char c) { + if ('0' <= c && c <= '9') return (int64_t)(c - '0'); + return (int64_t)-1; +} + bool stringStartWith(TString s, TString pref) { if (s.size < pref.size) return false; return stringCompSubstr(s.data, 0, pref.size, pref.data, @@ -363,6 +378,44 @@ int64_t stringFindFirstCharArr(TString s, const char *pattern) { return -1; } +int64_t stringToInt(TString s) { + int64_t sign = 1; + size_t len = stringLen(s); + + char* str = stringConvertToCharArr(s); + + if(str[0] == '-'){ + if(len == 1) { + setError(ERR_INVALID_NUMBER_REPR); + return 0; + } + sign = -1; + str++; + } + + int64_t val = 0; + while( *str != '\0' ) { + val = val * 10 + stringCharToInt64(*str); + + // overflow + if(val < 0) { + setError(ERR_NUMBER_OVERFLOW); + return val; + } + + str++; + } + val = val * sign; + + // free(strlen) throws an exception here + // The reason is that the pointer is incremented each iteration + // And for succesful deallocation it should point to the address + // of the memory that malloc returned + free(str - len); + + return val; +} + TString stringInit(size_t capacity) { TString s = {0}; s.data = (char *) malloc(sizeof(char) * capacity); @@ -608,6 +661,27 @@ TString stringSubstring(TString s, size_t pos, size_t len) { return res; } +char* stringConvertToCharArr(const TString s) { + if (s.data == NULL) return NULL; + clearError(); + size_t len = stringLen(s); + char *res = malloc(len + 1); + + if(res == NULL) { + setError(ERR_NULL_POINTER); + } + + if (isError()) { + return res; + } + + for (size_t i = 0; i < len; ++i) { + res[i] = s.data[i]; + } + res[len] = '\0'; + return res; +} + void stringScan(TString *s) { if (s == NULL) { setError(ERR_NULL_POINTER); diff --git a/tests/main.c b/tests/main.c index fe2513c..e43050e 100644 --- a/tests/main.c +++ b/tests/main.c @@ -471,6 +471,22 @@ void test_stringRemove() { printGreen("test_stringRemove\n"); } +void test_stringToInt() { + TString s1 = stringInitWithCharArr("0"); + TString s2 = stringInitWithCharArr("-2132456"); + TString s3 = stringInitWithCharArr("54377345"); + + assertEq(stringToInt(s1), 0); + assertEq(stringToInt(s2), -2132456); + assertEq(stringToInt(s3), 54377345); + + stringDestroy(&s1); + stringDestroy(&s2); + stringDestroy(&s3); + + printGreen("test_stringToInt\n"); +} + int main() { test_stringStartWith(); test_stringEndWith(); @@ -498,6 +514,7 @@ int main() { test_stringIsPalindrome(); test_stringPad(); test_stringRemove(); + test_stringToInt(); return 0; } From e3e9a4e8c4c9f88a896abe25564013570de15189 Mon Sep 17 00:00:00 2001 From: "ivanleu14@gmail.com" Date: Sun, 12 May 2024 10:06:15 +0300 Subject: [PATCH 2/5] added check for validity of the string passed in stringToInt function --- cstring.h | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/cstring.h b/cstring.h index b3b0b76..dc209df 100644 --- a/cstring.h +++ b/cstring.h @@ -395,9 +395,16 @@ int64_t stringToInt(TString s) { int64_t val = 0; while( *str != '\0' ) { - val = val * 10 + stringCharToInt64(*str); + int64_t digit = stringCharToInt64(*str); + // check for non numeric characters in string + if(digit == -1) { + setError(ERR_INVALID_NUMBER_REPR); + return 0; + } + + val = val * 10 + digit; - // overflow + // check for integer overflow if(val < 0) { setError(ERR_NUMBER_OVERFLOW); return val; @@ -409,7 +416,7 @@ int64_t stringToInt(TString s) { // free(strlen) throws an exception here // The reason is that the pointer is incremented each iteration - // And for succesful deallocation it should point to the address + // And for succesful deallocation it should point to the same address // of the memory that malloc returned free(str - len); From 3047804f7e3fe97c8522663180e6d3e9f38687d9 Mon Sep 17 00:00:00 2001 From: "ivanleu14@gmail.com" Date: Thu, 16 May 2024 07:21:33 +0300 Subject: [PATCH 3/5] updated functions definitions considering suggestions --- cstring.h | 63 +++++++++++++++++++------------------------------------ 1 file changed, 21 insertions(+), 42 deletions(-) diff --git a/cstring.h b/cstring.h index dc209df..cb1d63c 100644 --- a/cstring.h +++ b/cstring.h @@ -43,7 +43,6 @@ char stringCharToLower(char c); char stringCharToUpper(char c); int stringCharToInt(char c); -int64_t stringCharToInt64(char c); bool stringStartWith(TString s, TString pref); bool stringStartWithCharArr(TString s, char *pref); @@ -249,15 +248,12 @@ char stringCharToUpper(char c) { } int stringCharToInt(char c) { - if ('0' <= c && c <= '9') return c - '0'; + if ('0' <= c && c <= '9') + return c - '0'; + setError(ERR_INVALID_NUMBER_REPR); return -1; } -int64_t stringCharToInt64(char c) { - if ('0' <= c && c <= '9') return (int64_t)(c - '0'); - return (int64_t)-1; -} - bool stringStartWith(TString s, TString pref) { if (s.size < pref.size) return false; return stringCompSubstr(s.data, 0, pref.size, pref.data, @@ -380,46 +376,31 @@ int64_t stringFindFirstCharArr(TString s, const char *pattern) { int64_t stringToInt(TString s) { int64_t sign = 1; - size_t len = stringLen(s); - - char* str = stringConvertToCharArr(s); + int i = 0; - if(str[0] == '-'){ - if(len == 1) { + if (s.data[0] == '-') { + if (s.size == 1) { setError(ERR_INVALID_NUMBER_REPR); return 0; } sign = -1; - str++; + i++; } int64_t val = 0; - while( *str != '\0' ) { - int64_t digit = stringCharToInt64(*str); - // check for non numeric characters in string - if(digit == -1) { - setError(ERR_INVALID_NUMBER_REPR); - return 0; - } - - val = val * 10 + digit; - - // check for integer overflow - if(val < 0) { + for (; i < s.size; i++) { + int64_t digit = stringCharToInt(s.data[i]); + + if (val * 10 > INT64_MAX - digit) { setError(ERR_NUMBER_OVERFLOW); return val; } - - str++; + else { + val = val * 10 + digit; + } } val = val * sign; - // free(strlen) throws an exception here - // The reason is that the pointer is incremented each iteration - // And for succesful deallocation it should point to the same address - // of the memory that malloc returned - free(str - len); - return val; } @@ -669,23 +650,21 @@ TString stringSubstring(TString s, size_t pos, size_t len) { } char* stringConvertToCharArr(const TString s) { - if (s.data == NULL) return NULL; + if (s.data == NULL) + return NULL; + clearError(); - size_t len = stringLen(s); - char *res = malloc(len + 1); + char *res = malloc(s.size + 1); if(res == NULL) { setError(ERR_NULL_POINTER); + return NULL; } - if (isError()) { - return res; - } - - for (size_t i = 0; i < len; ++i) { + for (size_t i = 0; i < s.size; ++i) { res[i] = s.data[i]; } - res[len] = '\0'; + res[s.size] = '\0'; return res; } From 41dafebef49c55158ec55780d07c2ac32ec239a4 Mon Sep 17 00:00:00 2001 From: Ivan <145929083+IvanLeu@users.noreply.github.com> Date: Fri, 17 May 2024 23:13:16 +0300 Subject: [PATCH 4/5] working check for integer64 overflow in stringToInt --- cstring.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cstring.h b/cstring.h index cb1d63c..38fb25d 100644 --- a/cstring.h +++ b/cstring.h @@ -391,7 +391,7 @@ int64_t stringToInt(TString s) { for (; i < s.size; i++) { int64_t digit = stringCharToInt(s.data[i]); - if (val * 10 > INT64_MAX - digit) { + if (val > (INT64_MAX - digit) / 10) { setError(ERR_NUMBER_OVERFLOW); return val; } From 122461df453da60ca58cf5de35b24c40d5765a2e Mon Sep 17 00:00:00 2001 From: Ivan <145929083+IvanLeu@users.noreply.github.com> Date: Sun, 2 Jun 2024 14:32:56 +0300 Subject: [PATCH 5/5] resolved issues in stringToInt and stringCharToInt --- cstring.h | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/cstring.h b/cstring.h index 38fb25d..d9a3710 100644 --- a/cstring.h +++ b/cstring.h @@ -248,6 +248,7 @@ char stringCharToUpper(char c) { } int stringCharToInt(char c) { + clearError(); if ('0' <= c && c <= '9') return c - '0'; setError(ERR_INVALID_NUMBER_REPR); @@ -375,6 +376,8 @@ int64_t stringFindFirstCharArr(TString s, const char *pattern) { } int64_t stringToInt(TString s) { + clearError(); + int64_t sign = 1; int i = 0; @@ -390,8 +393,9 @@ int64_t stringToInt(TString s) { int64_t val = 0; for (; i < s.size; i++) { int64_t digit = stringCharToInt(s.data[i]); - - if (val > (INT64_MAX - digit) / 10) { + + // TODO: check for INT64_MIN overflow + if (val >= (INT64_MAX - digit) / 10) { setError(ERR_NUMBER_OVERFLOW); return val; }