472,794 Members | 4,312 Online
Bytes | Software Development & Data Engineering Community
Post Job

Home Posts Topics Members FAQ

Join Bytes to post your question to a community of 472,794 software developers and data experts.

two dimensional arrays passed to functions

I'm trying to pass an array of string to a function without knowing how
many strings I have beforehand.

I've defined one functions as

char * insert(char table[256],int cols, char values[3][256]);

out of deperation because when I defined it as

char * insert(char table[255],int cols, char values)

I keep getting no data passed.

char * insert(char table[256],int cols, char values * [3]);

Gets me only one arguement passed. I thought I used to do this all the
time. In fact, main does this. I've loaded the entire source code I'm
working with onto htto://www.freedom-it.com/clinical.tgz ifd anyone wants
to look. The code is using GTK 2.x and MYSQL 4.0x for anyone interested.

Ruben
Nov 14 '05 #1
6 2640
On Thu, 09 Sep 2004 00:42:57 -0400, Ruben wrote:
htto://www.freedom-it.com/clinical.tgz


Sorry that would be https://www.freedom-it.com/clinical.tgz

Note the s in https
Ruben
Nov 14 '05 #2
On Thu, 09 Sep 2004 00:42:57 -0400, Ruben wrote:
out of deperation because when I defined it as

char * insert(char table[255],int cols, char values)

I keep getting no data passed.


Actually, I originally defined this function as
char * insert(char table[255],int cols, char **values)

Everything I'm reading seems to say I have to define this
as
char * insert(char table[255],int cols, char values[][256])

but main can be defined as int main (int argv, char **argc) without any
problem.

This is driving me crazy because I could sware I did this on SCO
compilers about 8 years ago without any trouble.

Ruben

<<I'm trying to pass an array of string to a function without knowing how
many strings I have beforehand.

I've defined one functions as

char * insert(char table[256],int cols, char values[3][256]);

out of deperation because when I defined it as

char * insert(char table[255],int cols, char values)

I keep getting no data passed.

char * insert(char table[256],int cols, char values * [3]);

Gets me only one arguement passed. I thought I used to do this all the
time. In fact, main does this. I've loaded the entire source code I'm
working with onto https://www.freedom-it.com/clinical.tgz ifd anyone wants
to look. The code is using GTK 2.x and MYSQL 4.0x for anyone interested.

Ruben>>
Nov 14 '05 #3
Ruben <ru***@www2.mrbrklyn.com> wrote:
On Thu, 09 Sep 2004 00:42:57 -0400, Ruben wrote:
out of deperation because when I defined it as

char * insert(char table[255],int cols, char values)

I keep getting no data passed.


Actually, I originally defined this function as
char * insert(char table[255],int cols, char **values)

Everything I'm reading seems to say I have to define this
as
char * insert(char table[255],int cols, char values[][256]) but main can be defined as int main (int argv, char **argc) without any
problem. This is driving me crazy because I could sware I did this on SCO
compilers about 8 years ago without any trouble.


Sorry, but the URL you gave for the code doesn't work. The main
question is: what exactly is it that you want to pass to the
function? From what you write it looks as if in the caller you
have the 'value' array defined as

char values[ N ][ 256 ];

where I don't know N but it doesn't really matter. If that is the case
then the form

char * insert(char table[255],int cols, char values[][256])

looks reasonable. The difference to the way argv is used is comes
from argv not being a 2-dimensional array but a 1-dimensional array
of char pointers. I.e. argv is defined similar to this

char *x[ M ];

Each of the M pointers may point to a different string. And that's not
a 2-dimensional array - it only has room for M char pointers and nothing
more. All the strings pointed to must get their memory independently of
that definition

If you now pass something like argv to a function what the function
gets is a pointer to the first element of this array, i.e. a pointer
to the first pointer - that's why argv can be written as either
"char **argv" or "char *argv[ ]" in the call of main().

On the other hand

char values[ N ][ 256 ];

has room for N strings, each 256 chars long. And it does not get
converted to a pointer to pointer when passed to a function, since
it's not a 1-dimensional array (what the function actually gets can
be treated as a pointer to the first char in the first string, so
you could define the function as

char * insert(char table[255],int cols, char *values)

But that has the obvious drawback that then the compiler has no idea
where the strings start and you have to calculate that all by yourself,
i.e. the start of the n-th string would then be (value + n * 256) if
you start counting at 0.
Regards, Jens
--
\ Jens Thoms Toerring ___ Je***********@physik.fu-berlin.de
\__________________________ http://www.toerring.de
Nov 14 '05 #4
On Thu, 09 Sep 2004 14:32:51 -0400, Jens.Toerring wrote:
Ruben <ru***@www2.mrbrklyn.com> wrote:
On Thu, 09 Sep 2004 00:42:57 -0400, Ruben wrote:
out of deperation because when I defined it as

char * insert(char table[255],int cols, char values)

I keep getting no data passed.


Actually, I originally defined this function as char * insert(char
table[255],int cols, char **values)

Everything I'm reading seems to say I have to define this as char *
insert(char table[255],int cols, char values[][256])

but main can be defined as int main (int argv, char **argc) without any
problem.

This is driving me crazy because I could sware I did this on SCO
compilers about 8 years ago without any trouble.


Sorry, but the URL you gave for the code doesn't work.


Someone else said that you me but it seems to be working now. Covad was
having some troubles over at tellhouse this morning

https://www.freedom-it.com/clinical.tgz is up currently

The main question
is: what exactly is it that you want to pass to the function? From what
you write it looks as if in the caller you have the 'value' array
defined as

char values[ N ][ 256 ];

where I don't know N but it doesn't really matter. If that is the case
then the form

char * insert(char table[255],int cols, char values[][256])

looks reasonable.
But it's not what I originally wanted. I'm quite sure and relooked at
old code on SCO and I used to just assign a char * to the address of the
array and then send it down as a single dimmensional array. This method
is dead appearently.

The difference to the way argv is used is comes from
argv not being a 2-dimensional array but a 1-dimensional array of char
pointers. I.e. argv is defined similar to this

char *x[ M ];
OK

Each of the M pointers may point to a different string.
x is a pointer to an array of chars.

And that's not a
2-dimensional array - it only has room for M char pointers and nothing
more.
But where is it allocated memory for the pointer address?
All the strings pointed to must get their memory independently of
that definition

Yes. I was using strcpy of string literals for that. In my main gtk
program, they are coming from editable text objects.

If you now pass something like argv to a function what the function gets
is a pointer to the first element of this array, i.e. a pointer to the
first pointer - that's why argv can be written as either "char **argv"
or "char *argv[ ]" in the call of main().

On the other hand

char values[ N ][ 256 ];
has room for N strings, each 256 chars long. And it does not get
converted to a pointer to pointer when passed to a function, since it's
not a 1-dimensional array (what the function actually gets can be
treated as a pointer to the first char in the first string, so you could
define the function as

char * insert(char table[255],int cols, char *values)
I thought I tried this variation and it failed.
I'll give it another run.


But that has the obvious drawback that then the compiler has no idea
where the strings start and you have to calculate that all by yourself,
i.e. the start of the n-th string would then be (value + n * 256) if you
start counting at 0.
Regards, Jens
Thanks

Ruben
--
\ Jens Thoms Toerring ___ Je***********@physik.fu-berlin.de
\__________________________ http://www.toerring.de

Nov 14 '05 #5
Ruben <ru***@www2.mrbrklyn.com> wrote:
On Thu, 09 Sep 2004 14:32:51 -0400, Jens.Toerring wrote:
Sorry, but the URL you gave for the code doesn't work.
Someone else said that you me but it seems to be working now. Covad was
having some troubles over at tellhouse this morning
https://www.freedom-it.com/clinical.tgz is up currently
Yep, got it now.
The main question
is: what exactly is it that you want to pass to the function? From what
you write it looks as if in the caller you have the 'value' array
defined as

char values[ N ][ 256 ];

where I don't know N but it doesn't really matter. If that is the case
then the form

char * insert(char table[255],int cols, char values[][256])

looks reasonable. But it's not what I originally wanted. I'm quite sure and relooked at
old code on SCO and I used to just assign a char * to the address of the
array and then send it down as a single dimmensional array. This method
is dead appearently.
What exactly did you want? Please show a bit of real code, just describing
it in words tends to be too prone to misunderstandings.
The difference to the way argv is used is comes from
argv not being a 2-dimensional array but a 1-dimensional array of char
pointers. I.e. argv is defined similar to this

char *x[ M ]; OK Each of the M pointers may point to a different string. x is a pointer to an array of chars.
No, x is an array of char pointers. Only if x is used in value context,
i.e. it's treated as if it would have a value, like for example when
used in a function call, it gets converted in this context (it "decays
to" as it's often called, see also <http://web.torek.net/torek/c/pa.html>)
to a pointer to the first element of this array, i.e. a pointer to the
first char pointer - that's what the called function sees of it if it
gets called like "f( x );".
And that's not a
2-dimensional array - it only has room for M char pointers and nothing
more. But where is it allocated memory for the pointer address?
Which pointer address?
All the strings pointed to must get their memory independently of
that definition Yes. I was using strcpy of string literals for that. In my main gtk
program, they are coming from editable text objects.
Yes, but you're not working with an array of char pointers (like argv
is one) but with a two-dimensional array of chars (and that's why you
need to copy the strings and not just assign pointers to them).
If you now pass something like argv to a function what the function gets
is a pointer to the first element of this array, i.e. a pointer to the
first pointer - that's why argv can be written as either "char **argv"
or "char *argv[ ]" in the call of main().

On the other hand

char values[ N ][ 256 ];

has room for N strings, each 256 chars long. And it does not get
converted to a pointer to pointer when passed to a function, since it's
not a 1-dimensional array (what the function actually gets can be
treated as a pointer to the first char in the first string, so you could
define the function as

char * insert(char table[255],int cols, char *values)

I thought I tried this variation and it failed.
I'll give it another run.


Since in the caller you have

char *error;
char table[ ] = "patient";
char cols[ 3 ][ 256 ] = { { '\0' }, { '\0' }, { '\0' } };

strcpy( cols[ 0 ], patient.first );
strcpy( cols[ 1 ], patient.last );
strcpy( cols[ 2 ], patient.mrn );
error = insert( table, 3, cols );

the correct way to define the function, as far as I can see would be

char *insert( char table[ ], int cols, char values[ ][ 256 ] )

or

char *insert( char *table, int cols, char values[ ][ 256 ] )

(Please note that there isn't a 3 as the first dimension for
'values' here since it looks like you want to be able to get the
function to work with an unspecified number of strings, otherwise
you wouldn't have to pass the number if strings in the 'cols'
variable to the function. And there's also no explicit size for
the length of 'table' since you don't know in advance, it's definitely
not 255. Finally, in your insert_patient() function you use the type
'gchar' for 'table' and '*error' but your insert() function expects
and returns 'char', which doesn't look right.)

Since you don't seem to change neither 'table' nor any of the strings
from 'values' within the insert() function it might make sense to
make that clear by using

char *insert( const char *table, int cols, const char values[ ][ 256 ] )

And if this will stay that way (i.e. none of the strings is ever going
to be changged from within insert()) you could even get rid of copying
all that strings from the 'patient' structure to the 'cols' matrix.
You could use an array of char pointers here and just do

char *error;
char *table = "patient";
char *cols[ ] = { patient.first, patient.last, patient,mrn };

error = insert( table, sizeof cols / sizeof *cols, cols );

Then you would have to define the insert() function as

char *insert( const char *table, int cols, const char *cols[ ] );

i.e. use the same method by which argv is passed to main(). In that
case the 'cols' in insert() would be an array of char pointers, each
pointing to a string (you're not supposed to modify).

BTW, your insert() function is badly leaking memory - you call malloc()
twice there without ever freeing the memory you got. And, of course,
you should check the return value of malloc() and not blindly assume
that it did succeed. Actually, the 'value' array, for which you also
allocate memory is never used at all. Moreover, this part

strcpy( query,"INSERT INTO " );
strcat( query, table );
strcat( query, " VALUES (NULL,'" );
str_length = strlen( query );
end = query + str_length;
str_length = strlen( query );
end = query + str_length;

looks strange - the two last lines look wrong because they make 'end'
point way beyond the end of the 'query' string. Actually, you could
do all you need to do in a single line, i.e.

end = query + sprintf( query, "INSERT INTO %s VALUES (NULL,'", table );

Also the following code won't work correctly:

for ( i = 0; i < cols; i++ )
{
end += mysql_real_escape_string( clinical_db, end, values[ i ],
strlen( values[ i ] ) );
*end++ = '\'';
*end++ = ',';
*end++ = '\'';
}

str_length = strlen( end ) - 2;
end[ str_length ] = ')';
str_length++;
end[ str_length ] = '\0';

If you get out of that loop, 'end' doesn't point to a '\0' terminated
string, so applying strlen() to it won't work. All you actually need
here is

*( end - 2 ) = ')';
*( end - 1 ) = '\0';

Regards, Jens
--
\ Jens Thoms Toerring ___ Je***********@physik.fu-berlin.de
\__________________________ http://www.toerring.de
Nov 14 '05 #6


Ruben wrote:
On Thu, 09 Sep 2004 00:42:57 -0400, Ruben wrote:

out of deperation because when I defined it as

char * insert(char table[255],int cols, char values)

I keep getting no data passed.

Actually, I originally defined this function as
char * insert(char table[255],int cols, char **values)

Everything I'm reading seems to say I have to define this
as
char * insert(char table[255],int cols, char values[][256])

but main can be defined as int main (int argv, char **argc) without any
problem.


Do you have a fixed array or do you have dynamic allocations?

I tend to enclose the array and the number of elements in a struct
and dynamically insert strings into the array. You can allocate 1d with
the char buffer being fixed, i.e. 256, or you can allocate 2d.

The 1d struct:
struct STRINGARR
{
char (*String)[256];
size_t numelements;
};

The 2d struct:
struct STRINGARR
{
char **String;
size_t numelements;
};

The prototype for the insert function would be:
char *insert(struct STRINGARR *array, const char *newstring);

Here is an example of the 1d version:

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

#define STR_SZ 64

typedef struct STRINGARR
{
char (*String)[STR_SZ];
size_t numstrings;
} STRINGARR;
/* Prototypes */
char *InsertSTRINGARR(STRINGARR *p, const char *s);
void PrintSTRINGARR(const STRINGARR *p);
void FreeSTRINGARR(STRINGARR *p);

int main(void)
{
STRINGARR presidents = {NULL}; /* Neccessary */

InsertSTRINGARR(&presidents,"George Washington");
InsertSTRINGARR(&presidents,"Abe Lincoln");
InsertSTRINGARR(&presidents,"Bill Clinton");
InsertSTRINGARR(&presidents,"George Bush");
puts("The presidents in the string array are:");
PrintSTRINGARR(&presidents);
FreeSTRINGARR(&presidents);
return 0;
}

char *InsertSTRINGARR(STRINGARR *p, const char *s)
{
char (*tmp)[STR_SZ];

tmp = realloc(p->String,(sizeof *tmp)*(p->numstrings+1));
if(!tmp) return NULL;
p->String = tmp;
strncpy(p->String[p->numstrings],s,STR_SZ);
p->String[p->numstrings][STR_SZ-1] = '\0';
return p->String[p->numstrings++];
}

void PrintSTRINGARR(const STRINGARR *p)
{
size_t i;

for(i = 0; i < p->numstrings; i++)
puts(p->String[i]);
return;
}

void FreeSTRINGARR(STRINGARR *p)
{
free(p->String);
p->String = NULL;
p->numstrings = 0;
return;
}

--
Al Bowers
Tampa, Fl USA
mailto: xa******@myrapidsys.com (remove the x to send email)
http://www.geocities.com/abowers822/

Nov 14 '05 #7

This thread has been closed and replies have been disabled. Please start a new discussion.

Similar topics

2
by: ip4ram | last post by:
I used to work with C and have a set of libraries which allocate multi-dimensional arrays(2 and 3) with single malloc call. data_type **myarray =...
1
by: seemanta dutta | last post by:
greetings C gurus, I would be grateful if I could know the answers to 2 questions: 1. I want to know how to pass a 2-dimensional array to a function, say foo() and what will be its prototype...
9
by: Luke Wu | last post by:
Hello, I'm having some problems understanding 2 dimensional arrays. My problem relates to the following code: #include <stdio.h> #define M 3 #define N 3
11
by: truckaxle | last post by:
I am trying to pass a slice from a larger 2-dimensional array to a function that will work on a smaller region of the array space. The code below is a distillation of what I am trying to...
22
by: spam.noam | last post by:
Hello, I discovered that I needed a small change to the Python grammar. I would like to hear what you think about it. In two lines: Currently, the expression "x" is a syntax error. I suggest...
3
by: ZMan | last post by:
The following code won't compile with gcc version 3.4.2 (mingw-special). How come? Error: cannot convert `char (*)' to `char**' /**********************************************************/...
8
by: per9000 | last post by:
Hi all, I have a two-dimensional array of data, f.x int's. We can imagine that the array is "really large". Now I want the data in it and store this in a one-dimensional array. The obvious...
272
by: Peter Olcott | last post by:
http://groups.google.com/group/comp.lang.c++/msg/a9092f0f6c9bf13a I think that the operator() member function does not work correctly, does anyone else know how to make a template for making two...
152
by: vippstar | last post by:
The subject might be misleading. Regardless, is this code valid: #include <stdio.h> void f(double *p, size_t size) { while(size--) printf("%f\n", *p++); } int main(void) { double array = { {...
0
linyimin
by: linyimin | last post by:
Spring Startup Analyzer generates an interactive Spring application startup report that lets you understand what contributes to the application startup time and helps to optimize it. Support for...
0
by: kcodez | last post by:
As a H5 game development enthusiast, I recently wrote a very interesting little game - Toy Claw ((http://claw.kjeek.com/))。Here I will summarize and share the development experience here, and hope it...
2
isladogs
by: isladogs | last post by:
The next Access Europe meeting will be on Wednesday 6 Sept 2023 starting at 18:00 UK time (6PM UTC+1) and finishing at about 19:15 (7.15PM) The start time is equivalent to 19:00 (7PM) in Central...
0
by: Taofi | last post by:
I try to insert a new record but the error message says the number of query names and destination fields are not the same This are my field names ID, Budgeted, Actual, Status and Differences ...
14
DJRhino1175
by: DJRhino1175 | last post by:
When I run this code I get an error, its Run-time error# 424 Object required...This is my first attempt at doing something like this. I test the entire code and it worked until I added this - If...
0
by: Rina0 | last post by:
I am looking for a Python code to find the longest common subsequence of two strings. I found this blog post that describes the length of longest common subsequence problem and provides a solution in...
5
by: DJRhino | last post by:
Private Sub CboDrawingID_BeforeUpdate(Cancel As Integer) If = 310029923 Or 310030138 Or 310030152 Or 310030346 Or 310030348 Or _ 310030356 Or 310030359 Or 310030362 Or...
0
by: lllomh | last post by:
Define the method first this.state = { buttonBackgroundColor: 'green', isBlinking: false, // A new status is added to identify whether the button is blinking or not } autoStart=()=>{
0
by: lllomh | last post by:
How does React native implement an English player?

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.