08 Feb, 2012, Vigud wrote in the 21st comment:
Votes: 0
Hence the if.
08 Feb, 2012, Rarva.Riendf wrote in the 22nd comment:
Votes: 0
I suggest this tool when reading variable declaration of array and pointers, it helps tremendously.
cdecl tool

Helps a lot to read those goddam char declaration
09 Feb, 2012, Tyche wrote in the 23rd comment:
Votes: 0
If you really want to see what's going on, you can run it in gdb.
There's no better way to see how C works under the covers.

int somefunction() {
char *a = "hello";
char b[] = "hello";
char c[50] = "hello";
return;
}

Step through the function you hit the return statement.
I've color-coded this output to make it easy.

(gdb) info locals
a = 0x402080 "hello"
b = "hello"
c = "hello", '\000' <repeats 44 times>

a holds an address to literal pool, 0x402080, which is in the .data section and it is
likely allocated to a read-only page.

(gdb) p &a
$1 = (char **) 0x22ccec
(gdb) p &b
$2 = (char (*)[6]) 0x22cce6
(gdb) p &c
$3 = (char (*)[50]) 0x22ccb4

The above are the addresses of the local varables on the stack. The stack is always on a
read/writeable page. And in this compiler things are allocated in order from the top of memory
on down.

If you examine the stack from where c points on up to include a and b (50+6+4=60) bytes.
(gdb) x/60 c
0x22ccb4: 0x68 0x65 0x6c 0x6c 0x6f 0x00 0x00 0x00
0x22ccbc: 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00
0x22ccc4: 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00
0x22cccc: 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00
0x22ccd4: 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00
0x22ccdc: 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00
0x22cce4: 0x00 0x00
0x68 0x65 0x6c 0x6c 0x6f 0x00
0x22ccec: 0x80 0x20 0x40 0x00

You'll see you have three copies of "hello", one in literal pool and two on the stack.

This was using Cygwin gcc 4.2, with -ggbd -O0 options. Different compilers might do it differently, but are
probably very similar.
09 Feb, 2012, Cratylus wrote in the 24th comment:
Votes: 0
can we talk about handling strings in G now
09 Feb, 2012, Scandum wrote in the 25th comment:
Votes: 0
KaVir said:
Scandum said:
This because orig is a pointer and doesn't actually hold any actual data like an int would.

They hold a memory address, which is usually a 32 bit integer.

Yes, that's what I wrote in the second part you quoted: "orig holds a pointer to the character array". If you're going to be intellectual and call it a memory address you probably should be more consistent, as it makes as much sense to call it a 32 bit integer as it would to call it a 32 bit float. As data blocks are allocated in bytes (a byte is 8 bits) it's best to skip talking in bits and describe a memory address as a 4 byte data block, or 8 bytes on a 64 bit architecture. Correct me if I'm wrong, or right, obviously it doesn't matter.

KaVir said:
Scandum said:
So orig holds a pointer to the character array, while &orig points to the pointer's physical address, which you typically have little use for.

&orig returns the address of a variable which contains another memory address. This can be a useful technique in certain string handling functions, because C technically only supports pass-by-value.

Yes, exactly what I wrote, though you're being rather vague, probably so it doesn't sound like you're repeating me. Lets repeat it a third time worded differently, it's so much fun! &orig returns the memory address that holds the memory address to the variable (orig) which in turn holds the memory address to the start of a block of data (the null terminated character array also known as a string). Yay!
09 Feb, 2012, Scandum wrote in the 26th comment:
Votes: 0
Cratylus said:
can we talk about handling strings in G now

No, we can write about it though.
09 Feb, 2012, Scandum wrote in the 27th comment:
Votes: 0
Vigud said:
Because he said something about initializing a string and that's what can't be done in C, so I had to guess.

You can't guess in C, sorry. There are no strings in C, and indeed, you can't initialize what doesn't exist.
09 Feb, 2012, Tyche wrote in the 28th comment:
Votes: 0
JohnnyStarr said:
Thanks for the input guys…
#include <stdio.h>
char *map[50][50];

int main(void) {

char exit[100];
char *desc;
strcpy(exit, "East");

map[0][0] = exit;

desc = map[0][0];

strcat(desc, " - To Tom Bombidil's house.");

printf("%s <- updated.", map[0][0]);

return 0;

}


My concern is this seems too easy. I didn't realize that you could even have an array of char*, so I am hesitant
to put to much effort into this without knowing for sure what it will yield. What are the hazards here? Should I
be allocating the map with malloc() or calloc()?


Well… exit is allocated on the stack, and when you hit return, the stack unwinds and other
random goodies will be allocated at that memory. The global map[0,0] will point to random data,
otherwise known as a "wild pointer".

You had better use malloc/calloc. :-)
09 Feb, 2012, Tyche wrote in the 29th comment:
Votes: 0
Surely 'string' is an abstract concept in C, and we all know what we really mean here, specifically, "an array of chars terminated with a NUL character".
At least that is the concept behind C's standard library string routines.
Obviously other conceptions of 'string' can be implemented in C, and are likely better in other ways.

struct string {
size_t length;
char * data;
}
09 Feb, 2012, Rarva.Riendf wrote in the 30th comment:
Votes: 0
You can do stuff like that that can be useful though

const char* RANGED_WEAPON_NAMES[WEAPON_TYPE_NUMBER][20] = {
/*RANGED_BOW*/ {"bow","longbow","compound bow","flatbow","recurve bow","reflex bow",NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL},
/*RANGED_CROSSBOW*/ {"crossbow","repeating crossbow","recurve crossbow","arbalest",NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL},
/*RANGED_GUN*/ {"musket","arquebus","flintlock pistol",NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL},
};
09 Feb, 2012, Vigud wrote in the 31st comment:
Votes: 0
Tyche said:
If you really want to see what's going on, you can run it in gdb.
There's no better way to see how C works under the covers.
Almost: that's pretty good way to see how this specific implementation works. For example, C has nothing to do with stacks.
09 Feb, 2012, Tyche wrote in the 32nd comment:
Votes: 0
Vigud said:
Tyche said:
If you really want to see what's going on, you can run it in gdb.
There's no better way to see how C works under the covers.
Almost: that's pretty good way to see how this specific implementation works. For example, C has nothing to do with stacks.

I'm well aware of that as I work on IBM MVS and zOS. IBM's C wasn't implemented using a stack.
I can be just as infuriatingly anal retentive, but I don't really don't think it's going to help the poster.
I've already mentioned 'implementation dependent' in a previous post and I'm simply not going to repeat it in every fucking post.
09 Feb, 2012, KaVir wrote in the 33rd comment:
Votes: 0
Scandum said:
KaVir said:
Scandum said:
This because orig is a pointer and doesn't actually hold any actual data like an int would.

They hold a memory address, which is usually a 32 bit integer.

Yes, that's what I wrote in the second part you quoted: "orig holds a pointer to the character array".

You said a pointer "doesn't actually hold any actual data like an int would". However that's actually exactly what it does. Clearly you feel offended that I've corrected you, but understanding how pointers work is essential to understanding string manipulation in C, and the OP started this thread specifically because he wants to "master C strings once and for all".
09 Feb, 2012, Kaz wrote in the 34th comment:
Votes: 0
JohnnyStarr said:

By making a 2d array of type char*, I am hoping to be able to implement an ASCII mapper.

My concern is this seems too easy. I didn't realize that you could even have an array of char*, so I am hesitant
to put to much effort into this without knowing for sure what it will yield. What are the hazards here? Should I
be allocating the map with malloc() or calloc()?

** I am currently developing with codepad.org (I'm at work), which accounts for the lack of compiler warnings.


It's better than that: you have an array of 50 arrays of 50 pointers to char. :)

So, should you be allocating the map with malloc or calloc? In this case, no. Your map, which is at file-scope, has static storage (not to be confused with the static keyword) and is thus initialised to be all-0s. If you want your map to have a variable size, then yes. At that point, you really want to start writing yourself a set of functions to manipulate it, though.

Anyway, the big thing is that just copying raw pointers into it will not do. As someone has pointed out, you want to strdup (or similar) into the map, and free (or similar) on release. Here's a rough guide to what you want. You don't have to use such functions (you may prefer just dealing with it in-line, or may want to use more than one map), but it should provide at least a description of what it does.

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

char *map[50][50];

void remove_from_map(int x, int y)
{
free(map[x][y]);
map[x][y] = NULL;
}

void insert_into_map(int x, int y, char *str)
{
free(map[x][y]);
map[x][y] = strdup(str);
}

const char *get_from_map(int x, int y)
{
return map[x][y];
}

int main()
{
insert_into_map(45, 30, "map[45][30]");
printf("\"%s\"\n", get_from_map(45, 30));
remove_from_map(45, 30);
if (get_from_map(45, 30) != NULL)
{
printf("Universe is broken.\n");
}
}
09 Feb, 2012, JohnnyStarr wrote in the 35th comment:
Votes: 0
@Tyche
Thanks for the gdb example, very helpful.

@Kaz
Thanks for the example as well, I'm sure I'll use it as a reference.

It occurred to me that I don't really need to store strings in the map. I think short int map[50][50] makes more sense. As far as grid characters, I will probably
keep them in a const char* table and enums to corresponding indices:

enum {MP_FOREST, MP_RIVER, MP_MOUNTAIN, MP_LINKHOR, MP_LINKVERT};
const char* glyphs[] = {"#", "~", "^", "-", "|"}; // may have color codes added

// assignment
map[x][y] = MP_FOREST;
map[x][y+1] = MP_LINKVERT;
09 Feb, 2012, Vigud wrote in the 36th comment:
Votes: 0
There's another approach you may want to consider: non-standard library.
http://www.and.org/vstr/comparison
This seems to be popular: bstring.sf.net
09 Feb, 2012, Rarva.Riendf wrote in the 37th comment:
Votes: 0
Or use C++ strings. The 'solutions' to avoid those char* nightmares are numerous. Only thing that matters for the OP is to identify if it is a practical problem, or just an intellectual one.
10 Feb, 2012, Runter wrote in the 38th comment:
Votes: 0
Well, regardless, one should learn about C strings if one wants to be proficient in C.
10 Feb, 2012, drifton wrote in the 39th comment:
Votes: 0
this is more or less my map code from a graphic map program i made

#include <stdio.h>
#define MAP_WIDTH 32
#define MAP_HEIGHT 32

int main()
{
char * map=0;
char value=0;

int offset_y=0;
int offset_x=0;

map = (char *) malloc(MAP_WIDTH * MAP_HEIGHT);
memset(map,0,MAP_WIDTH*MAP_HEIGHT);

for(y = offset_y; y < 8; y++)
{
for(x = offset_x; x < 8; x++)
{
value = map[(x)+ ((y)*MAP_WIDTH)];
select(value)
{
/*0 - 2 boarder pieces */
case 0: printf("+"); break;
case 1: printf("-"); break;
case 2: printf("|"); break;
/*3-9 terain pieces - water, mountain, forest, plains, road,city */
case 3: printf("~");break;
case 4: printf("^");break;
case 5: printf("#");break;
case 6: printf(";");break;
case 7: printf(" ");break;
case 8: printf("*");break;
default: printf("!"); break; /*shouldn't see this*/
}
printf("\n\r"); /* end of the line needs to drop down one */
}
}

free(map);

return 0;
}

void change_tile(int x, int y, char * map, char tile);
{
if(!((x >= 0 && y >= 0 ) && ( x < MAP_WIDTH && y < MAP_HEIGHT)))
{
printf("index (x,y) (%i,%i) is out of range\n\r",x ,y);
}
else
{
memset(map+(x+(y*MAP_WIDTH)), tile,1);
/* you could also probably use this which is more or less what i have above
map[x+(y*MAP_WIDTH)] = tile;
*/
}
}


you use an array index to edit the value of the tile i personally would use an array of structures so more data could be held and referenced instead of having a separate list of map exits you could denote weather the tile has an exit or not and where it would lead to or you could store some kind of resource amount but that would depend on how complex your map needs to be

it wouldn't be to hard to build helper functions that help generate and edit this data.
this is by no means optimized i basically replaced my drawtile function from a tile engine example i wrote for class a long time ago circa 2002 with printf. as is this program should draw a grid of 8x8 '+' but it would be your job to fill in the map data and to load and save it
20.0/39