почему этот параметр имени файла указатель на символ вместо строки? - PullRequest
0 голосов
/ 17 декабря 2018

В моем универе есть функция, которая должна считываться в файле.В параметре есть параметр fileName.Чего я не понимаю, так это почему они используют символьный указатель вместо простой строки?

Кроме того, как мне тогда вызвать эту функцию со строковым именем файла?

Язапуск C ++ 14 в выпуске Visual Studio 2017 Community Edition.

double* read_text(char *fileName, int sizeR, int sizeC)
{
    double* data = new double[sizeR*sizeC];
    int i = 0;
    ifstream myfile(fileName);
    if (myfile.is_open())
    {

        while (myfile.good())
        {
            if (i > sizeR*sizeC - 1) break;
            myfile >> *(data + i);
            i++;
        }
        myfile.close();
    }
    else cout << "Unable to open file";
    //cout << i;
    return data;
}

Редактировать: Я понимаю, ребята, это глупо.Я отправлю отдельный вопрос тогда.Спасибо за быстрый ответ!

1 Ответ

0 голосов
/ 17 декабря 2018

почему этот параметр имени файла является указателем на символ вместо строки?

Поскольку разработчик API решил это сделать.Большинство людей в Stack Overflow не являются авторами этого API, поэтому мы не можем точно ответить на этот вопрос.

Однако есть еще один похожий вопрос, на который мы можем ответить: каковы причины использования указателя символов в качестве строкового аргумента?Позвольте мне ответить на этот вопрос вместо этого:

  • Не использование std::string в качестве аргумента позволяет пользователю API не создавать объект std::string.Это может быть полезно, когда:
    • API необходимо использовать в «автономных» реализациях, которые не предоставляют стандартную библиотеку и поэтому не имеют std::string.Это, вероятно, не относится к вашему конкретному примеру, так как реализация функции использует стандартную библиотеку, но я включаю этот аргумент для полноты.
    • API необходимо использовать в системах, которые не обеспечивают динамическое выделение памяти,который std::string требует.
    • Динамическое выделение памяти, которое может потребоваться для создания строки, может быть слишком медленным в контексте использования API (это не относится к API, который будет считывать издиск, но я включаю аргумент здесь для полноты).
  • (const) char* позволяет использовать API из C. Это может быть актуально, потому что:
    • API, возможно, изначально был написан для C и был унаследован к базе кода, которая теперь использует C ++, но API не был изменен для обеспечения обратной совместимости.
    • Предоставление Cсовместимый API позволяет использовать API из других языков, которые могут взаимодействовать с C. Многие языки поддерживают интерфейс CНапример, очень немногие языки поддерживают интерфейсы C ++.

Кроме того, как мне тогда вызвать эту функцию со строковым именем файла?

Вы можете получить указатель на завершенную нулем строку, используя функцию-член c_str.К сожалению, API плохо спроектирован, и аргумент не является константным, а указатель, возвращаемый c_str, является константным.Вы можете const_cast константность аргумента прочь, чтобы вызвать эту функцию.Это «ОК», потому что функция фактически не изменяет указанную строку.

Если вам может потребоваться стандарт C ++ 17 и исходная строка не является константной, тогда функция-член data будетпроще, так как не требует const_cast.До C ++ 17 не было неконстантной перегрузки, поэтому требовалось бы такое же преобразование констант, а до C ++ 11 указанная строка не гарантировалась нулевым завершением.

Чтобы было ясно: использование неконстантного строкового аргумента для этой функции - плохой дизайн - является ли этот аргумент символьным указателем на завершенную нулем строку или ссылкой на std::string.


PST Существуют и другие, более серьезные проблемы:

  • Вызывающий функцию не может знать, сколько чисел было прочитано из файла.Невозможно избежать UB, если файл имеет значения меньше sizeR*sizeC.
  • Возвращение пустого указателя, который владеет динамическим ресурсом памяти, является очень плохим дизайном.
  • Цикл, который читаетиз файла проверяет, было ли чтение успешным после значение уже добавлено в массив, и значение никогда не перезаписывается, поэтому последний записанный в массив элемент всегда имеет неопределенное значение.
...