Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- #include <inttypes.h>
- #include <stdbool.h>
- #include <stdint.h>
- #include <stdio.h>
- #include <stdlib.h>
- #include <string.h>
- #include <vcruntime.h>
- #define lengthof(x) (sizeof(x) / sizeof(*(x)))
- void *safemalloc(size_t size) {
- void *block = malloc(size);
- if (!block) {
- (void)fputs("Memory allocation has failed.", stderr);
- abort();
- }
- return block;
- }
- void *saferealloc(void *block, size_t size) {
- char *newBlock = realloc(block, size);
- if (!newBlock) {
- (void)fputs("Memory reallocation has failed.", stderr);
- abort();
- }
- return newBlock;
- }
- char *input(uint16_t maxLength) {
- if (!maxLength) {
- return NULL;
- }
- int32_t inputStringSize = maxLength + 2;
- char *inputString = safemalloc(inputStringSize);
- if (!fgets(inputString, inputStringSize, stdin)) {
- free(inputString);
- while (getchar() != '\n') {
- }
- return NULL;
- }
- if (inputString[0] == '\n') {
- free(inputString);
- return NULL;
- }
- size_t inputStringLength = strlen(inputString);
- char *lastStringCharacterPtr = &(inputString[inputStringLength - 1]);
- if (*lastStringCharacterPtr != '\n') {
- free(inputString);
- while (getchar() != '\n') {
- }
- return NULL;
- }
- *lastStringCharacterPtr = '\0';
- return saferealloc(inputString, inputStringLength);
- }
- uint64_t abs64(int64_t integer) { return integer < 0 ? -(uint64_t)integer : integer; }
- typedef struct {
- int64_t integer;
- const char *error;
- } StringToIntResult;
- StringToIntResult *stringToInt(const char *string) {
- StringToIntResult *result = safemalloc(sizeof(StringToIntResult));
- if (!string) {
- *result = (StringToIntResult){0, "Passed NULL."};
- return result;
- }
- if (string[0] == '\0') {
- *result = (StringToIntResult){0, "Invalid string."};
- return result;
- }
- bool startsWithNegativeSign = (string[0] == '-');
- if (startsWithNegativeSign) {
- string = string + 1;
- }
- uint64_t maxInt = abs64(startsWithNegativeSign ? INT64_MIN : INT64_MAX);
- uint8_t maxDigitNumber = snprintf( // NOLINT(clang-analyzer-security.insecureAPI.DeprecatedOrUnsafeBufferHandling)
- NULL, 0, "%" PRIu64, maxInt);
- size_t stringLength = strlen(string);
- if (stringLength == 0 || string[0] == '0' || stringLength > maxDigitNumber) {
- *result = (StringToIntResult){0, "Invalid string."};
- return result;
- }
- for (uint32_t i = 0; i < stringLength; ++i) {
- if (string[i] < '0' || string[i] > '9') {
- *result = (StringToIntResult){0, "The string contains non numerical characters."};
- return result;
- }
- }
- if (stringLength == maxDigitNumber) {
- char *maxString = safemalloc(maxDigitNumber + 1);
- (void)snprintf(maxString, // NOLINT(clang-analyzer-security.insecureAPI.DeprecatedOrUnsafeBufferHandling)
- maxDigitNumber + 1, "%" PRIu64, maxInt);
- for (uint32_t i = 0; i < stringLength; ++i) {
- if (string[i] > maxString[i]) {
- free(maxString);
- *result = (StringToIntResult){0, "The resulting integer is too large."};
- return result;
- }
- }
- free(maxString);
- }
- int64_t integer = strtoll(string, NULL, 10);
- if (startsWithNegativeSign) {
- integer = -integer;
- }
- *result = (StringToIntResult){integer, NULL};
- return result;
- }
- typedef struct {
- size_t smallerIndex;
- size_t biggerIndex;
- } ClosestNumberIndeces;
- ClosestNumberIndeces *calculate(int32_t *array, size_t size) {
- if (size < 2) {
- puts("The array has to have at least 2 elements.");
- abort();
- }
- ClosestNumberIndeces *closestNumberIndeces = safemalloc(sizeof(ClosestNumberIndeces));
- *closestNumberIndeces = (ClosestNumberIndeces){0, 1};
- if (size == 2 || !abs64((int64_t)(array[closestNumberIndeces->smallerIndex]) -
- (int64_t)(array[closestNumberIndeces->biggerIndex]))) {
- return closestNumberIndeces;
- }
- uint64_t iterationAbsoluteDifference = 0;
- for (size_t i = 0; i < size; ++i) {
- for (size_t j = i + 1; j < size; ++j) {
- iterationAbsoluteDifference = abs64((int64_t)(array[i]) - (int64_t)(array[j]));
- if (iterationAbsoluteDifference == 0) {
- *closestNumberIndeces = (ClosestNumberIndeces){i, j};
- return closestNumberIndeces;
- }
- if (iterationAbsoluteDifference < abs64((int64_t)(array[closestNumberIndeces->smallerIndex]) -
- (int64_t)(array[closestNumberIndeces->biggerIndex]))) {
- *closestNumberIndeces = (ClosestNumberIndeces){i, j};
- }
- }
- }
- return closestNumberIndeces;
- }
- int main() {
- printf("Enter array size >>> ");
- char *arraySizeString = input(9);
- if (!arraySizeString) {
- puts("Invalid input.");
- return 1;
- }
- StringToIntResult *arraySizeResult = stringToInt(arraySizeString);
- free(arraySizeString);
- if (arraySizeResult->error) {
- puts(arraySizeResult->error);
- free(arraySizeResult);
- return 1;
- }
- int32_t *array = safemalloc(sizeof(int32_t) * arraySizeResult->integer);
- for (size_t i = 0; i < arraySizeResult->integer; ++i) {
- printf("Enter array element >>> ");
- char *elementString = input(9);
- if (!elementString) {
- free(arraySizeResult);
- free(array);
- puts("Invalid input.");
- return 1;
- }
- StringToIntResult *elementResult = stringToInt(elementString);
- free(elementString);
- if (elementResult->error) {
- free(arraySizeResult);
- free(array);
- puts(elementResult->error);
- free(elementResult);
- return 1;
- }
- array[i] = (int32_t)elementResult->integer;
- free(elementResult);
- }
- ClosestNumberIndeces *closestNumberIndeces = calculate(array, arraySizeResult->integer);
- free(arraySizeResult);
- free(array);
- printf("%" PRIu64 " %" PRIu64, closestNumberIndeces->smallerIndex, closestNumberIndeces->biggerIndex);
- free(closestNumberIndeces);
- return 0;
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement