Я пытаюсь присвоить отдельный номер в целочисленной переменной динамическому массиву в c. Но почему-то не работает

Итак, я пытаюсь протестировать этот код, который, похоже, не работает должным образом. Я раньше не использовал C и делаю это для CS50 (кто знаком с ним 1 неделю).

Итак, по сути, у меня есть целое число, скажем, 12345. Я пытаюсь присвоить первое число (1) индексу 0 динамического массива и так далее.

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

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




int countDigits(int num) //this gives the length of the integer
{
    int count = 0;

    while(num != 0)
    {
        count++;
        num = num/10;
    }
    return count;
}


int main(void)
{
    int num = get_long("num: ");

    int length = countDigits(num);

    printf("%d \n", length); //printing test to see if it has returned the correct length, and it does

    int* array; //declare the pointer

    array = (int*) malloc(length * sizeof(int));  // declare the dynamic array

    for(int i = 0; i < length ;i ++)
    {
        printf("%d", array[i]);  //print out the array first to see the content
    }
    printf("\n");

    for(int k = 0; k < 2 ; k ++)
    {
        array[length] = (num % 10);  //this is just a testing enviroment for me to assign numbers (i am currently keeping it two digits)
        num = num/10;
        length --;
    }

    for(int j = 0; j < 2 ;j ++)
    {
        printf("%d \n", array[length]);  //once again i print out the content and see if its correct and its not
    }
}

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

Когда вы выделяете память с помощью malloc, память никак не инициализируется. Вся память будет содержать неопределенные (читай: мусор) данные.

Some programmer dude 17.04.2024 23:01

Как мне тогда подойти к этой проблеме?

GhostaNero 17.04.2024 23:04

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

Some programmer dude 17.04.2024 23:08

это для другого проекта, где я пытаюсь реализовать алогрифм Луна для проверки кредитной карты. Мой подход заключался в том, чтобы получить длину кредитной карты и объявить массив этой длины. Тогда, поскольку я использую оператор модуля, используя длину, он не будет инвертирован.

GhostaNero 17.04.2024 23:12

Тогда я предлагаю вам работать со строками и символами вместо чисел. Прежде всего, CC-номера обычно содержат больше цифр, которые можно обработать одним int. Во-вторых, используя int, вы потеряете ведущие нули.

Some programmer dude 17.04.2024 23:15

Вы уверены, что int num = get_long("num: "); не смешивает типы?

Weather Vane 17.04.2024 23:17

можно ли выполнять вычисления со строками и символами в C? (Питон этого не делает)

GhostaNero 17.04.2024 23:17

@ user24446695 Да, это возможно. C гарантирует, что вы можете сделать, например. '3' - '0' и получите целое значение 3. Итак, чтобы получить целочисленный эквивалент символа в строке str, вы используете str[i] - '0'. Но, пожалуйста, не будьте консервативны при создании строки (используя простой массив символов), используйте размер, который, как вы знаете, вы никогда не получите. Тогда вам не придется беспокоиться о таких вещах, как терминатор строки. Назовите не менее 32 символов.

Some programmer dude 17.04.2024 23:18

Да, вы правы, я забыл это изменить, когда пытался это проверить (скопировать и вставить из другого файла.)

GhostaNero 17.04.2024 23:18

Ого, это на самом деле очень приятно. Я обязательно переключусь и буду использовать его. Спасибо за помощь!

GhostaNero 17.04.2024 23:19
printf("%d \n", array[length]); Вероятно, вы захотите либо изменить length, либо каким-то образом использовать j, если только вы не хотите печатать один и тот же индекс несколько раз.
Retired Ninja 17.04.2024 23:20
array[length] = (num % 10); нарушит границы массива. length в первой итерации — это количество элементов, индексировать можно только от [0] до [length-1].
Weather Vane 17.04.2024 23:20

В последнем цикле должно быть printf("%d \n", array[length]); printf("%d \n", array[j]); ?

Weather Vane 17.04.2024 23:23

На самом деле я такой тупой, что вы, ребята, все заметили мои глупые ошибки. В свою защиту скажу, что я не выпил чашку кофе. (Большое спасибо!)

GhostaNero 17.04.2024 23:26

Не будьте слишком умными... Если проблема в алгоритме Луна, то данные представляют собой «числа» CC. Предполагается, что они «размером с человека» (т. е. не имеют длину 328 цифр). Более простой код будет использовать массив времени компиляции, скажем, 32 или 64 байта, избегая сложностей выделения кучи. (Вы забыли free() блок.) Используйте стек размером 8 МБ (или 1 МБ), предоставленный вашей программе, и напишите более простой код «KISS»...

Fe2O3 17.04.2024 23:45
Структурированный массив Numpy
Структурированный массив Numpy
Однако в реальных проектах я чаще всего имею дело со списками, состоящими из нескольких типов данных. Как мы можем использовать массивы numpy, чтобы...
T - 1Bits: Генерация последовательного массива
T - 1Bits: Генерация последовательного массива
По мере того, как мы пишем все больше кода, мы привыкаем к определенным способам действий. То тут, то там мы находим код, который заставляет нас...
Что такое деструктуризация массива в JavaScript?
Что такое деструктуризация массива в JavaScript?
Деструктуризация позволяет распаковывать значения из массивов и добавлять их в отдельные переменные.
0
15
78
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Основная проблема заключается в следующем задании:

array[length] = (num % 10)

Когда цикл запускается, вы назначаете элемент, который находится за пределами массива. Выход за пределы массива (фиксированные или динамические) приводит к неопределенному поведению.

Либо используйте lenght - 1 в качестве индекса, либо --length. Но в обоих случаях вам нужно это явно проверить length > 0.

Затем, когда вы печатаете содержимое массива, вы печатаете только один элемент, который может быть действительным, а может и не быть.


Если вы хотите использовать только два элемента массива, прежде всего убедитесь, что ваши циклы не выходят за пределы (используйте k < 2 && k < length в качестве условия). Затем просто используйте k в качестве индекса:

array[k] = (num % 10)

Чтобы быть более ясным, не выводите значения сразу после вызова malloc. А циклы установки значений и их печати должны выглядеть так:

for(size_t k = 0; k < 2 && k < length; k++)
{
    // Do what your loops needs to do
    // Using the variable k as the index
}

Я сделал это сейчас, теперь он действительно присваивает номера, но показывает, что сохранены 1 и 1, а не 1 и 2 (тестовые данные — 12). Также из любопытства, поскольку я больше использую Python, как на самом деле работает malloc (да, я прочитал некоторые руководства), я подумал, что это похоже на объявление массива в Python с двумя индексами.

GhostaNero 17.04.2024 23:09

@user24446695 malloc(length * sizeof(int)) выделит достаточно байтов для length количества int элементов. И, как и все массивы в C, индекс начинается с нуля, поэтому у вас есть индексы элементов от 0 до length - 1.

Some programmer dude 17.04.2024 23:12

По сути, вы говорите, что если бы длина была равна 2, было бы выделено достаточно байтов для двух элементов int или буквально числа 2?

GhostaNero 17.04.2024 23:16

@ user24446695 Достаточно для двух элементов. И действительными индексами будут 0 и 1.

Some programmer dude 17.04.2024 23:17

Другие вопросы по теме