Mortamass
Mortamass

Reputation: 21

UE4, C++, fscanf, match strings with specifiers

I am new to Unreal Engine, coming from Unity and as well new to C++. I am trying to import PDB files directly into the engine by using fscanf.

The section of the PDB file which I am attempting to capture is shown below:

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  

I have found some other examples in libraries that use specifiers such as:

const char atom_line_iformat_[] = "ATOM %5d%*1c%4c%1c%3c%*c%1c%4d%1c%*1c%*1c%*1c%8f%8f%8f%6f%6f%*1c%*1c%*1c%*1c%*1c%*1c%4c%2c%2c";

However, when attempting to use the above specifiers, unreal engine will crash every time if the "ATOM" specifier is present.

My current solution manages to extract the 3D co-ordinate data but as well parses in other lines from the pdb file that are unwanted. There also seems to be duplicate lines in the output as shown in the below image.

[duplicate output logs1

You can also see here are more incorrect outputs, first image is the log output, second is the data from the pdb files that is being incorrectly read as it is not an ATOM record.

enter image description here

enter image description here

I believe I need a specifier that checks that the first string is "ATOM", but I have not be able to find a working solution.

Any advice would be greatly appreciated!

Code found below:

FString directory = FPaths::ProjectContentDir();
IPlatformFile& 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 %*s\n", &xValue, 
        &yValue, &zValue) != EOF) 
        {
            UE_LOG(LogTemp, Warning, TEXT("X: %lf, Y: %lf, Z: %lf"), xValue, yValue, zValue);
        }
    }
}

Upvotes: 1

Views: 735

Answers (1)

chux
chux

Reputation: 153328

Code is tagged C++ and scanf - a strange combination.

I'll go forward with a fgets(), sscanf() explanation, yet using getline() and other parsing code is more C++ like.


*scanf() and friends are terrible at recovering from input that does not match the expected format.

As input is line orientation, best to read a line and then parse it.

char buffer[200];
while (fgets(buffer, sizeof buffer, ptr)) {
  if (sscanf(buffer, "%*s %*d %*s %*s %*s %*d %lf %lf %lf %*lf %*lf %*s\n", 
      &xValue, &yValue, &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);
}

I am confident with a quick code exit of a failed to parsed line, OP will localize the scanning problem.

// Hint - format and input are mismatched
%*d %*s %*s %*s %*d
27 HG21ATHR A   1

Upvotes: 0

Related Questions