Pointer problem.

P

Paul

hi, there,

In the following codes, If I change the varible "string "in main()
to char* string=" this is the test string "; the program will
be crashed. can someone tell me why and how to modify the code so that
I can still use char * string? thanks.

================================
#include <stdio.h>

char *Trim(char *string)
{
char *from, *to;
int spaces = 0;



/* skip leading spaces */
for (from = to = string; *from ==' '; ++from);

for (;*from != '\0'; ++from)
{
if (*from != ' ')
{
if (spaces == 1) *to++ = ' ';
spaces = 0;
*to++ = *from;
}
else spaces = 1;
}
*to = '\0';
return string;

}

int main(void)
{
char string[] = " This is a test of the
string trim ";

printf("Before: \"%s\"\n",string);

string=Trim(string);
printf("After: \"%s\"\n",string);

return 0;

}

============================================================
 
A

ajm

Hi Paul,
In the following codes, If I change the varible "string "in main()
to char* string=" this is the test string "; the program will
be crashed. can someone tell me why and how to modify the code so that
I can still use char * string? thanks.

couple of details first - the return type of Trim is a char * but is
assigned to a variable of (incomplete) type char[] which in any event
is
a string literal so I would suggest that you reserve your variable
"string"
for the input and have a separate variable, "trim_string" (of type char
*) for the output. note that a function does not know if it is passed
a char[] or a char * argument but does know what it is supposed to
return.

next a very minor detail: decide how you wish to return the trimmed
string,
do you want to use a second char ** argument and pass your trim_string
variable
by address (&trim_string) or do you want to pass the trim_string back
as the
return value. The former allows you to communicate errors via return
codes but you could also do this by returning a NULL too.

finally since you are creating a new string (trim_string) you will need
to
malloc some space for it (which requires that the caller free it when
it is no longer needed) - otherwise you are probably going to get a seg
fault or bus error etc. The rest of the trim code (def prt copy etc.)
is probably fine as is (have not studied in detail ;)

hth,
ajm.
 
E

Emmanuel Delahaye

Paul a écrit :
hi, there,

In the following codes, If I change the varible "string "in main()
to char* string=" this is the test string "; the program will
be crashed. can someone tell me why and how to modify the code so that
I can still use char * string? thanks.

What about reading the FAQ before posting ?
 
P

pete

Paul said:
hi, there,

In the following codes, If I change the varible "string "in main()
to char* string=" this is the test string "; the program will
be crashed. can someone tell me why

It's undefined behavior to attempt to modify the contents
of an object identified by a string literal.
Modifying most other objects of array type, is OK.
and how to modify the code so that
I can still use char * string? thanks.

char string[] is the right way to do what you want.
char *string is the wrong way to do what you want.
 
F

Flash Gordon

ajm said:
Hi Paul,
In the following codes, If I change the varible "string "in main()
to char* string=" this is the test string "; the program will
be crashed. can someone tell me why and how to modify the code so that
I can still use char * string? thanks.

couple of details first - the return type of Trim is a char * but is
assigned to a variable of (incomplete) type char[] which in any event
is a string literal

You snipped a bit too much context, namely the parts of the code you are
commenting on. Please don't assume that everyone has seen the post you
are replying to. I'll restore the bits in question as by chance I happen
to have it available. The variable you referred to was in the following:

| int main(void)
| {
| char string[] = " This is a test of the
| string trim ";

string here is *not* an incomplete type, nor is it a string literal. The
C compiler completes the type because is it given an initialiser, the
string literal.

So string is an array of exactly the correct size to hold the string
literal *including* the '\0' that terminates the string.

| printf("Before: \"%s\"\n",string);
|
| string=Trim(string);

You are not allowed to assign to arrays.

| printf("After: \"%s\"\n",string);
|
| return 0;
|
| }

> so I would suggest that you reserve your variable
"string"
for the input and have a separate variable, "trim_string" (of type char
*) for the output. note that a function does not know if it is passed
a char[] or a char * argument but does know what it is supposed to
return.

Correct, more or less.
next a very minor detail: decide how you wish to return the trimmed
string,
do you want to use a second char ** argument and pass your trim_string
variable
by address (&trim_string) or do you want to pass the trim_string back
as the
return value. The former allows you to communicate errors via return
codes but you could also do this by returning a NULL too.

You forgot the possibility of modifying the string in place, which
sometimes is an appropriate solution. The problems with modifying the
string in place are:

1) It means you cannot pass a pointer to a string literal, since you are
not allowed to modify string literals (it invokes undefined behaviour
which on some systems shows up as a crash and on others as weird things
happening). This is the reason the OP's program crashed when using "char
*string=" instead of "char string[]=".
2) You cannot enlarge the string.
finally since you are creating a new string (trim_string) you will need
to
malloc some space for it (which requires that the caller free it when
it is no longer needed) - otherwise you are probably going to get a seg
fault or bus error etc. The rest of the trim code (def prt copy etc.)
is probably fine as is (have not studied in detail ;)

One point you missed was that string is a bad name for a variable. At
file scope identifiers starting with str followed by a lower case letter
are reserved if string.h is included, and they are always reserved for
external linkage (even if string.h is not included), so as a matter of
course it is best to just avoid them altogether, including when they are
allowed.
 
N

Nerox

Paul ha escrito:
hi, there,

In the following codes, If I change the varible "string "in main()
to char* string=" this is the test string "; the program will
be crashed. can someone tell me why and how to modify the code so that
I can still use char * string? thanks.

In order to use char *string rather than char string[], you must write:

....

#define NUM 512 /* Any size that is large enough to hold the string */

char *string;
string = (char *) malloc(sizeof(char)* NUM);
strcpy(string," This is a test of the string trim
");

....

If you code in this way:

char *string = " This is a test of the string trim
";
string[3] = 'A';

Modifying the literal string yields an undefined behavior, so anything
can happen (in your case a crash).
 
F

Flash Gordon

Nerox said:
Paul ha escrito:
hi, there,

In the following codes, If I change the varible "string "in main()
to char* string=" this is the test string "; the program will
be crashed. can someone tell me why and how to modify the code so that
I can still use char * string? thanks.


In order to use char *string rather than char string[], you must write:

No you should not. See comments bellow.
...

#define NUM 512 /* Any size that is large enough to hold the string */

char *string;
string = (char *) malloc(sizeof(char)* NUM);

<snip>

Don't cast the return value of malloc, it's not required in C and can
prevent the compiler from producing an otherwise required diagnostic if
you have failed to include stdlib.h, and you have not told the OP to
include it. Also, sizeof char is 1 by *definition* so multiplying by it
is pointless. So with something that is obviously a pointer to char use:
string = malloc(NUM);
Otherwise use
ptr = malloc(NUM * sizeof *ptr);
 

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,170
Messages
2,570,925
Members
47,468
Latest member
Fannie44U3

Latest Threads

Top