Page 1 of 2

Need tutorials

Posted: 24 Nov 2010, 04:54
by nxtboyiii
Can someone give me a tutorial on reading and writing structures, arrays, and structure arrays?
I have a problem with that and I need help.


Thanks, and have a nice day,
nxtboy III

Re: Need tutorials

Posted: 24 Nov 2010, 21:26
by physics-matt
A few more details would help:

1. What programming language?
2. What exactly do you mean by "reading" and "writing"? Depending on the context, these could mean a number of different things (e.g. writing to a file? writing to memory? )

I'm sure people here would like to help, it's just not quite clear what exactly you're after.

Matt

Re: Need tutorials

Posted: 25 Nov 2010, 01:31
by nxtboyiii
In NXC.
Reading and writing to a .dat file.

Re: Need tutorials

Posted: 25 Nov 2010, 08:16
by physics-matt
There are two things you need to learn: first, how to format the data in your struct, and second, how to write the data to a file.

There is no such command as "write this struct to a file" (EDIT: Yes there is, see below... oops :oops: ). Instead, you must turn the data in your struct into a string or byte array (which is also, effectively, a string). For instance, you might do something like this:

Code: Select all

struct MyStruct {
  int a;
  int b[10];
};

task main()
{
  string str;
  // Create a struct and fill it with data
  MyStruct A;
  A.a = 1;
  for (int i =0; i < 10; i ++)
   A.b[i] = i;

  // Make a string that contains the data
  str = NumToStr( A.a );
  for (int i =0; i < 10; i ++)
    str = StrCat( str, " ", NumToStr(A.b[i]) );
}
This would create a string that you can now write to a file. e.g.

Code: Select all

  byte fid = 0;
  long bytesWritten = 0;
  long fileSize = 11*2;
  CreateFile("data.dat", fileSize, fid);
  WriteString(fid, str, bytesWritten )
  CloseFile(fid);
All the file read/write commands in NXC are well explained in the documentation and are fairly easy to use. Most of the work will be to figure out a format for your data so that you can convert the struct to a suitable string, and back again.

Hope that helps.

Matt

Re: Need tutorials

Posted: 25 Nov 2010, 17:50
by nxtboyiii
Thank you. :)
Is there a limit to how much you put into an array to read?
I am having a problem with the code on the post in the Mindstorms Software category "Help with efficiency of code".
Are you sure you have to convert it into a string?
Is there a way to convert it back?

Thanks, and have a nice day,
nxtboy III

Re: Need tutorials

Posted: 26 Nov 2010, 09:00
by physics-matt
I've had a look at your code in the other thread, and I gather that the line in question is

Code: Select all

Write(handle,Game);
I've looked through the documentation again, and it turns out I was wrong about whether or not you can write structs directly to a file. For instance, the following code works fine:

Code: Select all

struct Substruct {
  int c;
  int d;
};

struct MyStruct {
  int a;
  Substruct b[];
};

task main()
{
  MyStruct A;
  Substruct B[10];
  A.a = 1;
  for (int i =0; i < 10; i ++)
  {
   B[i].c = i;
   B[i].d = i;
  }

  A.b = B;

  byte fid = 0;
  long fileSize = 100; // Just some large number for now...
  CreateFile("data.dat", fileSize, fid);
  Write( fid, A );
  CloseFile(fid);
}
So it seems you can read and (I assume) write fairly complicated structs to files. Not sure then why your code doesn't work, but it's probably somewhere in the detail about the way that gamesave is defined or used in your code. Having a quick look, I can't see how it differs significantly to what I've written, but that was only a quick look.

I would try writing a little program just to try loading and saving a gamesave structure - only include the code absolutely necessary to try it out (a bit like I've been doing above). That might make it clearer why it isn't working.

Sorry I can't be more help, but I'm late for work!

Matt

Re: Need tutorials

Posted: 26 Nov 2010, 17:08
by nxtboyiii
I used this code, but when I saved the file, quit out of the program on the NXT, and ran it again and read it, it said that A.a equals 0, though it should equal 1. :(
Does anyone know why?

Code: Select all

struct Substruct {
  int c;
  int d;
};

struct MyStruct {
  int a;
  Substruct b[];
};
  long fileSize = 100; // Just some large number for now...
    MyStruct A;
task main()
{
 while(1)
 {
 ArrayInit(A.b,0,10);
 if(ButtonPressed(BTNLEFT,0))
 {
  A.a = 1;
  for (int i =0; i < 10; i ++)
  {
   A.b[i].c = i;
   A.b[i].d = i;
  }

  byte fid = 0;
  CreateFile("data.dat", fileSize, fid);
  Write( fid, A );
  CloseFile(fid);
  }
  else if(ButtonPressed(BTNRIGHT,0))
  {
  byte fid2;
    OpenFileRead("data.dat", fileSize, fid2);
  Read( fid2, A );
  CloseFile(fid2);
  NumOut(0,0,A.a);
  }
  }
}

Re: Need tutorials

Posted: 26 Nov 2010, 18:26
by physics-matt
The compiled code for

Code: Select all

Read(fid2, A);
is:

Code: Select all

	mov __FReadArgs.FileHandle, __main_7qG2_fid2_7qG2_000
	set __FReadArgs.Length, 6
	syscall 3, __FReadArgs
	mov __D0main, __FReadArgs.Result
	unflatten A, __FReadTmpByte, __FReadArgs.Buffer, A
The bit to notice is that __FReadArgs.Length has been set to 6, meaning that only 6 bytes are being read. This certainly does not look right. My guess is that the compiler is unable to work out how big the array is and uses the size of a single Substruct instead.

I suspect only John H can tell us exactly what's going on and whether it can be fixed. How about the following work around:

Code: Select all

  OpenFileRead("data.dat", fileSize, fid2);
  Read( fid2, A.a );
  for ( int i = 0; i < 10; i ++)
  {
    Substruct ss;
    Read( fid2, ss );
    A.b[i] = ss;
  }
  CloseFile(fid2);
Matt

Re: Need tutorials

Posted: 26 Nov 2010, 22:02
by nxtboyiii
I think there is a limit to how much is saved to a file.
Is there?
If I make the variable "map" smaller, it works fine.

Code: Select all

LocationType map[]={{1,1},{2,2},{3,3},{1,1},{2,2},{3,3},{1,1},{2,2},{3,3},{1,1},{2,2},{3,3},{1,1},{2,2},{3,3},{1,1},{2,2},{3,3},{1,1},{2,2},{3,3},{1,1},{2,2},{3,3},{1,1},{2,2},{3,3},{1,1},{2,2},{3,3},{1,1},{2,2},{3,3},{1,1},{2,2},{3,3},{1,1},{2,2},{3,3},{1,1},{2,2},{3,3},{1,1},{2,2},{3,3},{1,1},{2,2},{3,3},{1,1},{2,2},{3,3},{1,1},{2,2},{3,3},{1,1},{2,2},{3,3},{1,1},{2,2},{3,3},{1,1},{2,2},{3,3},{1,1},{2,2},{3,3},{1,1},{2,2},{3,3},{1,1},{2,2},{3,3},{1,1},{2,2},{3,3},{1,1},{2,2},{3,3},{1,1},{2,2},{3,3},{1,1},{2,2},{3,3},{1,1},{2,2},{3,3},{1,1},{2,2},{3,3},{1,1},{2,2},{3,3},{1,1},{2,2},{3,3},{1,1},{2,2},{3,3},{1,1},{2,2},{3,3},{1,1},{2,2},{3,3},{1,1},{2,2},{3,3},{1,1},{2,2},{3,3},{1,1},{2,2},{3,3},{1,1},{2,2},{3,3}};
int A1[];
int A2[];
int fs=2000;
long handle=0;
long handle2=0;
task main()
{
 while(1)
 {
 if(ButtonPressed(BTNLEFT,0))
 {
// string text=ByteArrayToStr(map);
 //TextOut(0,0,text);
// Wait(5000);
 ClearScreen();
 long Arrlen=ArrayLen(map);
      ArrayInit(A1,0,Arrlen);
     ArrayInit(A2,0,Arrlen);
      for(long c=0; c < Arrlen;c++)
     {
      A1[c]=map[c].X;
     }
     PlayToneEx(500,30,1,0);
          for(long c=0; c < Arrlen;c++)
     {
      A2[c]=map[c].Y;
     }
 DeleteFile("test.tst");
 CreateFile("test.tst",fs,handle);
 Write(handle,A1);
 CloseFile(handle);
  DeleteFile("test2.tst");
 CreateFile("test2.tst",fs,handle2);
 Write(handle2,A2);
 CloseFile(handle2);
 PlayToneEx(400,30,1,0);
 }
 if(ButtonPressed(BTNRIGHT,0))
 {
 //string text2;
 OpenFileRead("test.tst",fs,handle);
 Read(handle,A1);
 CloseFile(handle);
  OpenFileRead("test2.tst",fs,handle2);
 Read(handle2,A2);
 CloseFile(handle);
  long Arrlen=ArrayLen(A1);
         for(long c=0; c < Arrlen;c++)
     {
      map[c].X=A1[c];
     }
          for(long c=0; c < Arrlen;c++)
     {
      map[c].Y=A2[c];
     }
 //StrToByteArray(text2,map);
 NumOut(0,0,Arrlen);
 Wait(1000);
 ClearScreen();
 }
 }
}

Re: Need tutorials

Posted: 26 Nov 2010, 22:35
by physics-matt
Are you sure that it works fine?

When I run it the second time (having previously run it and pressed the left button) and press the right button it prints 0 to the screen, indicating that A1 is length 0, so no data was read from the file.

Matt