Ошибка сегментации при копировании строковых элементов в другую строку - PullRequest
0 голосов
/ 23 июня 2018

Почему у меня ошибка сегментации? Я перечислил мой код ниже.

Скажите, пожалуйста, кто-нибудь знает, в чем здесь моя вина и как я могу исправить ее?

Что я пытаюсь сделать здесь

Я пытаюсь взять числа в качестве входных данных, и для них я должен вывести строку символов.

Задача

ссылка на проблему находится здесь.

Код моего предложенного решения

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

int main() {

    long long int n, k;
    char manku[] = { 'm', 'a', 'n', 'k', 'u' };
    char l[10000000];
    int t, i = 0, j, p;
    scanf("%d", &t);

    while (t > 0)
    {
        scanf("%lld", &n);

        while (n > 0)
        {
            j = n % 5;
            if (j == 0)
                l[i] = manku[4];
            else
                l[i] = manku[j - 1];

            n = n / 5;
            i++;
        }

        p = strlen(l);

        for (i = 0; i < p; i++)
            l[i] = l[p - 1 - i];

        for (i = 0; i < p; i++)
            printf("%c", l[i]);

        t--;
    }

    return 0;
}

Ответы [ 4 ]

0 голосов
/ 23 июня 2018

Краткий ответ: Ошибка сегментации вызвана char l[10000000];. Декалирование char l[26]; достаточно.

Детали

Как уже говорили другие, распределение char l[10000000]; вызывает ошибку сегментации. Вам не нужно так много памяти. В вопросе говорилось, что максимальное значение для n составляет 10 ^ 18. Таким образом, максимальная длина слова будет 26 символов. Таким образом, char l[26]; достаточно.

Объяснение: Имеется 10 или 18 вариантов размещения символов k. У каждого персонажа есть 5 опций, и поэтому количество опций для размещения этих символов составляет 5^k Теперь вам просто нужно найти k:

5^k = 10^18  ==>  k = log_5(10^18) ~= 25.75218 < 26 

Осуществление

Что касается реализации, у вас есть несколько неправильных вещей.

  • Вы не устанавливаете i = 0; после каждого входного сканирования.
  • Вы не можете использовать strlen без завершающего нулевого символа. Вы должны добавить l[i] = '\0'; выше p = strlen(l);.
  • Ваш второй цикл for, который должен возвращать строку, не работает должным образом. Каждый шаг изменяет строку и шаги после нее используют измененную строку (вместо работы с исходной).

Что касается алгоритма, он также не работает должным образом. Я могу дать вам подсказку: эта проблема похожа на подсчет в base-5 .

Комментарии

Все вышесказанное - это всего лишь несколько вещей, которые я заметил. Я думаю, вам следует подумать о переписывании кода, поскольку он все еще может содержать небольшие недостатки.

Еще один совет: для печати строк (символьных массивов в c) вы можете использовать

printf("%s", str);

Предполагая, что str является массивом символов, который заканчивается завершающим нулевым символом. Еще немного информации здесь .

0 голосов
/ 23 июня 2018

Вы получаете ошибку сегментации, когда запускаете двоичный файл, потому что у вас заканчивается память стека из-за большого размера массива char l[10000000] (вы можете проверить размер стека, запустив

$ ulimit -s

в вашей оболочке).

Для этого есть как минимум два решения:

  1. Увеличьте размер вашего стека.Вы можете сделать это, запустив, например,

    $ ulimit -s unlimited
    

    в своей оболочке перед запуском двоичного файла.

  2. Используйте malloc для выделения массива l,так что он размещается в куче, а не в стеке.

0 голосов
/ 23 июня 2018
char l[10000000];

Этот огромный массив переполняет вашу память стека.
Сегмент стековой памяти - это область памяти, выделенная для автоматических переменных, и его размер довольно мал. Не очень хорошая идея иметь такой большой массив в стеке. Попробуйте выделить его динамически, например так:

char *l;
l = malloc(10000000);  //note: size of char is 1

При этом память выделяется на l в сегменте кучи. Удостоверьтесь, что free это как только вы сделали с ним.

В качестве альтернативы, вы можете сделать l глобальной или статической локальной переменной, чтобы она вошла в Сегмент данных .

0 голосов
/ 23 июня 2018

Во-первых, инициализировать переменную i после сканирования n.

while(t>0) {
    scanf("%lld",&n);
    i = 0; /* initialize i every time here */

    while(n>0) {
       /* some code */
    }
}

Кроме того, вместо создания массива, созданного в стеке, например char l[10000000];, создайте динамический массив один раз перед циклом while и free динамически распределенной памятью после завершения. например,

char *l = malloc(SIZE); /* define the SIZE */
...
...
free(l);
...