Developer forum
cancel
Showing results for 
Search instead for 
Did you mean: 

Attributes selected by name - char and pointers

kzaremba
Newcomer
Hi,

I'm trying to select attributes by name. I based it on Example I and II in AttributeGet docs.
After a while, I had Example 2 working but... It's doing well for all strings which have same beginning. So T, TE, TES, TEST all of them work. I assume its char handling but I'm not sure how to make it work.
Instead of the header.name I tried UniString pointer but referencing causes AC crashed.
Here is my try:
/* Example II -- loop through all attributes of a kind */
API_Attribute  attrib;
	short          nLin, i;
	GSErrCode      err;

	BNZeroMemory(&attrib, sizeof(API_Attribute));
	attrib.header.typeID = API_CompWallID;
	err = ACAPI_Attribute_GetNum(API_CompWallID, &nLin);
	
	for (i = 1; i <= nLin && err == NoError; i++) {
		attrib.header.index = i;
		err = ACAPI_Attribute_Get(&attrib);

		if (err == NoError) {
			char TTT[100] = "TEST";
			int TTT_Idx;
			
			char AttTxt = *attrib.compWall.head.name;

			if (AttTxt == *TTT) {
				DGAlert(DG_INFORMATION, "ERR1", "ATTRIB GUT", "", "Good");
				TTT_Idx = attrib.compWall.head.index;
			}
Example 1 didn't work at all. I tried building header but search ends up with an error.
	//Example I
	API_Attribute attrib;
	BNZeroMemory(&attrib, sizeof(API_Attribute));
	char TTT[256] = "TEST";

	attrib.header.name[256] = *TTT;
	
	err = ACAPI_Attribute_Search(&attrib.header);

	if (err == NoError) {
	char msgStr[512];
	sprintf(msgStr, "[%d] %s", attrib.header.index, attrib.header.name);
	ACAPI_WriteReport(msgStr, true);
	DGAlert(DG_INFORMATION, "ERR1",  msgStr, "", "Good");
	}
	else {
	DGAlert(DG_INFORMATION, "ERR1", "error", "", "Good");
	}
Please help
1 ACCEPTED SOLUTION

Solution
Tibor Lorantfy
Advisor
You handled the character arrays incorrectly.

In "Example II" you made the mistake here:
kzaremba wrote:
/* Example II -- loop through all attributes of a kind */
...
			char AttTxt = *attrib.compWall.head.name;

			if (AttTxt == *TTT) {
...
This way you copied only the first character of the attrib.compWall.head.name string to the AttTxt variable and in the if statement you compared only the first character of TTT to AttTxt.

This would be correct:
/* Example II -- loop through all attributes of a kind */
...
			if (strcmp (attrib.compWall.head.name, TTT) == 0) {
...
You don't need the AttTxt variable and you can compare (char*) strings using strcmp method.

But to search attributes with a specific name the ACAPI_Attribute_Search function is recommended, so your other example code fits better for this purpose.
You made mistake in your "Example I" here:
kzaremba wrote:
	//Example I
...
	char TTT[256] = "TEST";

	attrib.header.name[256] = *TTT;
...
This way only the first character from TTT will be copied.

Use strcpy method to copy the whole string:
	//Example I
...
strcpy (attrib.header.name, "TEST");
...

View solution in original post

6 REPLIES 6

Solution
Tibor Lorantfy
Advisor
You handled the character arrays incorrectly.

In "Example II" you made the mistake here:
kzaremba wrote:
/* Example II -- loop through all attributes of a kind */
...
			char AttTxt = *attrib.compWall.head.name;

			if (AttTxt == *TTT) {
...
This way you copied only the first character of the attrib.compWall.head.name string to the AttTxt variable and in the if statement you compared only the first character of TTT to AttTxt.

This would be correct:
/* Example II -- loop through all attributes of a kind */
...
			if (strcmp (attrib.compWall.head.name, TTT) == 0) {
...
You don't need the AttTxt variable and you can compare (char*) strings using strcmp method.

But to search attributes with a specific name the ACAPI_Attribute_Search function is recommended, so your other example code fits better for this purpose.
You made mistake in your "Example I" here:
kzaremba wrote:
	//Example I
...
	char TTT[256] = "TEST";

	attrib.header.name[256] = *TTT;
...
This way only the first character from TTT will be copied.

Use strcpy method to copy the whole string:
	//Example I
...
strcpy (attrib.header.name, "TEST");
...

View solution in original post

kzaremba
Newcomer
Hi Tibor,

Thanks a lot, I have struggled with chars for a while. Example I works as a charm!

I couldn't get Example II working. strcmp gets violet in VS and got this description "strcmp_DISABLED!!!" and compiler error C2065.

dfintha
Newcomer
Hello,

Yes, strcmp is disabled in add-on sources. You can use the CHCompareCStrings function instead, which has a similar set of arguments, and produces identical results.

Best regards,
Dénes

kzaremba
Newcomer
Hi, thanks a lot for pointing it out.
Right now I struggle a lot with char/std::string/GS::String conversions. What is the best practice in your opinion to handle chars and string? Using standard lib or GSRoot? Does it make any difference?

dfintha
Newcomer
Hello,

Using GS::UniString is the preferred method, as it is used in the API function calls and structures, and it uses UTF-8 encoding.
Also, you can use it in a similar fashion as you would use the std::string class, and you can use the GS::UniString::Printf static function instead of sprintf to construct a GS::UniString instance.

If you need a zero-terminated C string, you can convert a GS::UniString to a const char * by using the ToCStr method.


GS::UniString myStr = "Hello, world!";
// ...
FunctionTakingCStr (myStr.ToCStr ().Get ());

Best regards,
Dénes

kzaremba
Newcomer
To be honest, I don't need to use zero-terminated.. but AC seems to need them sometimes. Now I know how to handle them thanks a lot

Still looking?

Browse more topics

Back to forum

See latest solutions

Accepted solutions

Start a new discussion!