Jump to content

TARGET - Advanced programming


ivanwfr

Recommended Posts

What I'm having difficulty now is adjusting the backlight intensity on the Fly, this is what I'm doing so far:......

 

Remember, a MapKey() statement runs only once and sets its values when it runs. So in your example, you had the following (I simplified it down to a single MapKey, not MapKeyIOUMD):

 

MapKey(&Throttle, CHF, CHAIN(EXEC("count = count + 50;"), D(5), LED(&Throttle, LED_INTENSITY, count)));

 

The problem is, the LED() command sees count only when it runs the MapKey() command, so it permanently sets the intensity to the value of count when you run MapKey(). It is as if count is a constant. The only way to pass a variable (not just its value) into a MapKey() is to use a type alias (like &Throttle, or &count), but LED() expects the intensity value to be an int, not an alias. So you can't use &count.

 

So you have to use some form of EXEC() so that it will execute the code every time and hence reference the current value of count, not a constant value stored previously. The obvious way to do that is just use ActKey() in an EXEC().

 

Here is a version of your code but fixed by using EXEC("ActKey();"). Also, I added some extra code around count to make sure it is never < 0 or > 255. So it enforces using 0, 50, 100, 150, 200, and 250, which gives you the 6 possible LED intensity values for the Warthog. Finally, I added a printf() in EventHandle() just for feedback.

 

include "target.tmh"

int count=150;
//program startup
int main()
{
   if(Init(&EventHandle)) return 1; // declare the event handler, return on error

   ActKey(PULSE+KEYON+LED(&Throttle, LED_INTENSITY, count)); //set Backlight Intensity

   MapKey(&Throttle, CHF, 
       CHAIN(EXEC("count = count + 50; if(count>250) count=250;"), D(5), EXEC("ActKey(PULSE+KEYON+LED(&Throttle, LED_INTENSITY, count));") ) 
   );

   MapKey(&Throttle, CHB, 
       CHAIN(EXEC("count = count - 50; if(count<0) count=0;"), D(5), EXEC("ActKey(PULSE+KEYON+LED(&Throttle, LED_INTENSITY, count));") )
   );

   printf("----------------------------------\xa");
} // end main()

//event handler
int EventHandle(int type, alias o, int x)
{
   DefaultMapping(&o, x);

   printf("count=%d\xa", count);

}

 

P.S. This is the answer most people probably would have tried eventually, but without knowing why it is needed. It is important to understand that MapKey() statements in main() execute only once and that MapKey() stores its configurations in arrays (keyalloc[] and devicedata[] as defined in target.tmh). Those configs are acted upon, or executed later by DefaultMapping() which is called by EventHandle() every time a button is pressed or an axis moves on a controller.


Edited by Drakoz
Link to comment
Share on other sites

...after helping SGT coyle in another thread, of having spoken wave files with the aircraft's designation being played when switching profiles. I used an online site to generate the wav files from text to speech.

 

Where is that thread? I haven't revisited the issue, but sounds (ha) like you have a solution.

Link to comment
Share on other sites

  • 3 weeks later...
Hi all,

 

I have a TARGET script which used to combine both my TM Throttle and Joystick into one device and used to hide the individual controllers.

 

Now, the script creates the Thrustmaster combined device but does not hide the individual controllers which causes havoc with controller mapping in many games.

 

I am on windows 10 x64 version 1909 with everything up to date using the latest versions of TM driver software and TARGET script.

 

I have tried the following to no avail :

 

Updated motherboard chipset drivers.

 

In device manager on both USB devices and Human Interface Device controllers unchecked the "Allow the computer to turn off this device"

 

Uninstalled and reinstalled the driver and target software numerous times.

 

The only fix seems to be reboot or unplug and replug the controllers but this is a PITA.

 

Any help greatly appreciated.

 

EDIT: I think I may have found the solution...full credit to Clorydric at this post https://forums.eagle.ru/showpost.php?p=4050109&postcount=15

 

Kill the Windows Store app.

 

You can do this through task manager directly or by creating shortcut to:

 

taskkill.exe /f /im winstore.app.exe

 

 

For the mods, perhaps make this a sticky in the input output forums ?

 

Or you can do what i did and remove the damn app altogether:mad::mad:

 

https://www.avoiderrors.com/remove-windows-store-windows-10/

Link to comment
Share on other sites

with me removing winstore.app.exe does not do a thing

check what is bugging your USB ports/change ports/uninstall hubs

| VR goggles | Autopilot panel | Headtracker | TM HOTAS | G920 HOTAS | MS FFB 2 | Throttle Quadrants | 8600K | GTX 1080 | 64GB RAM| Win 10 x64 | Voicerecognition | 50" UHD TV monitor | 40" 1080p TV monitor | 2x 24" 1080p side monitors | 24" 1080p touchscreen |

Link to comment
Share on other sites

  • 2 weeks later...

Help to get position of substring in TARGET SCRIPT

 

Hiya,

 

I'm working my way through the string manipulation functions available (listed in sys.tmh).

 

I am stumbling on the following function.

 

int strstr(alias string, alias substring){} // returns substring position, or -1 of not found

 

I cannot seem to get this to work. It always returns a '0'.

 

sample code...

 

alias string1 = "This is a test";
alias string2 = "is";
int pos;

pos = strstr(&string1, &string2);

printf("pos = %d\x0a", pos);

 

Can anyone here advise what I'm doing wrong and how to get this working?

Or, heaven forbid, I found a bug in this function!

 

dmonds

Link to comment
Share on other sites

Good question. I tried several variations of using strstr() and was also not able to get it to work. Strings in TARGET are not totally correct compared to C programming. There are a few hoops you have to jump through to use strings in TARGET.

 

Here's two specific examples I tried among others...

 

In this example, I take the simplest method. A quoted text string tends to always work in TARGET since they are constants (no aliases, or having to deal with worrying about string length).

 

printf("strstr test 1:  %d\xa", strstr("This is my string", "is") );

 

The above returns:

strstr test 1: 0

 

C programming expects to see NULL characters (an 8 bit 0) at the end of a string in order to terminate it. TARGET does not add these NULL's automatically in most cases. So below, I added NULLs to my strings using sprintf and \x0 (because x0 is a NULL). Also, using Dim() to create 265 byte buffers means now I am using variables, not constants. It shouldn't matter, but this way I can make sure there is a NULL at the end of the strings. But same result, strstr() didn't work.

 

char str1; Dim(&str1, 256);
char str2; Dim(&str2, 256);
sprintf(&str1, "This is my string\x0");
sprintf(&str2, "is\x0");
printf("_%s_    _%s_\xa", &str1, &str2);
printf("strstr:  %d\xa", strstr(&str1, &str2));

 

The above returns:

_This is my string_ _is_

strstr: 0

 

I tried a few other ideas, but ya, it appears strstr() does not work.

 

In C Programming, strstr() returns a pointer to the location within the string (str1 above) that is the first match. But since TARGET does not directly support pointers (it only supports the concept of an alias which is the address to a variable and is referenced as &str1), they couldn't do it that way. But on the off chance they did and just defined it incorrectly, then strstr() would return a memory address as its integer. It isn't doing that.

 

So ya, I wonder what am I missing as well, but it looks like strstr() doesn't work.

Link to comment
Share on other sites

Ok, well thanks @drakoz for proving I'm not a total numpty.

 

My next challenge is REXEC.

 

1) I have written a function that reads a short, one line json file.

2) I have also written a function to find and read various key values within this file.

They work well.

 

3) I have also found and played with an external C++ program which can also read same file and send me the contents of a specific key whenever it changes (via RegisterGameCallback()).

This also works well (but requires the external program to be running whilst the game is running).

 

I was thinking...why not just use REXEC to run the function described in '1)' above every 1-2 seconds and do away with the external C++ program.

 

Except...I can't get this to work.

 

My function name (in a seperate '.tmh' file) is called 'fnReadJson();'

 

My statement is;

 

REXEC(1, 2000, "fnReadJson();", RNOSTOP);

 

This just hangs the Target Script Editor.

 

I've looked for examples and they all deal with a switch/button press and simple ActKey(PULSE+KEYON+'a') type code.

 

Does anyone here know how I can call my function using REXEC (or any other method) and have it loop indefinitely in the background?

 

Thanks

dmonds

Link to comment
Share on other sites

How are you running REXEC()? It must either be called from within a MapKey(), KeyAxis(), etc., or you have to run it using ActKey(KEYON+REXEC(....)); if you want to just run it stand alone. For example, if you just want to run the REXEC() from main() and just have it run continuously from the moment you first run the script, you need to use ActKey().

 

REXEC() is exactly like EXEC() regarding how and where you can use it. So any example you see using EXEC(), it applies the same to REXEC().

 

I was just discussing several examples of using REXEC() to create background timers. My examples include using REXEC() to run both functions like you are trying, as well as multi-line code written into the REXEC() itself, which is another common gotcha with EXEC() and REXEC(). My examples show off most of the variations of using REXEC(). If you are curious, check it out here: https://simhq.com/forum/ubbthreads.php/topics/4508325/start-a-timer-on-a-key-press

Link to comment
Share on other sites

Thanks again @Drakoz.

 

My code snippet in my last post is how I was trying to run it.

 

Funnily enough, I use REXEC in my code to in a couple MapKey statements already, and didn't realise REXEC specifically needed a MapKey/ActKey/KeyAxis wrapper.

I'll give your suggestion a go this evening when I'm at home again and will let you know.

 

Cheers

dmonds


Edited by dmonds
Link to comment
Share on other sites

Hi @Drakoz,

 

Just read the stuff in the link you included.

 

Interesting stuff, I'll look forward to absorbing properly when I get home tonight.

 

In particular interest was the "Speak()" stuff.

I recall that I had trouble getting "spawn" to work in Win 10, so I'm making an assumption that you are using Win7?

 

Anyhoo and just an FYI...I solved my Text-To-Speech requirements by using a free Win32 program called "voice.exe" and using a function with a text string argument parsed to it to dynamically build a "syscmd" to call it.

 

cheers

dmonds

Link to comment
Share on other sites

Ya, even I was confused about REXEC() the other day because I forgot about the need to use Actkey.

 

The Speak() function should work in Win XP through Win 10, but may fail depending on your Internet Security options (like if you locked things down) or if you don't have Internet Explorer installed at all. Not really sure about this as I've only talked to 2 people who had trouble. It is using a Windows HTML Application function call (using "spawn mshta.exe...") to the Windows Speech API. No need to install any special software.

 

I posted about this function here on the DCS forums as well as on SimHQ.com, but it was in answer to some other questions. There isn't a topic dedicated to it, though. It works great in general. I like it mainly because the external helper app I'm using is default Windows. But what you are doing is probably exactly the same, just using a different helper app.

Link to comment
Share on other sites

HI @Drakoz (again)...

 

1) Speak() ... I'm going to have a go at this and see if it works for me in Win10. Voice.exe, I believe, uses the same mshta if I recall, so...

 

2) REXEC ... still can't get this working. It just hangs the TARGET Script application.

 

Here are the statements I tried...

 

ActKey(KEYON+REXEC(3, 5000, "fnsReadStatusJson();", RNOSTOP));

...which hangs TARGET script...and...

 

ActKey(KEYON+REXEC(3, 5000, fnsReadStatusJson(), RNOSTOP));

...which returns "Bad alias in REXEC ( line 415 in target.tmh )"

 

Here's fnsReadStatus() ...

 

int fnsReadStatusJson() {

int 	buf = 512;
int	myResult;	

Dim(&myJson, buf);
myJson[0] = 0;

fp = fopen(&StatusFile, "r");
if (fp) {
	myResult = fread(&myJson, 1, buf, fp);
	fclose(fp);
	if (myResult == 0) {
		printf("File Read Error: %s\x0a", &StatusFile);
	}
	else {
		strdel(&myJson, myResult-1, buf);    // <<< having to do this this is annoying
	}
}
else {
	printf("Status.json file not found.\x0a");
}
}

 

Obviously, I have an 'alias Statusfile = "c:\\....file path" ' set correctly and 'char myJson;' declared as global variables ... when I call the function normally, it works perfectly.

 

Any help greatly appreciated.

 

dmonds


Edited by dmonds
Link to comment
Share on other sites

[EDIT] Never mind - it worked for me - see my next post.

 

My original comment...

 

I think the issue has to do with the Dim()? You declare myJson globally, but perhaps there is some issue with REXEC(...fnsReadStatusJson()...) creating the buffer (and failing). But by running it before the REXEC once, perhaps it creates the buffer and then it is OK? I don't know why, but doing that kind of thing is playing with memory and could cause all kinds of issues.

 

I'm still looking at it, but wanted to post this comment because it looks like you are looking at it right now too.


Edited by Drakoz
Link to comment
Share on other sites

Hmm, it works for me. Well, actually, you didn't define fp, so I had to add that. But even without it, I didn't get a crash. I just got a Runtime error, symbol not found: fp.... and the script continued to run.

 

Anyway, here is the code I used - your same code, but I added int fp and a printf statement.

 

I set this in main():
ActKey(KEYON+REXEC(20,5000,"fnsReadStatusJson();",RNOSTOP));

Then I copied and pasted your function into a script of mine, added the char myJson; 
and alias for the file name, and added int fp;.  So this is your code. I didn't do 
anything that should have changed it other than the int fp;.  


char myJson;
alias StatusFile = "Myfile.cfg";
int fnsReadStatusJson() {

int	buf = 512;
int	myResult;	
int	fp;

Dim(&myJson, buf);
myJson[0] = 0;

fp = fopen(&StatusFile, "r");
if (fp) {
	myResult = fread(&myJson, 1, buf, fp);
	fclose(fp);
	if (myResult == 0) {
		printf("File Read Error: %s\x0a", &StatusFile);
	}
	else {
		strdel(&myJson, myResult-1, buf);    // <<< having to do this this is annoying
	}
}
else {
	printf("Status.json file not found.\x0a");
}
printf("fnsReadStatusJson:  %s\xa", &myJson);
}

 

The file I read contains the following text (a single line of text with a CR/LF at the end of the line).

 

pro_ProfileSelection=26

 

This is a file I am reading with my own function very similar to yours, so I just replaced my function with yours and called it with the REXEC() in main() as explained above.

 

What are the contents of your json file? Maybe it is something in the file you are reading.

 

Or some other issue.... Does that other program have the file open at the same time you run the TARGET Script?

 

======================

 

It is funny my own function to read a configuration file is very similar to yours. Right down to the part where we both figured out we have to add a NULL to the char[0] element of our alias (buf[0]=0 in my version). But I ended up using fgetc(fp) instead of fread() - mostly because I wanted to try character IO on a file instead of taking the easy way out of using fread(). :D But I notice you don't add a NULL to the end of &myJson after you read the line from your file. I assume this somehow doesn't matter for your script? If I remember correctly, I had to add a NULL to the end of &buf because the string functions wouldn't work with it otherwise. See the buf[i+1] = 0 line.

 

pro_ProfileSelection and pro_ProfileChanged are globals. Everything else are local variables in my function.

 

Anyway, my function below also worked in an REXEC except every now and then, it would print this error. No lockup, just the error, and the script would continue running:

Compile error in Eval: Syntax error: 26e, in "26e"

 

I assume this is an issue with using fgetc() perhaps failing??? It never happens when I run the routine by itself (not in an REXEC). So maybe there are some unpredictable results from doing file IO in an REXEC.

 

Here is my config file read routine:

 

//******************************************************************
// ConfigFileRead()
//	Read the configuration file to set parameters saved from the last time the script was run.
//	For now, this only means the selected profile (e.g. file should contain "pro_ProfileSelection=XX" where XX is the profile number).  
//	The config filename is set by the ConfigFile define below. This file is expected to be in the TARGET Scripts folder.
define	ConfigFile	"Drakoz_TrainSimWorld_Config.cfg"
int ConfigFileRead()
{
int fp, i, p, bufe;
char buf; Dim(&buf, 256);		// buffer used to store the line read from the config file
char parm; Dim(&parm, 256);		// buffer used to hold the parameters (name or value) read from the config file
buf[0]=0;						// Make sure buf has a null to terminate the string

fp = fopen(ConfigFile, "r");
if (fp) {
	i = 0;
	while (1) {
		p = fgetc(fp);		// read a char
		if ((p==0xD) | (p==0xA) | (p==-1)) break;		// if char is CR, LF, or EOF exit
		buf[i] = p;			// add char to buffer
		i = i + 1;
		if (i>254) break;	// just in case the text from file exceeds our buffer size
	}
	buf[i+1] = 0;		// place a null at end of buffer to terminate the string
	fclose(fp);
}

bufe = strchr(&buf, '=');				// find the = in the line (e.g. pro_ProfileSelection=12)
if (bufe > 0) {
	strsub(&parm, &buf, 0, bufe-1);						// get the parameter name (e.g. pro_ProfileSelection)
	if (strcmp(&parm, "pro_ProfileSelection") == 0) {	// if paramater name = pro_ProfileSelection...
		strsub(&parm, &buf, bufe+1, strlen(&buf)-1);	// find the parameter value (e.g. 12)
		p = ieval(&parm);								// convert parameter value from text to integer
		if ((p > 0) & (p <= pro_NumOfProfiles)) {		// if parameter value between 0 and max number of profiles...
			pro_ProfileSelection = p;					//    set new profile
			pro_ProfileChanged = 1;						//    Set profile has changed so we will speak the profile name later.
		}
	}
}
printf("ConfigFileRead:  %d\xa", pro_ProfileSelection);
}

Link to comment
Share on other sites

/snap...both posted at same time!

 

original post (prior to yours)

 

Yeah, maybe I'll move...

 

 

Dim(&myJson, buf);

myJson[0] = 0;

 

... outside and initialise them very early on in the script.

 

No need to reinitialise every time the function is called...surely?

 

My eyes are giving up on me...so I'll call it a night and take another look tomorrow.

 

Thanks heaps for helping out...really appreciate it.

 

dmonds


Edited by dmonds
Link to comment
Share on other sites

No need to reinitialise every time the function is called...surely?

 

Ya, I was thinking about that too. Dim() allocates memory, but I don't know if or how it deallocates that memory. I assume it does, just like it would deallocate a variable, because there are several examples of Dim() in target.tmh inside functions that get called over and over again. But I agree, if your variable is global, might as well allocate the memory with Dim() in main(), or before you call your file read function.

Link to comment
Share on other sites

Hmm, it works for me. Well, actually, you didn't define fp, so I had to add that. But even without it, I didn't get a crash. I just got a Runtime error, symbol not found: fp.... and the script continued to run.

 

Yeah, sorry...another global which should be local but I've been moving a lot of stuff into and out of my functions.

 

 

 

What are the contents of your json file?  Maybe it is something in the file you are reading.

 

File I'm reading is a simple, one line json.

I have several copies of this which I test my code via a simple copy file on a command line to simulate the program.

 

There is nothing in it which would trip up this function.

 

 

It is funny my own function to read a configuration file is very similar to yours.  Right down to the part where we both figured out we have to add a NULL to the char[0] element of our alias (buf[0]=0 in my version).

 

I take that as a compliment.

 

But I ended up using fgetc(fp) instead of fread() - mostly because I wanted to try character IO on a file instead of taking the easy way out of using fread().  :D  

 

You calling me lazy? ;-)

 

But I notice you don't add a NULL to the end of &myJson after you read the line from your file.  I assume this somehow doesn't matter for your script?  If I remember correctly, I had to add a NULL to the end of &buf because the string functions wouldn't work with it otherwise.  See the buf[i+1] = 0 line.

 

Hmmm...the function works but if I printf &myJson ... often get garbage displayed at the end of the string. Hence, the 'strdel' statement.

I'm not a programmer, this works, but if there is a 'proper' way to seal my string after the fread, then I'm all ears....are you saying I add a null via a 'strcat' rather than the 'strdel' is better/preferred/more-proper-ish?

 

Anyhoo, regardless of why I needed to run 'fnsReadStatusJson();' before the REXEC ... it now works and I can move onto what I was trying to achieve in the first place.

 

For that, I thank you for your very valuable assistance.

 

Cheers

dmonds

 

p.s. no doubt I'll be back with more newbie questions very soon!

Link to comment
Share on other sites

Ha, calling you lazy. No in fact, I was actually being lazy because I didn't want to figure out fread(). So thanks for your example. ;)

 

Regarding the NULL. Ah, now I get it what you were doing. Yes, the reason you get the garbage on your &myJson string when you print it is because there is no NULL character at the end of the string. In normal C, all string functions would add a NULL (a zero) to the end of the string and all such functions recognize the NULL as the end of the string even if the buffer or variable holding that string is longer. printf() is looking for that NULL so it knows when it should stop printing characters.

 

So when you create a string like this:

 

alias str1 = "This is my string";

 

everything works because TARGET seems to terminate the string with a NULL after the g in "string" (I believe) and hence str...() functions or printf() knows where the end of the string is. This is how C works normally. But for strings defined like this (which is not standard for C):

 

char str2;

Dim(&str2, 256); // create an array of char, 256 characters long, which really creates a string

 

Now the string referenced by &str2, is 256 characters long, and there is no guarantee that the string will end in a NULL as the 256 bytes of memory is not cleared when created. What ever garbage was in memory when it was created is what you get.

 

So in TARGET, because of this non-standard way of creating and handling strings, we have to add a NULL to the end of our strings manually. In my example, the line "buf[i+1] = 0;" is where I added the NULL, where i is the string length. I was able to do this because by using fgetc, I knew the length of my string because I counted every character in my file until I found a CR/LF character pair for the end of a line. In your case, you would do the same, but you would have to parse the line of text you read with fread() to find the end of line. And, in fact, this is why I was a bit "lazy" and did not try fread because I wasn't sure I would get the CR/LF using fread, or if fread would return the number of characters correctly. But your example shows that fread does return the string length, so it works after all. I should have known that I guess. Again, thanks for showing this.

 

Hence, perhaps you should replace your line:

 

strdel(&myJson, myResult-1, buf);

 

with this line:

 

myJson[myResult] = 0;

 

Because the string is myResult long, myJson[myResult-1] is the last character in the string, so we place a NULL at myJson[myResult] and it terminates the string. I'm not saying this or any other method is the "correct" way to do it, but when it comes to strings, thinking of them as arrays of char helps a great deal with basic string manipulation. That is how all the str...() functions are working with these strings.

 

What I don't know because I didn't test it is, I don't know if strdel() adds a NULL to the end of the valid string characters after deleting the characters. I assume it does because in fact, deleting characters off the right end of a string is actually accomplished not by actually deleting anything, but by adding a NULL character right after the character marked by myResult-1 in your example.

 

Regarding strings and array of char

 

In case you don't understand &str vs str[0], remember, a string is actually a single dimensional array of char. Say we have:

 

alias str3 = "Hello";

 

This is the same as:

 

char str4[] = {'H', 'e', 'l', 'l', 'o', 0} // NULL added to the end of the string

 

Where a letter enclosed in ' ' is a single byte or a char, and str4[] is an array of char.

 

&str3 refers to the entire string, and str3[0] is equal to H. In C (and I assume in TARGET), str[6] would be a NULL. But I haven't really tested this to confirm. Also, above, we can say &str3 and str3[0] as valid representations of str3, and we can also say str4[0] as well, but we cannot say &str4 because str4 is not an alias.

 

Again, I'm shooting a little from the hip here. I haven't completely tested these things, so a couple details may be off (regular C programmers out there will probably tell me where I'm being an idiot). But my goal is to explain how strings work in TARGET because TARGET does not do strings the way C does them. And often, it is a royal pain in the behind. To understand this better, go read up on arrays and pointers in C and it might start to make more sense.

Link to comment
Share on other sites

Hi again...thanks for all that.

 

It makes sense and aligns with how I "thought" it should work.

 

When testing...I wrote a string, using combinations of putc and fwrite.

In both cases I wrote a NUL at the end.

 

When reading back...at first I thought I'd nailed it as the printf was printing the string correctly.

Then, subsequent, stop/start of the script, and...garbage again at the end of the string.

 

As the strdel seemed to work , I kind of went "too hard, I'll come back to it later".

 

TLDR...I have not seen adding a NUL to a string I am writing in target as doing what it should.

 

Perhaps I did it wrong?

 

I tried fwrite with a string "abcdef\x0" (where string was 7 chars).

I tried fwrite with a string "abcdef"...(6 chars) then a putc 0.

 

Both seemed to work at first...then, subsequent runs later....boom....garbage after the string when printf the string...very frustrating.

 

Mind you...only printf exhibited the issue.

Things like strcmp etc all worked fine, 100% of the time.

 

Very strange....probably a bug in printf.

 

dmonds


Edited by dmonds
Link to comment
Share on other sites

Instead of putting a NULL in the file you write, just make sure to add the NULL to strings you read from the file. This shouldn't be needed in C, but in TARGET, I don't trust functions to handle NULLs correctly.

 

More importantly, a text file is generally supposed to be human readable in a common text editor, and a NULL is considered a binary code. So if you write NULLs to a text file, you are breaking with convention of the file being a text file. Or worse, if you or someone edits the text file in a common text editor, there is a good chance the NULLs might unknowingly be removed, breaking your ability to correctly read the file from your script.

 

Instead, depend on EOL (end of line such as CR, LF, or CR/LF) as this is the intended way to tell the end of a line. This is the other reason I used fputc and fgetc in my example. I wanted to play with controlling these characters exactly whereas I wasn't sure if fwrite and fread would give me that. You are further along than me on this since you have been playing with this stuff more, so not sure I'm offering much advice. Maybe some of the stuff you tried isn't working exactly right because of TARGET not being correct in its string handling.

 

I think all the str...() functions add/delete and handle NULLs correctly, but maybe some of your strings didn't have NULLs added correctly in the first place which maybe cause issues with the some of the str...() functions. Or rather, I've seen the str... functions add NULLs, but maybe in some cases, they aren't adding NULLs because they expect a NULL to exist there already. In my experience, printf has always handled strings exactly as expected - meaning if no NULL, printf prints the entire buffer until it finds a random NULL. If the NULL is where I wanted it to be (because I added), printf has always printed the string correctly.

Link to comment
Share on other sites

  • Recently Browsing   0 members

    • No registered users viewing this page.
×
×
  • Create New...