#c #parsing #scanf #unreal-engine4 #protein-database
Вопрос:
Я новичок в Unreal Engine, родом из Unity, а также новичок в C . Я пытаюсь импортировать файлы PDB непосредственно в движок с помощью fscanf.
Раздел файла PDB, который я пытаюсь захватить, показан ниже:
ATOM 15 H1 ATHR A 1 3.035 -14.005 16.173 0.75 6.58 H
ATOM 16 H1 BTHR A 1 2.914 -14.713 18.488 0.25 11.77 H
ATOM 17 H2 ATHR A 1 2.830 -14.148 17.523 0.75 6.58 H
ATOM 18 H2 BTHR A 1 4.980 -14.983 15.512 0.25 11.77 H
ATOM 19 H3 ATHR A 1 3.680 -15.162 17.238 0.75 6.58 H
ATOM 20 H3 BTHR A 1 9.013 -8.192 18.474 0.25 11.77 H
ATOM 21 HA ATHR A 1 3.181 -11.806 16.823 0.75 4.19 H
ATOM 22 HA BTHR A 1 3.605 -12.290 17.060 0.25 5.98 H
ATOM 23 HB ATHR A 1 5.699 -13.731 17.989 0.75 4.53 H
ATOM 24 HB BTHR A 1 4.523 -12.115 19.103 0.25 9.37 H
ATOM 25 HG1ATHR A 1 3.314 -12.887 19.057 0.75 8.30 H
ATOM 26 HG1BTHR A 1 4.049 -10.109 18.478 0.25 15.91 H
ATOM 27 HG21ATHR A 1 6.468 -11.628 19.047 0.75 7.89 H
Я нашел несколько других примеров в библиотеках, использующих спецификаторы, такие как:
const char atom_line_iformat_[] = "ATOM ]%*1cL
Однако при попытке использовать вышеуказанные спецификаторы unreal engine будет выходить из строя каждый раз, если присутствует спецификатор «ATOM».
Мое текущее решение позволяет извлекать данные 3D-координат, но также анализирует другие строки из файла pdb, которые являются нежелательными. Также кажется, что в выходных данных есть повторяющиеся строки, как показано на рисунке ниже.
[
Вы также можете увидеть здесь более неправильные выходные данные, первое изображение-это вывод журнала, второе-данные из файлов pdb, которые неправильно считываются, поскольку это не запись ATOM.
Я считаю, что мне нужен спецификатор, который проверяет, что первая строка — «АТОМ», но я не смог найти рабочее решение.
Любой совет был бы очень признателен!
Код, найденный ниже:
FString directory = FPaths::ProjectContentDir();
IPlatformFileamp; file = FPlatformFileManager::Get().GetPlatformFile();
if (file.CreateDirectory(*directory)) {
FString myFile = directory "/" fileName ".pdb";
const char* fileLocation = TCHAR_TO_ANSI(*myFile);
FILE* ptr = fopen(fileLocation, "r");
if (ptr == NULL) {
GEngine->AddOnScreenDebugMessage(-1, 5.f, FColor::Red, TEXT("FILE NOT FOUND."));
return atomPositions;
}
else {
double xValue = 0;
double yValue = 0;
double zValue = 0;
UE_LOG(LogTemp, Warning, TEXT("RUNNING"));
while (fscanf(ptr, "%*s %*d %*s %*s %*s %*d %lf %lf %lf %*lf %*lf %*sn", amp;xValue,
amp;yValue, amp;zValue) != EOF)
{
UE_LOG(LogTemp, Warning, TEXT("X: %lf, Y: %lf, Z: %lf"), xValue, yValue, zValue);
}
}
}
Комментарии:
1. Зачем сравнивать agianst
EOF
, а не 3 вwhile (fscanf(ptr, "%*s %*d %*s %*s %*s %*d %lf %lf %lf %*lf %*lf %*sn", amp;xValue, amp;yValue, amp;zValue) != EOF)
2. Я предположил, что это позволяет fscanf выполнять цикл до EOF, я добавил его в оператор while, увидев, что он используется в другом операторе онлайн.
3. Mortamass 1) Поскольку цикл имеет смысл продолжать только в том случае, если прочитаны 3 успешных FP, а не 2, 1, 0 или
EOF
, лучше использоватьwhile (fscanf(ptr, ...) == 3)
2) Кодирование путем имитации наследует хорошие и плохие привычки.
Ответ №1:
Код помечен C и scanf— странное сочетание.
Я продолжу с fgets()
sscanf()
объяснением, но использование getline()
и другой синтаксический анализ кода больше похожи на C .
*scanf()
и друзья ужасно восстанавливаются после ввода, который не соответствует ожидаемому формату.
Поскольку ввод-это ориентация строки, лучше всего прочитать строку, а затем проанализировать ее.
char buffer[200];
while (fgets(buffer, sizeof buffer, ptr)) {
if (sscanf(buffer, "%*s %*d %*s %*s %*s %*d %lf %lf %lf %*lf %*lf %*sn",
amp;xValue, amp;yValue, amp;zValue) != 3) {
fprintf(stderr, "Unable to parse <%s>n", buffer);
exit(-1):
}
UE_LOG(LogTemp, Warning, TEXT("X: %lf, Y: %lf, Z: %lf"), xValue, yValue, zValue);
}
Я уверен, что при быстром выходе кода из не проанализированной строки OP локализует проблему сканирования.
// Hint - format and input are mismatched
%*d %*s %*s %*s %*d
27 HG21ATHR A 1
Комментарии:
1. Все пробелы (и n) в строке формата являются ненужными и должны быть удалены. Конечные
%*
совпадения также бессмысленны и должны быть удалены.2. На самом деле, учитывая формат фиксированной ширины, было бы лучше
if (sscanf(buffer OFFSET, "%f%f%f",
… гдеOFFSET
(фиксированное) смещение в строке, где начинаются интересующие числа.3. @ChrisDodd Пробелы в формате действительно не нужны. Это хорошее улучшение, однако, не является проблемой OP в настоящее время. Пробелы удалены или нет-это проблема стиля, которую лучше всего решать в соответствии с руководством по стилю группы. Я тоже нахожу их излишними. Конечные
"*…"
спецификаторы полезны, если есть (и должен быть) конечный спецификатор, например" %n"
, для оценки соответствия формату.if (sscanf(buffer OFFSET ...
это интересная идея, но это проблема, если длина строки меньшеOFFSET
.