Home > Enterprise >  transferring values into a string by function in c
transferring values into a string by function in c

Time:06-10

I need to create an encoding function that receives an original string and a pointer to a result string, encodes the original and stores the encoded string in the result string by pointer

the encoding rules are:

  1. digits are duplicated n 1 times
    e.g.: 2 will appear 2 1=3 times in result('2'-->'222')

  2. uppercase letters will turn to lowercase and the ASCII value of the lower case will be ordered in reverse and appear in the result str
    e.g: 'A' will turn to 'a' whose ASCII is 97 so in the res_str '79' will appear

  3. lowercase letters will turn to uppercase letters but in reverse order and their ASCII value will appear also reversed in the res_str
    e.g: 'a' will turn to 'Z' whose ASCII value is 90 so in the res_str '09' will appear.

I think I managed to figure out the encoding algorithm but when trying to write to the res_str I go into over flow i don't know if it's the mem allocation or the way i writeto res_str...

int get_codedstring(char *orig_str, char **coded_str)
{
    // figuring out the minimal length needed for result_str
    int len = 1; // minimal length for string that has nothing in it exept'\0'
    int i = 0;
    while (orig_str[i] != '\0')
    {
        if ((int)orig_str[i] >= BOT_DIGIT && (int)orig_str[i] <= TOP_DIGIT) // digit
            len  = (int)orig_str[i] - BOT_DIGIT   1;
        else if ((int)orig_str[i] >= BOT_UPPER && (int)orig_str[i] <= TOP_UPPER) // uppercase
        {
            if ((int)orig_str[i] >= BOT_LOWER && (int)orig_str[i] <= C)
                len  = 2;
            else
                len  = 3;
        }
        else // lowercase
            len  = 2;
        i  ;
    }
    *coded_str = malloc(sizeof(char) * len); // allocating mem for res_str
    // encoding
    i = 0;
    int j = 0;
    int temp;
    while (orig_str[i] != '\0')
    {
        if ((int)orig_str[i] >= BOT_DIGIT && (int)orig_str[i] <= TOP_DIGIT) // digit
        {
            temp = (int)orig_str[i] - BOT_DIGIT   1;

            for (j; j < temp; j  )
            {
                *(coded_str[i   j]) = orig_str[i];
            }
            j = i   j;
        }

        else if ((int)orig_str[i] >= BOT_UPPER && (int)orig_str[i] <= TOP_UPPER) // uppercase
        {
            temp = (int)orig_str[i]   32; // switch to lowercase
            // add to coded_str in reverse digit order
            if (((int)orig_str[i]   32) >= BOT_LOWER && ((int)orig_str[i]   32) <= C)
            { // a=97,b=98,c=99 the rest need 3 spaces
                *coded_str[i   j] = (char)(temp % 10)   BOT_DIGIT;
                j  ;
                *coded_str[i   j] = (char)(temp / 10)   BOT_DIGIT;
                j  ;
            }
            else
            {
                *coded_str[i   j] = (char)(temp % 100)   BOT_DIGIT;
                j  ;
                temp /= 10;
                *coded_str[i   j] = (char)(temp % 10)   BOT_DIGIT;
                j  ;
                *coded_str[i   j] = (char)(temp / 10)   BOT_DIGIT;
                j  ;
            }
        }
        else // lowercase
        {
            temp = (int)orig_str[i] - 32;          // switch to lower case
            temp = TOP_UPPER - (temp - BOT_UPPER); // reverse order
            *coded_str[i   j] = (char)(temp % 10)   BOT_DIGIT;
            j  ;
            *coded_str[i   j] = (char)(temp / 10)   BOT_DIGIT;
            j  ;
        }
        i  ;
    }
    return len;
}

the defines are:


#define BOT_DIGIT 48
#define TOP_DIGIT 57
#define BOT_UPPER 65
#define TOP_UPPER 90
#define BOT_LOWER 97
#define TOP_LOWER 122
#define C 99

CodePudding user response:

You are dereferencing coded_str wrong. You are using these which do the same thing according to C Operator Precedence:

  • *(coded_str[i j])
  • *coded_str[i j]

But you should dereference coded_str first, then use the subscript operator:

(*coded_str)[i   j]

That is however not the only problem. If calling the function like this:

int main() {
    char* encoded;
    get_codedstring("Hello world", &encoded);
}

It will calculate len to be 24 but i j goes out of bounds with

i(8)   j(17) = 25

as can be seen by adding this line before each (*coded_str)[i j]:

printf("i(%d)   j(%d) = %d\n", i, j, i   j); fflush(stdout);

This is caused by the algorithm you use to calculate the length being different from the algorithm where you actually populate the resulting array. When you populate the result, you skip one character between each encoded character. The simple solution is to use (*coded_str)[j] everywhere and not to do j = i j. Step i and j independently and then your calculation will be correct.

You may want to null terminate the result before returning too.

CodePudding user response:

  1. It is much easier if you use functions. It makes program logic much easier.
  2. Do not use "magic" numbers. Use C standard functions to determine if char is a digit or upper or lover case letter.
char *addChar(char *str, char c, size_t *size)
{
    if(!*size) *size = 1;
    str = realloc(str, *size   1);
    if(str) 
    {
        str[*size - 1] = c;
        str[*size] = 0;
        (*size)  ;
    }
    return str;
}

char *charToDec(int c, char *str, size_t *size)
{
    for(int mask = 100; mask; mask /= 10)
    {
        if(mask < 100 || c / mask) 
        {
            str = addChar(str, '0'   c / mask, size);
            if(!str) break;
            c %= mask;
        }
    }
    return str;
}

size_t myfunc(const char *str, char **result)
{
    size_t size = 0;

    while(*str)
    {
        if(isdigit((unsigned char)*str))
        {
            for(int digit = 0; digit < *str - '0'   1; digit  )
            {
                char *tmp = addChar(*result, *str, &size);
                if(tmp) *result = tmp;
                else {/* error handling */}
            }
        }
        else if(islower(*str))
        {
            char *tmp = charToDec('Z' - (*str - 'a'), *result, &size);
            if(tmp) *result = tmp;
            else {/* error handling */}
        }
        else if(isupper(*str))
        {
            char *tmp = charToDec(tolower((unsigned char)*str), *result, &size);
            if(tmp) *result = tmp;
            else {/* error handling */}
        }
        str  ;
    }
}

int main(void)
{
    char *result = NULL;

    myfunc("5aA", &result);
    printf("`%s`\n", result);
    free(result);
}

https://godbolt.org/z/Kvf3a6bqq

  •  Tags:  
  • c
  • Related