Принимая пользовательский ввод с указателями - PullRequest
0 голосов
/ 20 февраля 2010

Я пытаюсь стать лучше при использовании указателей, а не при использовании обозначений массивов. Так что у меня есть функция для чтения ввода пользователя и возврата указателя на этот массив. Я могу сделать это так, и, кажется, работает нормально:

float *GetValues(float *p, size_t n) 
{   

    float input;
    int i = 0;

    if ((newPtr = (float *)malloc(n * sizeof(float))) == NULL) {
        cout << "Not enough memory\n";
        exit(EXIT_FAILURE);
    }
    cout << "Enter " << n << " float values separated by whitespace: \n";

    while (scanf("%f", &input) == 1) {
        p[i] = input;
        i++;
        cout << *p;
    }
    return p;
}

Но тогда, если я сделаю это:

float *GetValues(float *p, size_t n) 
{   
    float *newPtr;
    float input;

    if ((newPtr = (float *)malloc(n * sizeof(float))) == NULL) {
        cout << "Not enough memory\n";
        exit(EXIT_FAILURE);
    }
    cout << "Enter " << n << " float values separated by whitespace: \n";

    while (scanf("%f", &input) == 1) {
            *newPtr++ = input;
    }
    return newPtr;
}

Я получаю только 0, введенные в р. Почему это так?

Кроме того, я должен выделить здесь память для массива размером n? Сначала я попробовал это с помощью метода выше, используя указатели и не выделяя память, а просто установив p = для ввода, и я получал значения мусора. Спасибо!

Отредактировано: извините, я выделил новый ptr и возвращал неправильный, как вы сказали. Я просто пытался ввести числа в свой указатель и отобразить их обратно на экране для себя и не обращал внимания на тип возвращаемого значения, и я получал вывод 0, когда я cout << * newPtr. </p>

Ответы [ 4 ]

2 голосов
/ 20 февраля 2010

Учитывая, что это C ++, вы рассмотрели:

void GetValues(std::vector<float> &values) 
{   
    float input;
    while (scanf("%f", &input) == 1) {
        values.push_back(input);
    }
}

И есть нечто, называемое iostream классами, которое вы можете использовать вместо scanf. Вы должны это проверить!

0 голосов
/ 20 февраля 2010

Несколько советов:


Первый GetValues ​​выделяет newPtr (который не объявлен внутри функции, глобальной переменной?), Но затем ничего с этим не делает. Существует два возможных способа, с помощью которых ваша функция может работать с памятью:

  1. Функция получает указатель на допустимую память для массива достаточно большого размера. В этом случае подпись функции должна быть

    float * GetValues ​​(float * array, size_t arraySize)

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

  2. Функция должна выделять необходимую память сама и позволить вызывающей стороне освободить память через некоторое время. В этом случае у вас ДОЛЖЕН есть какой-то намек на имя функции, которая выделяет память. В противном случае вы попадете в беду с точки зрения поддержки этого кода, потому что будет очень легко совершать ошибки при освобождении памяти. Вам не нужно будет передавать указатель массива на функцию, но если вы делаете это, он должен быть двойным указателем, чтобы он имел какой-либо смысл (C и C ++ передают аргументы по значению, поэтому невозможно изменить указатель, который передан в качестве аргумента)

    float * GetValuesAndAllocateMemmory (size_t n)

    float * GetValuesAndAllocateMemmory (float ** array_pp, size_t n)


Цикл во втором GetValues ​​должен быть

float *start_p = p;
...
while (scanf("%f", &input) == 1) {
        *p++ = input;
        cout << *start_p;
}
return start_p;

, чтобы быть идентичными первым GetValues.


Здесь верхний предел числа значений с плавающей запятой равен n, но ваш код не проверяет это

cout << "Enter " << n << " float values separated by whitespace: \n";
while (scanf("%f", &input) == 1) {

и вылетает, если введено более n значений с плавающей запятой. Никогда не доверяйте вводимым пользователем данным , даже если они исходят от вас самих. Всегда проверяйте. Ищите термин «проверка ввода» для получения дополнительной информации об этом.

cout << "Enter " << n << " float values separated by whitespace: \n";
entered_values = 0;
while (entered_values < n && scanf("%f", &input) == 1) {
       entered_values++;
0 голосов
/ 20 февраля 2010

Вы даже не сохраняете никаких значений в p. И вы возвращаете указатель, который вы передаете в качестве аргумента, что не является необходимым. Лучшая версия будет:

long GetValues(float *p, size_t max) 
{   
    float input;
    long i;

    cout << "Enter at the most " << max << " float values separated by whitespace: \n";

    for(i = 0; i < max && scanf("%f", &input) == 1; ++i)
    {
        p[i] = input;
    }

    // Return the number of parsed numbers
    return i;
}
0 голосов
/ 20 февраля 2010

Um, p = newPtr;?

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...