Борьба со строками C и printf% s - PullRequest
3 голосов
/ 21 октября 2019

Так что я давно борюсь с (я думаю, простой) проблемой со строками в C.

Я хочу создать список char указателей и выделить malloc() каждого из них несколькопамять для заполнения одним случайным символом. Наконец, я хочу отсортировать их и создать новую строку с strcat().

Так что в этом коде показана только первая часть с некоторыми тестовыми функциями:

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

int main(int argc, char* argv[]) {
    if (argc < 2) {
        printf("Error, too few arguments!\n");
        return 0;
    }

    // initialize random generator
    srand((unsigned int)time(NULL));

    const int a = atoi(argv[1]);

    char *array[a];

    //--------------- generate random characters ----------------------------------------
    for (int i = 0; i < a; i++) {
        int r = rand() % 30 + 1;
        printf("%d ", r);

        array[i] = (char*)malloc(a + 1 * sizeof(char));

        sprintf(array[i], "%ls", &r);
        *(array[i] + 1) = '\0';
    }

    putchar('\n');
    printf("%d %d %d \n", *array[0], *array[1], *array[2]);

    char *array_2 = (char*) malloc(a * sizeof(char));

    strcat(array_2, *array);
    strcat(array_2, *(array + 1));
    strcat(array_2, *(array + 2));

    printf("Address array_2[0] : %p , value: %d \n", array_2, *array_2);
    printf("Address array_2[1] : %p , value: %d \n", &array_2[1], array_2[1]);
    printf("Address array_2[1] : %p , value: %d \n", &array_2[2], array_2[2]);

    // produces a lot a garbage and crap
    printf("array_2 with string : %s :\n", array_2);

    // rest of the code omitted because it is irrelevant to the issue
    return 0;
}

Итак, чтоЯ не понимаю: печать символов отдельно работает нормально. Если я хочу напечатать все это как строку, я получу только зашумленную строку символов. Как я могу реализовать идею?

Честно говоря, у меня не возникает проблемы - если я создаю массив символов, такой как char array[4] = {'a','b','c', '\0'}, я могу напечатать все это с помощью "% s" ... Но в моемПрограмма почти такая же, но не работает.

Я был бы рад, если бы кто-нибудь дал мне подсказку!

Ответы [ 2 ]

3 голосов
/ 21 октября 2019

В вашем коде есть несколько проблем:

  • Размеры массивов неверны. Строки a в array будут содержать случайное число от 0 до 30, поэтому для каждого требуется максимум 3 байта (две цифры и нулевой символ), но вы выделяете a байтов. Эти цифры не связаны. array_2 должен содержать объединение всех array строк, поэтому он будет иметь длину не более 2*a байтов и ему потребуется один дополнительный байт для нулевого символа в конце.
  • Ваш sprintf равеннеправильно: sprintf(array[i], "%ls", &r) пытается интерпретировать адрес целого числа r как адрес широкого массива символов. (Это действительно выглядит так, как будто вы возились с форматом и аргументом, пока компилятор не замолчал.) Чтобы напечатать число r в строке, используйте sprintf(array[i], "%d", r).
  • sprintf уже будет иметь нулевое значение. прервите вашу строку, так что нет необходимости делать это явно.
  • Как уже указывал Руслан, ваш array_2 указывает на неинициализированную память. Функция strcat требует строки с нулевым символом в конце. Вы можете сделать array_2 допустимой пустой строкой, установив для первого символа значение null '\0'.

Чтобы исправить код, я предлагаю следующее:

  • Создайте array массив строк размером 3. Не размещайте их в куче, а сделайте их автоматическими в стеке, что проще в управлении.
  • При создании числаСтроки, отслеживать, как долго они. Функции *printf имеют полезное возвращаемое значение, а именно количество символов, которые были напечатаны или записаны в строку / файл. Используйте эту длину для выделения памяти для array_2.
  • Инициализируйте array_2 как допустимую пустую строку, затем strcat все array строки array_2.
  • Делайте интересные вещис array_2, затем free выделенной памятью.

Вот код для этого:

int a = 8;
char array[a][3];
int len = 0;

for (int i = 0; i < a; i++) {
    int r = rand() % 30 + 1;

    printf("%d\n", r);
    len += sprintf(array[i], "%d", r);
}

char *array_2 = malloc(len + 1);

*array_2 = '\0';
for (int i = 0; i < a; i++) {
    strcat(array_2, array[i]);
}

printf("\"%s\"\n", array_2);
free(array_2);
2 голосов
/ 21 октября 2019

char *array_2 = (char*) malloc(a * sizeof(char));

strcat(array_2, *array);

Вы выделили array_2, не инициализировали его, а затем добавляете *array к любомумусор array_2 имел. Этот мусор, вероятно, содержит множество управляющих символов, печатных символов и еще много чего еще до появления нулевого символа, поэтому вы получаете все эти символы на своей консоли (возможно, со случайными звуковыми сигналами).

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...