Итак, я пытаюсь протестировать этот код, который, похоже, не работает должным образом. Я раньше не использовал 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.
Как мне тогда подойти к этой проблеме?
Кроме того, почему вы выделяете элементы length
, но используете только два из этих элементов? И, как я упоминаю в своем ответе, будьте осторожны, если пользователь ввел в качестве входных данных только однозначное значение.
это для другого проекта, где я пытаюсь реализовать алогрифм Луна для проверки кредитной карты. Мой подход заключался в том, чтобы получить длину кредитной карты и объявить массив этой длины. Тогда, поскольку я использую оператор модуля, используя длину, он не будет инвертирован.
Тогда я предлагаю вам работать со строками и символами вместо чисел. Прежде всего, CC-номера обычно содержат больше цифр, которые можно обработать одним int
. Во-вторых, используя int
, вы потеряете ведущие нули.
Вы уверены, что int num = get_long("num: ");
не смешивает типы?
можно ли выполнять вычисления со строками и символами в C? (Питон этого не делает)
@ user24446695 Да, это возможно. C гарантирует, что вы можете сделать, например. '3' - '0'
и получите целое значение 3
. Итак, чтобы получить целочисленный эквивалент символа в строке str
, вы используете str[i] - '0'
. Но, пожалуйста, не будьте консервативны при создании строки (используя простой массив символов), используйте размер, который, как вы знаете, вы никогда не получите. Тогда вам не придется беспокоиться о таких вещах, как терминатор строки. Назовите не менее 32 символов.
Да, вы правы, я забыл это изменить, когда пытался это проверить (скопировать и вставить из другого файла.)
Ого, это на самом деле очень приятно. Я обязательно переключусь и буду использовать его. Спасибо за помощь!
printf("%d \n", array[length]);
Вероятно, вы захотите либо изменить length
, либо каким-то образом использовать j
, если только вы не хотите печатать один и тот же индекс несколько раз.
array[length] = (num % 10);
нарушит границы массива. length
в первой итерации — это количество элементов, индексировать можно только от [0]
до [length-1]
.
В последнем цикле должно быть printf("%d \n", array[length]);
printf("%d \n", array[j]);
?
На самом деле я такой тупой, что вы, ребята, все заметили мои глупые ошибки. В свою защиту скажу, что я не выпил чашку кофе. (Большое спасибо!)
Не будьте слишком умными... Если проблема в алгоритме Луна, то данные представляют собой «числа» CC. Предполагается, что они «размером с человека» (т. е. не имеют длину 328 цифр). Более простой код будет использовать массив времени компиляции, скажем, 32 или 64 байта, избегая сложностей выделения кучи. (Вы забыли free()
блок.) Используйте стек размером 8 МБ (или 1 МБ), предоставленный вашей программе, и напишите более простой код «KISS»...
Основная проблема заключается в следующем задании:
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 с двумя индексами.
@user24446695 malloc(length * sizeof(int))
выделит достаточно байтов для length
количества int
элементов. И, как и все массивы в C, индекс начинается с нуля, поэтому у вас есть индексы элементов от 0
до length - 1
.
По сути, вы говорите, что если бы длина была равна 2, было бы выделено достаточно байтов для двух элементов int или буквально числа 2?
@ user24446695 Достаточно для двух элементов. И действительными индексами будут 0
и 1
.
Когда вы выделяете память с помощью
malloc
, память никак не инициализируется. Вся память будет содержать неопределенные (читай: мусор) данные.