Login Page - Create Account

Support Board


Date/Time: Mon, 14 Apr 2025 02:04:15 +0000



[Programming Help] - Possible SCString::ParseLineItemsAsFloats() Bug?

View Count: 85

[2025-04-08 03:57:55]
drinkcodejava - Posts: 23
I believe there might be a bug in SCString::ParseLineItemsAsFloats()

Here are the prototype and description from the reference page:
void ParseLineItemsAsFloats(std::vector<float> &FloatValues);
The ParseLineItemsAsFloats() function parses the SCString object looking for \n (newline) characters and placing each floating point value prefacing the \n into the FloatValues vector.

Bug description: the last value in the passed vector parameter is not parsed correctly, and the vector parameter's .size() function returns a value that is one less than the actual size. There is an additional behavior where the vector retains values from a previous call, requiring the vector to be cleared so that values from previous calls do not accumulate (SCString::Tokenize() does not exhibit this behavior).

I am using ParseLineItemsAsFloats() to parse data from a file, and this bug requires me to add an extra column of dummy data to the right in order to be able to access the last column of legitimate data while iterating the vector.

I've written a custom study to illustrate (.cpp attached):
#include "sierrachart.h"

SCDLLName("ParseLineItemsAsFloats Bug Demo")

SCSFExport scsf_ParseLineItemsAsFloatsBugDemo(SCStudyInterfaceRef sc)
{  
  SCString msg; // for message log output
  SCString datastring; // for demonstration data
  std::vector<SCString> Lines; // holds demo data parsed into lines
  std::vector<float> FloatVals; // holds demo data lines parsed into floats
  std::vector<char*> Tokens; // holds demo data lines parsed into tokens
  
  if (sc.Index == 0) {
    
    // Generate demonstration data
    datastring.Format("0.1,0.2,0.3,0.4,0.5\n1.1,1.2,1.3,1.4,1.5,1.6\n2.1,2.2,2.3\n");
    
    // Parse the demonstration data into a vector of SCStrings
    datastring.ParseLines(Lines);
    
    // Loop through the parsed lines and parse each line into floats
    for (int i = 0; i < Lines.size(); i++) {
      
      // Output current line of demonstration data to message log
      msg.Format("Lines[%d] as string: %s", i, Lines[i].GetChars());
      sc.AddMessageToLog(msg,0);
      
      // Parse current line into a vector of floats
      Lines[i].ParseLineItemsAsFloats(FloatVals);
      
      // Generate message log output preface for FloatVals
      msg.Format("FloatVals vector (FloatVals.size(): %d): ", FloatVals.size());
      
      // Add each float to the message log output
      for (int i = 0; i <= FloatVals.size(); i++) { // Note <= operator for loop end condition
        msg.AppendFormat("%.1f", FloatVals[i]);
        if (i < FloatVals.size()) msg.AppendFormat(", ");
      }
      
      FloatVals.clear(); // Note how ParseLineItemsAsFloats requires this line while Tokenize does not
      
      // Output current line of floats to message log
      sc.AddMessageToLog(msg,0);
      
      
      // Parse current line into a vector of tokens
      Lines[i].Tokenize(",", Tokens);
      
      // Generate message log output preface for Tokens
      msg.Format("Tokens vector (Tokens.size(): %d): ", Tokens.size());
      
      for (int i = 0; i < Tokens.size(); i++) {
        msg.AppendFormat("%s", SCString(Tokens[i]).GetChars());
        if (i < Tokens.size()-1) msg.AppendFormat(", ");
      }
      
      // Output current line of tokens to message log
      sc.AddMessageToLog(msg,0);
    }
    
  }
}

The sample data is
0.1,0.2,0.3,0.4,0.5
1.1,1.2,1.3,1.4,1.5,1.6
2.1,2.2,2.3

and here is the output for the sample data comparing ParseLineItemsAsFloats() is called vs. Tokenize(), which behaves as expected:
2025-04-07 23:23:50.165 | Chart: MESM25[M] 1 Min #5 | Study: Custom DLL Study | Lines[0] as string: 0.1,0.2,0.3,0.4,0.5
2025-04-07 23:23:50.165 | Chart: MESM25[M] 1 Min #5 | Study: Custom DLL Study | FloatVals vector (FloatVals.size(): 4): 0.1, 0.2, 0.3, 0.4, 0.0
2025-04-07 23:23:50.165 | Chart: MESM25[M] 1 Min #5 | Study: Custom DLL Study | Tokens vector (Tokens.size(): 5): 0.1, 0.2, 0.3, 0.4, 0.5
2025-04-07 23:23:50.165 | Chart: MESM25[M] 1 Min #5 | Study: Custom DLL Study | Lines[1] as string: 1.1,1.2,1.3,1.4,1.5,1.6
2025-04-07 23:23:50.165 | Chart: MESM25[M] 1 Min #5 | Study: Custom DLL Study | FloatVals vector (FloatVals.size(): 5): 1.1, 1.2, 1.3, 1.4, 1.5, 0.0
2025-04-07 23:23:50.165 | Chart: MESM25[M] 1 Min #5 | Study: Custom DLL Study | Tokens vector (Tokens.size(): 6): 1.1, 1.2, 1.3, 1.4, 1.5, 1.6
2025-04-07 23:23:50.165 | Chart: MESM25[M] 1 Min #5 | Study: Custom DLL Study | Lines[2] as string: 2.1,2.2,2.3
2025-04-07 23:23:50.165 | Chart: MESM25[M] 1 Min #5 | Study: Custom DLL Study | FloatVals vector (FloatVals.size(): 2): 2.1, 2.2, 1.3
2025-04-07 23:23:50.165 | Chart: MESM25[M] 1 Min #5 | Study: Custom DLL Study | Tokens vector (Tokens.size(): 3): 2.1, 2.2, 2.3

If you look carefully, you'll also see that the last line's last value is parsed as 1.3 instead of as 0 in the previous lines. I can't explain where this value is coming from.

My apologies in advance if this is an error on my part; I admit my coding experience is limited with C++. Thanks for taking the time to look into this!
attachmentParseLineItemsAsFloatsBug.cpp - Attached On 2025-04-08 03:26:43 UTC - Size: 2.13 KB - 15 views
[2025-04-11 06:31:50]
Sierra_Chart Engineering - Posts: 19166
We will look this over. It could be that the last value in the input string, is not getting parsed if there is not a comma after it.

There is an additional behavior where the vector retains values from a previous call, requiring the vector to be cleared so that values from previous calls do not accumulate (SCString::Tokenize() does not exhibit this behavior).
This is normal. We could clear the vector but it definitely is not a mistake that it does not get cleared. The responsibility for clearing it is from the caller.
Sierra Chart Support - Engineering Level

Your definitive source for support. Other responses are from users. Try to keep your questions brief and to the point. Be aware of support policy:
https://www.sierrachart.com/index.php?l=PostingInformation.php#GeneralInformation

For the most reliable, advanced, and zero cost futures order routing, use the Teton service:
Sierra Chart Teton Futures Order Routing
[2025-04-11 22:42:06]
drinkcodejava - Posts: 23
Thanks so much! I'm continually blown away by your ability to support such a broad code base and network infrastructure. Keep up the great work!

To post a message in this thread, you need to log in with your Sierra Chart account:

Login

Login Page - Create Account