project-navigation
Personal tools

Author Topic: C: appending arrays  (Read 9546 times)

Hoehrer

  • Guest
C: appending arrays
« on: March 25, 2006, 09:15:54 am »
This is most probably a noob question, but how do i append two arrays in C?
For strings there is the strcat function, but

Example code
Code: [Select]
int a1[25];
int a1[25];


Let's now say that the arrays are filled from the beginning (0++) and the first array has at least one free space at the end. Is there an existing function/way to do this or do i need to write my own?

Werner

EDIT: Note to self: This is a pretty good overview on C FAQs http://www.eskimo.com/~scs/c-faq.com/ ... need to dig through the array-section soon.

oxyXen

  • Guest
C: appending arrays
« Reply #1 on: March 25, 2006, 12:34:32 pm »
Hi

You mean probably  :wink:
Code: [Select]

int a1[25]
int a2[25]

and want a function doing something like : a3[50]=a1+a2

When you create an array, then its space in the memory is static. You will have to do something like that (pseudocode):
Code: [Select]
arrayAppend(char* a1, char* a2)
{
   l1<-length of a1
   l2<-length of a2
   
   char* a3 = (char*) malloc (sizeof(char)*(l1+l2))
   and now use 2 loops to copy the whole stuff.
   return a3
}


strcat needs as a parameter enough allocated space.
Quote
Parameters.
dest
  Pointer to a null-terminated string with enough space allocated to contain both src and dest.
src
  Null-terminated string to append.

Everywhere are pros and contras ;)
What exactly do you want to do with this?

ox
 :)

edit: arrays are no black magic, but they can get me sometimes insane :D

Hoehrer

  • Guest
C: appending arrays
« Reply #2 on: March 25, 2006, 01:24:33 pm »
Ugh, that is what i was afraid of .... let me show you what i need/want to do:

This is a nice little code-snippet from src/client/cl_research.c
Code: [Select]
/*
======================
R_GetFirstRequired

Returns the first required technologies that are needed by "id".
That means you need to research the result to be able to research (and maybe use) "id".
======================
*/

void R_GetFirstRequired( char *id, char *required[MAX_TECHLINKS])
{
int i, j;
technology_t *t;
char temp_requiredlist[MAX_TECHLINKS][MAX_VAR];

for ( i=0; i < numTechnologies; i++ ) {
t = &technologies[i];
R_GetRequired ( t->id, temp_requiredlist );
// if (length of temp_requiredlist == 0) TODO
// _append_ it to *required TODO
// else
for ( j=0; j < MAX_TECHLINKS; j++ ) {
R_GetFirstRequired( temp_requiredlist[j], temp_requiredlist );
}
}
Com_Printf( _("R_GetFirstRequired: technology \"%s\" not found.\n"), id );
}


Ok, this function is meant to loop (recursively) through an array (not the one in question) and collects multiple arrays of strings by calling
Code: [Select]
R_GetRequired ( t->id, temp_requiredlist );
this arrays of strings should finally be appended to (char *required)

every list of strings looks like this:
Code: [Select]
char varname[MAX_TECHLINKS][MAX_VAR];

I hope my explaination was clear enough?

Thanks for any help.
Werner

oxyXen

  • Guest
C: appending arrays
« Reply #3 on: March 25, 2006, 03:26:20 pm »
Ok, this is now a bit heavier for me :wink:

At first i'll try to understand the system:
Code: [Select]
initial
    |----tachyon
            |----tachyonrifle
                     |----tachyonrifle_ammo
                     |----tachyonsniper
                              |----tachyonsniper_ammo

So, this is now a piece of the techtree.

Ok, now i wann research tachyonsniper_ammo.

R_GetFirstRequired should now return tachyon (i guess, initial is researched at the beginning of the game).

Hm, i think i don't get it completely. How about that:
Code: [Select]
void R_GetRequired(technology_t *t, char *required)
{
   if (t->required->isResearched)
   {
       return;
   } else
   {
       <pseudo>append t->required to required</pseudo>
       R_GetRequired(t->required, required);
   }

   return;
}

technology_t *R_GetFirstRequired(technology_t *t)
{
   char temp[MAX...]
   R_GetRequired(t, temp);
   <pseudo>reverse temp</pseudo>
   return temp[0];
}


I don't know the structs and the pointer-wirrwarr :wink: that well, so it might look strange or be even not that, what you want :(

Why don't you take integers for the ids?

You could also try to get a list of pointers to the technologies needed.

Will there be technologies which will require two or more predecessors, ie:
Code: [Select]
tech oxyXen
{
type tech
name "Tachyon control"
requires oxygen
        requires    xentronium
description "oxyxen_txt"
time 100
}


And last but not least, there seems to be a bug in the research.ufo file:
Code: [Select]
tech plasma
{
type weapon
requires tachyonsniper
provides tachyonsniper_ammo
time 0
}


I hope i could help you somehow and did not get you dizzy ;)

ox

edit: there are some errors in my sourcecode, but i hope the idea can be realized anyways.

Hoehrer

  • Guest
C: appending arrays
« Reply #4 on: March 25, 2006, 03:50:00 pm »
Quote from: "oxyXen"
At first i'll try to understand the system:
Code: [Select]
initial
    |----tachyon
            |----tachyonrifle
                     |----tachyonrifle_ammo
                     |----tachyonsniper
                              |----tachyonsniper_ammo

So, this is now a piece of the techtree.

Ok, now i wann research tachyonsniper_ammo.

R_GetFirstRequired should now return tachyon (i guess, initial is researched at the beginning of the game).

Correct, the "initial" and "nothing" requirements are terminators and indicate that this is a starting technology (initial) or one that has been aquired from the aliens (nothing). ... in this case we can handle see them as equals.

I'll look into your pseudo code and see if i can make it out ... just need some time for that :)

Quote

I don't know the structs and the pointer-wirrwarr :wink: that well, so it might look strange or be even not that, what you want :(

Why don't you take integers for the ids?

You could also try to get a list of pointers to the technologies needed.

What would that change? I would still need to handle the appending of arrays... don't I? But i might not understand what you mean exactly. I'll look into this as well.

Quote
Will there be technologies which will require two or more predecessors, ie:

yes, the code for that looks like this:

Code: [Select]
tech oxyXen
{
type tech
name "Oxygen-Xentronium"
requires "oxygen xentronium"
description "oxyxen_txt"
time 1000
}

R_GetFirstRequired should return "oxygen" and "xentronium"


BTW: I fixed some bug in research.ufo recently including the plasma-bug

Quote
I hope i could help you somehow and did not get you dizzy ;)


Thanks for your help,
Werner

Hoehrer

  • Guest
C: appending arrays
« Reply #5 on: March 25, 2006, 03:59:18 pm »
i think i've found a solution ... if i use a struct that keeps track of the total numbers of strings in it i think this will be _alot_ easier. What do you think?

Example code for that struct:
Code: [Select]
typedef struct research_requirements_s
{
char requires[MAX_TECHLINKS][MAX_VAR];
int numEntries;
} research_requirements_t;


Werner

oxyXen

  • Guest
C: appending arrays
« Reply #6 on: March 25, 2006, 04:21:35 pm »
Hi

Quote
What would that change? I would still need to handle the appending of arrays... don't I? But i might not understand what you mean exactly. I'll look into this as well.


char is limited to a size of 1 byte, which means, that you can either identify "only" 255 techs by a character, or you can make combinations of character, which will of course increase the possibilities, but if one tech has x chars in its id, and another y chars, than there's no justification for implementing a function that can handle it.
With ints you have thousands of unique ids and everyone takes exactly sizeof(int) space in the memory.

Quote
R_GetFirstRequired should return "oxygen" and "xentronium"

What if xentronium requires xenophysics?

This whole research thing seems really to be not easy  :?

here is my idea of the structure object:
Code: [Select]
int id
char* name
int numRequired
techstruct* required[numRequired]
bool achieved
int timeToResearch


Now you can surf to your tech needed:
Code: [Select]
void ResearchSomething(techstruct* t)
{
   for (int i=0; i<t->numRequired; i++)
   {
      if (!t->required[i]->achieved))
      {
         ResearchSomething(t->required[i]);
         return;
      } else
      {
         com_printf("Research this: %s", t->name+'\0');
      }
   }
}


Now i'll try to post something sourceforge.

Good luck

ox

oxyXen

  • Guest
C: appending arrays
« Reply #7 on: March 25, 2006, 04:23:20 pm »
Quote from: "Hoehrer"
i think i've found a solution ... if i use a struct that keeps track of the total numbers of strings in it i think this will be _alot_ easier. What do you think?

Example code for that struct:
Code: [Select]
typedef struct research_requirements_s
{
char requires[MAX_TECHLINKS][MAX_VAR];
int numEntries;
} research_requirements_t;


Werner


Heh, i don't know yet. What exactly does MAX_TECHLINKS do?

ox

Hoehrer

  • Guest
C: appending arrays
« Reply #8 on: March 25, 2006, 04:50:53 pm »
Quote from: "oxyXen"
Quote from: "Hoehrer"
i think i've found a solution ... if i use a struct that keeps track of the total numbers of strings in it i think this will be _alot_ easier. What do you think?

Example code for that struct:
Code: [Select]
typedef struct research_requirements_s
{
char requires[MAX_TECHLINKS][MAX_VAR];
int numEntries;
} research_requirements_t;


Werner


Heh, i don't know yet. What exactly does MAX_TECHLINKS do?

ox


That's just the maximal number (c-define) of strings that are allowed.
MAX_TECHLINKS ... number of available array entries (entry=string)
MAX_VAR ... numer of characters in a string
numEntries ... lists the number of the _used_ entries and is set when writing strings into the array.

I'm using this struct already in the code. The fact that this is now handles in a struct helps alot in the functions i'm not writing. So no need to worry too much about it..... thanks fo all your help so far anyway. :D

Werner

Hoehrer

  • Guest
C: appending arrays
« Reply #9 on: March 25, 2006, 04:58:51 pm »
Sorry, i missed your previous post, but as i wrote in my previous post the problem is more or less solved now.

Quote from: "oxyXen"
Quote
What would that change? I would still need to handle the appending of arrays... don't I? But i might not understand what you mean exactly. I'll look into this as well.


char is limited to a size of 1 byte, which means, that you can either identify "only" 255 techs by a character, or you can make combinations of character, which will of course increase the possibilities, but if one tech has x chars in its id, and another y chars, than there's no justification for implementing a function that can handle it.
With ints you have thousands of unique ids and everyone takes exactly sizeof(int) space in the memory.

I'm currently not identifying the techs by a char ... i'm using a full string that is ~256 chars long ;) this provides _alot_ more unique possibilities and is more readable as well. Space-requirement is an issue though, but that is solved as soon as i've finished the integration of the new struct in the getfirstrequired function. -> previous post.

Quote
Quote
R_GetFirstRequired should return "oxygen" and "xentronium"

What if xentronium requires xenophysics?

Then it should return "oxygen" and "xenophysics" instead (always the one that is nearer to "initial" and has not yet been researched)

oxyXen

  • Guest
C: appending arrays
« Reply #10 on: March 25, 2006, 05:02:45 pm »
Quote
Then it should return "oxygen" and "xenophysics" instead (always the one that is nearer to "initial" and has not yet been researched)


Rightey, then i got it :)

I'll take now a break and have later a more detailed look into the research code.
Until then, i'm looking forward to the next snapshot :)

ox

Hoehrer

  • Guest
C: appending arrays
« Reply #11 on: March 25, 2006, 07:50:56 pm »
Ok, just FYI: the R_GetFirstRequired fucntion now works and returns with the correct first requirements.

I think i need to add a check if it has been researched alread, but otherwise it is functional.

BUT ... there is always a "but" ;) ... i get the following error message when running "technologylist" in the console:
Code: [Select]
glibc detected *** free(): invalid next size (fast): 0x18de7158 ***
Received signal 6, exiting..


gdb gives me this:
Code: [Select]
removed to make a readable thread


I can't really decrypt this stuff. Does anybody have an idea?

Werner

Offline Mattn

  • Administrator
  • PHALANX Commander
  • *****
  • Posts: 4831
  • https://github.com/mgerhardy/vengi
    • View Profile
    • Vengi Voxel Tools
C: appending arrays
« Reply #12 on: March 25, 2006, 08:20:38 pm »
have a look at my latest commit - i've added a fixme that descibes the error (at least i hope so)

Hoehrer

  • Guest
C: appending arrays
« Reply #13 on: March 25, 2006, 08:39:03 pm »
Ah, thanks. I've suspected that the fault came from some init-problems and i even tried to init this one. But when i try to set it to 0s but that just produces  the error below.
Code: [Select]
memset( req_temp, 0, sizeof( research_requirements_t ) );
Code: [Select]
Received signal 11, exiting...
Speicherzugriffsfehler


Werner