Возврат массива из функции (Си)
Есть необходимость получить из функции массив с индексами определенных символов, например, 'a' со смещением (индексы начинаются с 1).
Смастерить массив получилось, но вот вернуть его не очень.
Где-то в main объявлены строка и указатель на массив
В переменной string массив символов.
char* string = "abbla";
size_t* nums = malloc(...);
int* indices (const char* string, size_t* nums) {
for (int i = 0; i < strlen(string); ++i) {
switch (string[i]) {
case 'a':
*(nums) = i + 1;
printf("%c - %zu\n", string[i], *nums); // тут все ок
break;
}
}
return nums;
}
Ожидаемый результат: {1, 5}
Полученный результат: {5, 0, -501312472, 32765, 2}
update:
Благодаря помощи уважаемых @LShadow77 и @avp код скорректировал:
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
int* indices (const char* string, size_t* nums) {
int n = 0;
for (int i = 0; i < strlen(string); ++i) {
switch (string[i]) {
case 'a':
nums[n] = i + 1;
printf("%c - %zu\n", string[i], nums[n); // тут все ок
n++;
break;
}
}
return nums;
}
int main() {
const char* string = "abbla";
size_t* nums = malloc(strlen(string) * sizeof(size_t));
indices(string, nums);
for (int i = 0; i < sizeof(nums) / sizeof(size_t); ++i) {
printf("%d %zu\t", i, nums[i]);
}
}
printf в main возвращает "0 1".
Ответы (2 шт):
Во-первых, нет смысла возвращать указатель на массив, который и так известен, ведь он передаётся в качестве параметра. Во-вторых, следовало бы возвратить вместо указателя размер получившегося массива индексов. В-третьих, помимо указателя на массив, а вернее на буфер, в котором формируется этот массив, следовало бы передать функции ещё и размер этого буфера, чтобы не допустить его переполнение. В четвёртых, после записи очередного индекса через указатель следует увеличить последний на единицу. Подытожу:
size_t indices (const char* string, size_t* nums, size_t nums_size) {
size_t count = 0;
for (int i = 0; (i < strlen(string)) && (count < nums_size); ++i) {
switch (string[i]) {
case 'a':
*nums = i + 1;
printf("%c - %zu\n", string[i], *nums); // тут все ок
++nums;
++count;
}
}
return count;
}
Вариант с динамическим массивом (возвращается указатель на массив):
//возвращает указатель на динамический массив индексов
size_t* indices (
const char* string, //указатель на искомую строку
size_t* nums_size //указатель на переменную, в которую будет помещён размер массива
)
{
int len = strlen(string);
//первый проход по строке - определяем размер массива
size_t nums_count = 0;
for (int i = 0; i < len; ++i)
if (string[i]=='a') ++nums_count;
//создаём массив
size_t* nums = (size_t*)malloc(nums_count*sizeof(size_t));
//второй проход по строке - заполняем массив индексами
for (int i = 0, j = 0; i < len; ++i)
if (string[i]=='a')
{
nums[j++] = i + 1;
printf("%c - %zu\n", string[i], i+1);
}
//возвращаем результат
*nums_size = nums_count;
return nums;
}
P.S. Не забываем потом удалить массив с помощью free()!
Благодаря помощи @avp получилось следующее решение:
Необходимо было добавить счетчик вхождений искомого символа (n) в строку, его инкремент в теле switch и корректно выделить память под возвращаемый массив.
int* indices (const char* string, size_t* nums) {
int n = 0;
*nums = 0;
int* indices = malloc(*nums * sizeof(*indices));
for (int i = 0; i < strlen(string); ++i) {
switch (string[i]) {
case 'a':
indices[n++] = i + 1;
break;
}
}
return indices;
}