void * как параметр функции

Оглядываясь на ответ Итай, похоже, что он читает файл тысячу раз после выборки одной строки кода, тогда как истинная выборка коллектора должна проходить только по «ленте» один раз. Я разработал код для перебора кода один раз с реальной выборкой коллектора на основе этого и различных описаний в Интернете.

import java.io.FileNotFoundException;
import java.io.IOException;
import java.util.List;

public class reservoirSampling {

    public static void main(String[] args) throws FileNotFoundException, IOException{
        Sampler mySampler = new Sampler();
        List myList = mySampler.sampler(10);
        for(int index = 0;index sampler (int reservoirSize) throws FileNotFoundException, IOException
    {
        String currentLine=null;
        //reservoirList is where our selected lines stored
        List  reservoirList= new ArrayList(reservoirSize); 
        // we will use this counter to count the current line number while iterating
        int count=0; 

        Random ra = new Random();
        int randomNumber = 0;
        Scanner sc = new Scanner(new File("Open_source.html")).useDelimiter("\n");
        while (sc.hasNext())
        {
            currentLine = sc.next();
            count ++;
            if (count<=reservoirSize)
            {
                reservoirList.add(currentLine);
            }
            else if ((randomNumber = (int) ra.nextInt(count))

Основная предпосылка заключается в том, что вы заполните резервуар, а затем вернитесь к нему и заполните случайные линии с вероятностью 1 / ReservoirSize. Надеюсь, это обеспечит более эффективный код. Пожалуйста, дайте мне знать, если это не сработает для вас, поскольку я буквально сбил его через полчаса.

1
задан Kris_Holder 18 January 2019 в 13:03
поделиться

6 ответов

Тип void не имеет размера. Поэтому вы не можете использовать void * для очистки массива. Вы не можете разыменовать этот тип по той же причине.

Вы должны привести к указателю с определенным типом:

void clean_buffer(void *ptr, size_t n)
{
    unsigned char *my_ptr = ptr;
    for (int i = 0; i < n; i++)
        my_ptr[i]=0;
}

Вы должны позаботиться о том, чтобы размер, передаваемый вашей функции, не мог быть числом или массивами, потому что компилятор не может выполнять арифметику указателей с [114 ] указатели. А для размеров вы должны использовать size_t

Вместо этого вы должны передать размер массива в байтах:

int main(void)
{
   float  *pf;
   int    *pi;

   pf = malloc(10*sizeof(float));
   pi = malloc(10*sizeof(int));

   clean_buffer( pf, 10*sizeof(float));
   clean_buffer( pi, 10*sizeof(int));

   return 0;
}

Или вам нужно передать любую другую информацию, которая может быть использована для определить тип и / или размер данных.

Также: приведение к возвращаемому значению malloc не требуется в C. Приведение параметров clean_buffer к типу, который уже имеет переменную, бесполезно. Тип указателя в любом случае преобразуется в void *, поскольку это то, что ожидает функция.

Примечание: в других ответах и ​​комментариях упоминается, что вы можете просто передать указатель на memset или использовать calloc и т. Д. Это может быть верно для этого очень специфического случая, но если вы хотите сделать что-то еще, кроме простого обнуления памяти применимы те же аспекты, что и к указателям void *, как я показал здесь. И в этих случаях memset или calloc не помогают.

0
ответ дан Gerhardh 18 January 2019 в 13:03
поделиться

void - это не значение, которое нельзя использовать *((void*) x) = v;, и использование приведения для использования указателя на другой тип опасно , поскольку размер может не совпадать

Но в вашем случае вы установили 0, поэтому вы можете использовать memset или заменить malloc my calloc и бесполезно иметь clean_buffer:

int main(void)
{
   float  *pf;
   int    *pi;

   pf = calloc(10, sizeof(float));
   pi = calloc(10, sizeof(int));

   return 0;
}
0
ответ дан bruno 18 January 2019 в 13:03
поделиться

void clean_buffer (void * ptr, int n)

Эта функция требует void * в качестве параметра.

clean_buffer ((float *) pf, 10);

Здесь вы приводите к указателю с плавающей точкой. Так что это другой тип по требованию

Также void не имеет размера, поэтому вы не можете использовать [] на ptr

.
0
ответ дан Immo Hellwig 18 January 2019 в 13:03
поделиться

Вы приводите ptr к соответствующему типу, чтобы он мог разыменовать, чтобы очистить то, на что он указывает; что-то, что вы знаете, указывает на тип, который вы хотите очистить i элементов.

0
ответ дан Scott Hunter 18 January 2019 в 13:03
поделиться

У меня проблема с использованием void *. Как мне сделать, чтобы использовать эту функцию clean_buffer для массивов int и float (?)

Другие упоминали полезные вещи, такие как необходимость sizeof найти размер, приведение не требуется и альтернативы используйте calloc() для нулевого инициализированного выделения памяти.


Добавить:

sizeof * object_pointer

Используйте sizeof *object_pointer, чтобы найти размер. Он менее подвержен ошибкам, его легче просматривать и поддерживать, чем кодировать в типе.

// clean_buffer( (float *)pf, 10);
// clean_buffer( (int *)pi, 10);

// cast not needed
clean_buffer(pf, sizeof *pf * 10);  // No need to mention type!
clean_buffer(pi, sizeof *pi * 10);

volatile

Очистка памяти после ее окончательного использования склонна к оптимизации, а затем веская причина для не использовать memset(), когда память безопасность вызывает беспокойство. Вместо этого используйте volatile, чтобы не допустить оптимизации самого clean_buffer().

void clean_buffer(void *ptr, size_t n) {
  volatile unsigned char *vuc = ptr;
  for(size_t i = 0; i < n; i++)
    vuc[i]=0;
  }
}
0
ответ дан chux 18 January 2019 в 13:03
поделиться

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

Вы можете использовать memset и передать размер всего буфера, чтобы очистить его, не беспокоясь о его типе.

void clean_buffer( void *ptr, size_t n)
{
    memset(ptr, 0, n)
}
int main(void)
{
   float  *pf;
   int    *pi;

   pf = (float *) malloc(10*sizeof(float));
   pi = (int *)malloc(10*sizeof(int));


   clean_buffer(pf, 10*sizeof(float));
   clean_buffer(pi, 10*sizeof(int));

    return 0;
}

Кроме того, как предлагали другие, вы можете использовать calloc, если вам это подходит.

0
ответ дан Jay 18 January 2019 в 13:03
поделиться
Другие вопросы по тегам:

Похожие вопросы: