Having issues trying to copy an array

C

Chad

I'm want
static char *output[BUFF];

to hold the modified string "tel chad"

However, when I debug it,
static char *output[BUFF]
holds the ascii value of the strng, and not the string itself.

Here is what I have. I know gets(), strcat strcpy() shouldn't be used.
I just wrote the program to isolate the problem I'm having.

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

#define BUFF 20

int main(void) {
char name[BUFF];
static char *output[BUFF];
int count = 2;

char tel[] = "tel ";
char *msg_list[] = {" apple", " orange", " grape" };

printf("Enter the target persons username \n");
gets(name);

/* tel = "tel chad"*/
strcat(tel,name);
printf("%s \n", tel);

strcpy(&output[1], tel);

/*strcat(tel,msg_list[1]);*/
/* printf("%s \n", output[1]);*/

return 0;
}
 
B

Bill Pursell

Chad said:
I'm want
static char *output[BUFF];

to hold the modified string "tel chad"

Since output is an array of char *, that
will be difficult.
However, when I debug it,
static char *output[BUFF]
holds the ascii value of the strng, and not the string itself.

Huh?

int main(void) {
char name[BUFF];
char tel[] = "tel ";
strcat(tel,name);

This doesn't do what you think it does. You have
declared tel to be an array of size 5 ('t', 'e', 'l', ' ', '\0')
and you are now writing data onto the stack beyond
the allocated area. (ie, you are stomping on other
variables.) You could instead do:
char tel[BUFF];
snprintf(tel, BUFF, "tel %s", name);
 
F

Flash Gordon

Chad said:
I'm want
static char *output[BUFF];

to hold the modified string "tel chad"

However, when I debug it,
static char *output[BUFF]
holds the ascii value of the strng, and not the string itself.

I've got no idea what you mean by this, but a quick scan of the code
shows there are lots of problems I can point out.
Here is what I have. I know gets(), strcat strcpy() shouldn't be used.

Nothing wrong with using strcat or strcpy when you *know* there will be
enough space. However, you are correct about not using gets.
I just wrote the program to isolate the problem I'm having.

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

You are going to by using string functions so you should also have
#include <string.h>

Had you included that line your compiler would have given you at least
one complaint which might have helped you.
#define BUFF 20

int main(void) {
char name[BUFF];
static char *output[BUFF];
int count = 2;

char tel[] = "tel ";

Make this
char tel[100 /* or some other big number */] = "tel ";
Obviously, for a real program, you would have to do better than a magic
number of 100.
char *msg_list[] = {" apple", " orange", " grape" };

printf("Enter the target persons username \n");
gets(name);

/* tel = "tel chad"*/
strcat(tel,name);

OK, here is your next problem. You made tel *only* large enough for the
sting "tel " rather than large enough for the combined sting.
printf("%s \n", tel);

You could use
puts(tel);
strcpy(&output[1], tel);

Ouch. This is wrong for several reasons. So wrong that had you included
string.h your compiler would have been required to complain at you.
output[1] is a *pointer* to char so &output[1] is a pointer to pointer
to char which is clearly wrong. So closer to what you want out be just
plain output[1]. However, output[1] also has a problem, it is a pointer
to char but you have not pointed it at somewhere for the string to be
stored! So even after removing the & to make the program compiler it
will still be wrong. Perhaps you want to use malloc to allocate some
space? Or maybe you wanted an array of arrays of char? You might have
wanted output[1]=tel but I doubt it since I assume in your real code tel
would take on different values which you want to hang off output.
/*strcat(tel,msg_list[1]);*/
/* printf("%s \n", output[1]);*/

return 0;
}
 
C

CBFalconer

Chad said:
I'm want
static char *output[BUFF];

to hold the modified string "tel chad"

However, when I debug it,
static char *output[BUFF]
holds the ascii value of the strng, and not the string itself.

Here is what I have. I know gets(), strcat strcpy() shouldn't be used.
I just wrote the program to isolate the problem I'm having.

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

#define BUFF 20

int main(void) {
char name[BUFF];
static char *output[BUFF];
int count = 2;

char tel[] = "tel ";
char *msg_list[] = {" apple", " orange", " grape" };

printf("Enter the target persons username \n");
gets(name);

/* tel = "tel chad"*/
strcat(tel,name);
printf("%s \n", tel);

strcpy(&output[1], tel);

/*strcat(tel,msg_list[1]);*/
/* printf("%s \n", output[1]);*/

return 0;
}

output is an array of BUFF pointers to char, none of which have
been initialized. In addition the thing does not even compile
cleanly:

[1] c:\c\junk>cc junk.c
junk.c: In function `main':
junk.c:12: warning: initialization discards qualifiers from pointer
target type
junk.c:12: warning: initialization discards qualifiers from pointer
target type
junk.c:12: warning: initialization discards qualifiers from pointer
target type
junk.c:18: warning: implicit declaration of function `strcat'
junk.c:21: warning: implicit declaration of function `strcpy'
junk.c:21: warning: passing arg 1 of `strcpy' from incompatible
pointer type
junk.c:9: warning: unused variable `count'
junk.c:12: warning: unused variable `msg_list'


--
"The power of the Executive to cast a man into prison without
formulating any charge known to the law, and particularly to
deny him the judgement of his peers, is in the highest degree
odious and is the foundation of all totalitarian government
whether Nazi or Communist." -- W. Churchill, Nov 21, 1943
 
B

Barry Schwarz

I'm want
static char *output[BUFF];

to hold the modified string "tel chad"

If you want an array to hold character data, make it an array of char,
not an array of char*.
However, when I debug it,
static char *output[BUFF]
holds the ascii value of the strng, and not the string itself.

Here is what I have. I know gets(), strcat strcpy() shouldn't be used.
I just wrote the program to isolate the problem I'm having.

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

You are missing string.h for the string functions. Didn't your
compiler complain about that when you called the functions?
#define BUFF 20

int main(void) {
char name[BUFF];
static char *output[BUFF];

output is an array of pointers. Each pointer in the array is
initialized to NULL.
int count = 2;

char tel[] = "tel ";

tel is an array. How many elements does it have?
char *msg_list[] = {" apple", " orange", " grape" };

printf("Enter the target persons username \n");
gets(name);

/* tel = "tel chad"*/
strcat(tel,name);

tel is the target of this operation and name is the source. Into
which elements of tel will the data from name go? Do these elements
exist? The technical term for attempting to store data in a
non-existent object is "undefined behavior".
printf("%s \n", tel);

strcpy(&output[1], tel);

&output[1] is the address of the second pointer in the array. You are
overlaying the current value of this pointer (which is still NULL)
with the **character** data contained in tel. It is extremely
unlikely that this character data will be valid when interpreted as a
pointer.

Additionally, your compiler should have generated a diagnostic for
this code. output[1] has type char*. &output[1] has type char**.
There is no implicit conversion between these types. If you did
receive a diagnostic, why did you ignore it? If not, you need to up
the warning level on you compiler.

If you want output[1] to point to the data, you should initialize it
to point an area of memory (either an array or an allocated block)
large enough to hold the result of this operation. And then use the
value output[1] (without the &) as the first argument.

Which raises the question of why output is an array of pointers at all
since you only use one pointer in the array.
/*strcat(tel,msg_list[1]);*/
/* printf("%s \n", output[1]);*/

At this point, output[1] is a pointer that does not contain a valid
address. As you noted, it contains your data, not the address of the
data, for the reason explained above.
return 0;
}


Remove del for email
 
B

Barry Schwarz

Chad said:
snip

int main(void) {
char name[BUFF];
static char *output[BUFF];
int count = 2; snip
}

output is an array of BUFF pointers to char, none of which have
been initialized. In addition the thing does not even compile
cleanly:
output is declared static so each element is initialized to NULL.


Remove del for email
 
C

CBFalconer

Tom said:
Chad wrote:
.... snip ...
printf("Enter the target persons username \n");
gets(name);

Newbs use gets. Use fgets instead.
/* tel = "tel chad"*/
strcat(tel,name);

strcat is for the weak. Use strncat
strcpy(&output[1], tel);

strncpy....

Use ggets, strlcat, and strlcpy. All safe, all available at:

<http://cbfalconer.home.att.net/download/>

in portable standard code, public domain (no restrictions).

--
"The power of the Executive to cast a man into prison without
formulating any charge known to the law, and particularly to
deny him the judgement of his peers, is in the highest degree
odious and is the foundation of all totalitarian government
whether Nazi or Communist." -- W. Churchill, Nov 21, 1943
 
C

CBFalconer

Barry said:
CBFalconer said:
Chad said:
snip

int main(void) {
char name[BUFF];
static char *output[BUFF];
int count = 2; snip
}

output is an array of BUFF pointers to char, none of which have
been initialized. In addition the thing does not even compile
cleanly:
output is declared static so each element is initialized to NULL.

No they aren't. They are initialized to all bits zero, which is
NOT the same thing.

--
"The power of the Executive to cast a man into prison without
formulating any charge known to the law, and particularly to
deny him the judgement of his peers, is in the highest degree
odious and is the foundation of all totalitarian government
whether Nazi or Communist." -- W. Churchill, Nov 21, 1943
 
T

Tim Woodall

Barry said:
CBFalconer said:
Chad wrote:
snip

int main(void) {
char name[BUFF];
static char *output[BUFF];
int count = 2; snip
}

output is an array of BUFF pointers to char, none of which have
been initialized. In addition the thing does not even compile
cleanly:
output is declared static so each element is initialized to NULL.

No they aren't. They are initialized to all bits zero, which is
NOT the same thing.
6.7.8 Initialization

#10 ... If an object that has static storage duration is not initialized
explicitly then:

-- if it has pointer type, it is initialized to a null pointer.


Tim.
 
K

Keith Thompson

CBFalconer said:
Barry said:
CBFalconer said:
Chad wrote:
snip

int main(void) {
char name[BUFF];
static char *output[BUFF];
int count = 2; snip
}

output is an array of BUFF pointers to char, none of which have
been initialized. In addition the thing does not even compile
cleanly:
output is declared static so each element is initialized to NULL.

No they aren't. They are initialized to all bits zero, which is
NOT the same thing.

No, they're initialized to null pointers, however null pointers happen
to be represented.

C99 6.7.8p10:

If an object that has automatic storage duration is not
initialized explicitly, its value is indeterminate. If an object
that has static storage duration is not initialized explicitly,
then:

-- if it has pointer type, it is initialized to a null pointer;

-- if it has arithmetic type, it is initialized to (positive or
unsigned) zero;

-- if it is an aggregate, every member is initialized
(recursively) according to these rules;

-- if it is a union, the first named member is initialized
(recursively) according to these rules.
 
C

CBFalconer

Tim said:
CBFalconer said:
Barry said:
Chad wrote:

snip

int main(void) {
char name[BUFF];
static char *output[BUFF];
int count = 2;
snip
}

output is an array of BUFF pointers to char, none of which have
been initialized. In addition the thing does not even compile
cleanly:

output is declared static so each element is initialized to NULL.

No they aren't. They are initialized to all bits zero, which is
NOT the same thing.
6.7.8 Initialization

#10 ... If an object that has static storage duration is not initialized
explicitly then:

-- if it has pointer type, it is initialized to a null pointer.

Woops, you may be right here. However, output is not a pointer
type, it is an array type. That provision may not apply, and I
will wait for others to cite C & V.
 
P

pete

Chad said:
I'm want
static char *output[BUFF];

to hold the modified string "tel chad"

However, when I debug it,
static char *output[BUFF]
holds the ascii value of the strng, and not the string itself.

Here is what I have. I know gets(), strcat strcpy() shouldn't be used.
I just wrote the program to isolate the problem I'm having.

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

#define BUFF 20

int main(void) {
char name[BUFF];
static char *output[BUFF];
int count = 2;

char tel[] = "tel ";
char *msg_list[] = {" apple", " orange", " grape" };

printf("Enter the target persons username \n");
gets(name);

/* tel = "tel chad"*/
strcat(tel,name);
printf("%s \n", tel);

strcpy(&output[1], tel);

/*strcat(tel,msg_list[1]);*/
/* printf("%s \n", output[1]);*/

return 0;
}

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

#define BUFF 20
#define str(x) # x
#define xstr(x) str(x)

int main(void)
{
int rc;
char name[BUFF + 1];
static char *output[BUFF + 1];
char *msg_list[] = {" apple", " orange", " grape" };
char tel[sizeof "tel " + BUFF + sizeof " orange"] = "tel ";

puts("Enter the target persons username:");
rc = fscanf(stdin, "%" xstr(BUFF) "[^\n]%*[^\n]", name);
if (!feof(stdin)) {
getchar();
}
if (rc == 0) {
*name = '\0';
}
if (rc == EOF) {
*name = '\0';
puts("rc == EOF");
}
strcat(tel, name);
puts(tel);
output[1] = tel;
strcat(tel, msg_list[1]);
puts(output[1]);
return 0;
}
 
P

pete

pete said:
output[1] = tel;
strcat(tel, msg_list[1]);
puts(output[1]);
return 0;
}

This ending might be more relevant to the topic of copying arrays:

#include <stdlib.h>

output[1] = malloc(strlen(tel) + 1);
if (output[1] == NULL) {
puts("output[1] == NULL");
exit(EXIT_FAILURE);
}
strcpy(output[1], tel);
strcat(tel, msg_list[1]);
puts(output[1]);
free(output[1]);
puts(tel);
return 0;
}
 
C

Clark S. Cox III

CBFalconer said:
Tim said:
CBFalconer said:
Barry Schwarz wrote:
Chad wrote:
snip
int main(void) {
char name[BUFF];
static char *output[BUFF];
int count = 2;
snip
}
output is an array of BUFF pointers to char, none of which have
been initialized. In addition the thing does not even compile
cleanly:

output is declared static so each element is initialized to NULL.
No they aren't. They are initialized to all bits zero, which is
NOT the same thing.
6.7.8 Initialization

#10 ... If an object that has static storage duration is not initialized
explicitly then:

-- if it has pointer type, it is initialized to a null pointer.

Woops, you may be right here. However, output is not a pointer
type, it is an array type. That provision may not apply, and I
will wait for others to cite C & V.

Two lines down:
—if it is an aggregate, every member is initialized (recursively)
according to these rules;
 
K

Keith Thompson

CBFalconer said:
Woops, you may be right here. However, output is not a pointer
type, it is an array type. That provision may not apply, and I
will wait for others to cite C & V.

I already did. C99 6.7.8p10.
 
J

Jack Klein

I'm want
static char *output[BUFF];

to hold the modified string "tel chad"

However, when I debug it,
static char *output[BUFF]
holds the ascii value of the strng, and not the string itself.

What do you mean by the ASCII (the proper capitalization of the
acronym) value and not the string itself?
Here is what I have. I know gets(), strcat strcpy() shouldn't be used.
I just wrote the program to isolate the problem I'm having.

Your code is so confusing that I am not sure what you are really
trying to do. I'll make some comments, ignoring the functions you
mentioned above.
#include <stdio.h>
#include <stdlib.h>

Need to add:

#include <string.h>

....for prototypes of strcat(), strcpy(), and strlen(), which I suggest
you add.
#define BUFF 20

int main(void) {
char name[BUFF];

This is an array 20 chars.
static char *output[BUFF];

This is an array of 20 POINTERS TO CHAR. It is for holding POINTERS
TO CHAR, not for holding actual chars. They are not initialized,
which means they don't actually point to any characters that you have
the right to access.
int count = 2;

char tel[] = "tel ";

Here you define "tel" as an array of 5 chars, the 4 that you typed and
the '\0' that the compiler automatically adds for you at the end. This
array only has room for 5 characters. You are not allowed to write or
copy any extra characters to it.
char *msg_list[] = {" apple", " orange", " grape" };

printf("Enter the target persons username \n");
gets(name);

/* tel = "tel chad"*/
strcat(tel,name);

Here's your first problem right here. You are trying to add
characters beyond the end of the array. That is undefined behavior,
don't do that. If you want to do that, change the definition to:

char tel [16 /* or more */] = "tel ";

....now the "tel" array has room to add "chad" and " orange" (the
longest of your string literals). But of course, if your input string
from the user is longer, you would need a longer array for "tel".
printf("%s \n", tel);

strcpy(&output[1], tel);

Your compiler should not accept this code, but perhaps it does because
you haven't included <string.h> with a prototype for strcpy(). The
first parameter to strcpy() is char *, but the type of "&output [1]"
is char **.

output [1] is an uninitialized pointer to char. It doesn't really
point to anything. If you want to put something into the memory it
points to, you have to give it some valid memory to point to first.
For example:

output [1] = malloc(strlen(tel) + 1);
if (NULL != output [1])
{
strcpy(output [1], tel);
}

....except of course you want to do this after you have finished
building the string in tel, that is after the strcat() to the end of
tel, after making sure tel is big enough.
/*strcat(tel,msg_list[1]);*/
/* printf("%s \n", output[1]);*/

return 0;
}
 
K

Keith Thompson

Jack Klein said:
comp.lang.c: [...]
static char *output[BUFF];

This is an array of 20 POINTERS TO CHAR. It is for holding POINTERS
TO CHAR, not for holding actual chars. They are not initialized,
which means they don't actually point to any characters that you have
the right to access.
[...]

No, because it's declared as static, the elements of the array are all
initlalized to null pointers. (Of course, they still don't point to
any characters that you have the right to access.)
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
474,432
Messages
2,571,680
Members
48,796
Latest member
Greg L.

Latest Threads

Top