целочисленный массив в строку указателя символа - PullRequest
0 голосов
/ 23 февраля 2019

Я пытаюсь преобразовать массив int в строку указателя на символ (значения массива преобразованы в шестнадцатеричное). Я использую редактор кодовых блоков.поэтому

                           int arr[4] = {30, 40, 15, 205};

следует преобразовать в

                            char *str =  "1e280fcd";

. Для этого я написал следующую программу:

#include <stdio.h>
#include <string.h>
#include <stdlib.h>

int main()
{
    char *cur_str, *prev_str;
    char *comp_str, *comp_str_copy;
    int arr[] = {30,40,15,205}, i, j, arr_length;
    arr_length = (sizeof(arr)/sizeof(arr[0]));
    prev_str = malloc(sizeof(0));
    cur_str = malloc(sizeof(0));
    comp_str = malloc(sizeof(0));
    for(i=0;i<arr_length;i++)
    {
        cur_str = malloc(2);
        sprintf(cur_str,"%02x",arr[i]);

        comp_str = malloc(sizeof(cur_str)+sizeof(prev_str));
        sprintf(comp_str,"%s%s",prev_str,cur_str);
        printf("%s\n",comp_str);

        free(prev_str);
        prev_str = malloc(sizeof(comp_str));
        sprintf(prev_str,"%s",comp_str);

        if(i==(arr_length-1)){
            comp_str_copy = malloc(sizeof(comp_str));
            sprintf(comp_str_copy,"%s",comp_str);
        }

        free(comp_str);
        free(cur_str);
    }
    printf("%s %d\n",comp_str_copy,strlen(comp_str_copy));
    return 0;
}

Вывод этой программы:

  • ошибка сегментации или
  • Строка со значением мусора в начальных местоположениях

enter image description here

enter image description here

Я запускал одну и ту же программу на разных онлайн-компиляторах.Все они выдают правильную строку в качестве вывода. Использует ли редактор проблему или методы управления памятью?

Ответы [ 3 ]

0 голосов
/ 23 февраля 2019

Это было много динамического выделения памяти для простой задачи.Если массив и строка останутся «маленькими», используйте стек в своих интересах:

#include <assert.h>
#include <stdio.h>

int main() {
    int const arr[] = {30, 40, 15, 205};
    int const arr_length = sizeof(arr) / sizeof(arr[0]);
    char str[2 * arr_length + 1];
    int len = 0;
    for (int i = 0; i < arr_length; i++) {
        len += sprintf(&str[len], "%02x", arr[i]);
    }
    assert(len == 2 * arr_length);
    printf("%s %d\n", str, len);
    return 0;
}

Но если вам действительно нужна динамическая строка, то есть char *str только что измененная char str[2 * arr_length + 1]; до

char *str = malloc(2 * arr_length + 1);

и добавьте free(str);

Примечание: все это предполагает, что целочисленные значения массива меньше 256.

0 голосов
/ 24 февраля 2019

следующий предложенный код:

  1. устраняет ненужную логику кода
  2. устраняет ненужные переменные
  3. устраняет ненужное использование динамической памяти
  4. чисто компилирует
  5. НЕ вызывает ошибку
  6. выполняет желаемую функциональность
  7. обратите внимание, что strlen() возвращает size_t, а не int
  8. обратите внимание, что sizeof() возвращает size_t, а не int
  9. , умножает длину массива arr[] на 2, чтобы вычислить количество символов, необходимое для отображения преобразованного массива
  10. добавляет 1 к вычисленной длине, чтобы учесть завершающий байт NUL
  11. перечисляет переменные в необходимом порядке, поэтому при необходимости всегда доступны конкретные параметры

А теперь предложенный код:

#include <stdio.h>
#include <string.h>

int main( void )
{
    int arr[] = {30,40,15,205};
    char comp_str[ sizeof( arr )*2 +1 ] = {'\0'};  

    size_t arr_length = (sizeof(arr)/sizeof(arr[0]));

    for( size_t i=0; i<arr_length; i++ )
    {          
        sprintf( comp_str,"%s%02x", comp_str, arr[i] );
        printf("%s\n",comp_str);
    }
}

Запуск предложенного кода приводит к:

1e
1e28
1e280f
1e280fcd
0 голосов
/ 23 февраля 2019

В

    cur_str = malloc(2);
    sprintf(cur_str,"%02x",arr[i]);

sprintf введите 3 символа, включая последний нулевой, в то время как вы выделили только 2

В

comp_str = malloc(sizeof(cur_str)+sizeof(prev_str));

длина allocate не правильная, потому что size_of не возвращает то, что вы ожидаете, должно быть

comp_str = malloc(strlen(cur_str)+strlen(prev_str)+1);

, но, конечно, предполагается, что prev_str также является правильной строкой в ​​начале, иэто не тот случай

Эти два malloc вызовут утечки памяти, потому что нет свободных (или не используемых)

cur_str = malloc(sizeof(0));
comp_str = malloc(sizeof(0));

Почему вы не используете realloc для увеличения размера prev_str?

Обратите внимание, что конечный необходимый размер легко узнать: sizeof(arr)/sizeof(arr[0]) * 2 + 1 если число ограничено 255 (2 цифры в гекса)

Предложение (без указания всех чисел <256): </p>

#include <string.h>
#include <stdlib.h>

int main()
{
    int arr[] = {30,40,15,205};
    size_t arr_length = sizeof(arr)/sizeof(arr[0]);
    size_t i;
    size_t sz = 0;
    char * r = malloc(0);

    for (i=0; i!= arr_length; ++i)
    {
      char s[20];
      int l = sprintf(s, "%02x",arr[i]);

      r = realloc(r, sz + l + 1);
      strcpy(r + sz, s);
      sz += l;
    }
    printf("%s %d\n", r, sz);
    free(r);
    return 0;
}

Компиляция и выполнение:

pi@raspberrypi:/tmp $ gcc -g -pedantic -Wextra a.c
pi@raspberrypi:/tmp $ ./a.out
1e280fcd 8

Исполнение под valgrind

pi@raspberrypi:/tmp $ valgrind ./a.out
==2985== Memcheck, a memory error detector
==2985== Copyright (C) 2002-2017, and GNU GPL'd, by Julian Seward et al.
==2985== Using Valgrind-3.13.0 and LibVEX; rerun with -h for copyright info
==2985== Command: ./a.out
==2985== 
1e280fcd 8
==2985== 
==2985== HEAP SUMMARY:
==2985==     in use at exit: 0 bytes in 0 blocks
==2985==   total heap usage: 6 allocs, 6 frees, 1,048 bytes allocated
==2985== 
==2985== All heap blocks were freed -- no leaks are possible
==2985== 
==2985== For counts of detected and suppressed errors, rerun with: -v
==2985== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 6 from 3)
...