Checking whether '\0' exists in the string

K

Kayle

How should we check if the '\0' characters exists in the string as I am
confused that some books mentioned
that we have to check whether we need to make sure that we pass the
'null-terminated-string' to some functions,
such as 'atoi'. (We assume that the string was extracted using an array, not
string literal)

This program shows blank for '\0' for all 3 cases. Why ? And I was trying to
pass some strings formed using an array, without
appending '\0' and it worked. Was there any inconsistencies here?

char *str = "Hello"; // Case1
char str[] = {'H', 'e', 'l', 'l', 'o'}; // Case2
char str[] = {'H', 'e', 'l', 'l', 'o'}; // Case3
int length = strlen(str);
char *p;
int i;

// Testing whether '0' exists in the string
for (p = str, i = 0; i <= length; p++, i++) {
printf("Character %d is: %c\n",i,*p);
}

Anybody can clarify this issue? Thanks
 
A

Artie Gold

Kayle said:
How should we check if the '\0' characters exists in the string as I am
confused that some books mentioned
that we have to check whether we need to make sure that we pass the
'null-terminated-string' to some functions,
such as 'atoi'. (We assume that the string was extracted using an array, not
string literal)

This program shows blank for '\0' for all 3 cases. Why ? And I was trying to
pass some strings formed using an array, without
appending '\0' and it worked. Was there any inconsistencies here?

char *str = "Hello"; // Case1
char str[] = {'H', 'e', 'l', 'l', 'o'}; // Case2
char str[] = {'H', 'e', 'l', 'l', 'o'}; // Case3
int length = strlen(str);
char *p;
int i;

// Testing whether '0' exists in the string
for (p = str, i = 0; i <= length; p++, i++) {
printf("Character %d is: %c\n",i,*p);
}

Anybody can clarify this issue? Thanks

In your example, you've used `strlen' to get the length -- which
returns the number of `char's up to *but not including* the
terminator ('\0').

Case1 is a pointer to the chars 'H', 'e', 'l', 'l', 'o', '\0'.

In Case2 and Case3, you just got (un)lucky.
As an exercise, print out what `length' is after the strlen call. If
it happens to be 5, it's purely happenstance.

HTH,
--ag
 
A

Artie Gold

Artie said:
Kayle said:
How should we check if the '\0' characters exists in the string as I am
confused that some books mentioned
that we have to check whether we need to make sure that we pass the
'null-terminated-string' to some functions,
such as 'atoi'. (We assume that the string was extracted using an
array, not
string literal)

This program shows blank for '\0' for all 3 cases. Why ? And I was
trying to
pass some strings formed using an array, without
appending '\0' and it worked. Was there any inconsistencies here?

char *str = "Hello"; // Case1
char str[] = {'H', 'e', 'l', 'l', 'o'}; // Case2
char str[] = {'H', 'e', 'l', 'l', 'o'}; // Case3
int length = strlen(str);
char *p;
int i;

// Testing whether '0' exists in the string
for (p = str, i = 0; i <= length; p++, i++) {
printf("Character %d is: %c\n",i,*p);
}

Anybody can clarify this issue? Thanks

In your example, you've used `strlen' to get the length -- which returns
the number of `char's up to *but not including* the terminator ('\0').

Case1 is a pointer to the chars 'H', 'e', 'l', 'l', 'o', '\0'.
"is a pointer to char pointing to memory containing the chars..."
In Case2 and Case3, you just got (un)lucky.
BTW - is there a difference?
As an exercise, print out what `length' is after the strlen call. If it
happens to be 5, it's purely happenstance.

HTH,
--ag
--ag
 
I

ipo

Kayle said:
How should we check if the '\0' characters exists in the string as I am
confused that some books mentioned
that we have to check whether we need to make sure that we pass the
'null-terminated-string' to some functions,
such as 'atoi'. (We assume that the string was extracted using an array, not
string literal)

The books are telling you to make sure that the strings you use in a program
are null-terminated. This does not mean that you have to write code to check
for the null terminating character before calling a function such as atoi().
Just make sure that all strings are null-terminated.
This program shows blank for '\0' for all 3 cases. Why ? And I was trying to
pass some strings formed using an array, without
appending '\0' and it worked. Was there any inconsistencies here?

char *str = "Hello"; // Case1
char str[] = {'H', 'e', 'l', 'l', 'o'}; // Case2
char str[] = {'H', 'e', 'l', 'l', 'o'}; // Case3
int length = strlen(str);
char *p;
int i;

Case 1 is already null-terminated. Cases 2 and 3 (which look the same, BTW),
are not necessarely so and therefore you must append '\0' to the arrays
prior to using them in any code that expects null-terminated strings.
// Testing whether '0' exists in the string
for (p = str, i = 0; i <= length; p++, i++) {
printf("Character %d is: %c\n",i,*p);
}

Anybody can clarify this issue? Thanks

Don't you find it interesting to use strlen() so that you can write a loop
to test for '\0' when strlen() itself expects a null-terminated string? You
just got lucky that both strlen() and the loop encountered '\0' somewhere in
the array. There's no guarantee of the same behaviour if you re-run the
program.
 
T

those who know me have no need of my name

in comp.lang.c i read:
How should we check if the '\0' characters exists in the string as I am
confused that some books mentioned that we have to check whether we need
to make sure that we pass the 'null-terminated-string' to some functions,
such as 'atoi'.

it's not a string unless there's a terminating null byte, by definition.
to ensure that an arbitrary sequence of char's is a valid string you need
to know the maximum number of bytes possible in the sequence, then you can
use memchr() to locate if a null byte is present within that space, e.g.,

char s1[] = "Hello"; /* case 1 */
char s2[5] = "Hello"; /* case 2 */
char *s3 = "Hello"; /* case 3 */
char *s4 = {'H','e','l','l','o'}; /* case 4 */

#define validstring(s,l) memchr(s,0,l)

if (validstring(s1, sizeof s1)) puts("s1 is a string");
if (validstring(s2, sizeof s2)) puts("s2 is a string");
if (validstring(s3, 6)) puts("s3 is a string");
if (validstring(s4, 6)) puts("s4 is a string");

in case 1 we have a string literal which is copied into the array, hence s1
contains a string, so the puts will execute.

in case 2 only the first 5 bytes of the string literal are copied into the
array, hence s2 does not contain a string, so the puts will not execute.

in case 3 we have a string literal, hence s3 points to a string, so the
puts will execute.

in case 4 we have a sequence of char's without an explicit null byte, hence
s4 does not point to a string, so the puts will not execute.

notice that for cases 3 and 4 we cannot supply the maximum size using a
simple programmatic means as is done for 1 and 2, because s3 and s4 are
pointers. these are the hard cases, especially if you aren't aware that
they are pointers, as happens when you learn how arrays are passed in a
slightly wrong way.
char str[] = {'H', 'e', 'l', 'l', 'o'}; // Case2
char str[] = {'H', 'e', 'l', 'l', 'o'}; // Case3

what difference do you see between these two?
int length = strlen(str);

undefined behavior when used against your case2 or case3 as neither are
(valid) strings, except by happenstance (hence the u.b.).
 
K

Kayle

ipo said:
The books are telling you to make sure that the strings you use in a program
are null-terminated. This does not mean that you have to write code to check
for the null terminating character before calling a function such as atoi().
Just make sure that all strings are null-terminated.

Thanks for the reply.
I got what you mean, BTW. What I intended to do is to display the null
character to see whether the null
character exist before calling a function like atoi, for example. Althought
it is not required to write the code to
check for the null terminating character, I just need to make sure that the
whole program executes properly with string
terminated with null when I debug it.


This program shows blank for '\0' for all 3 cases. Why ? And I was
trying
to
pass some strings formed using an array, without
appending '\0' and it worked. Was there any inconsistencies here?

char *str = "Hello"; // Case1
char str[] = {'H', 'e', 'l', 'l', 'o'}; // Case2
char str[] = {'H', 'e', 'l', 'l', 'o'}; // Case3
int length = strlen(str);
char *p;
int i;

Case 1 is already null-terminated. Cases 2 and 3 (which look the same, BTW),
are not necessarely so and therefore you must append '\0' to the arrays
prior to using them in any code that expects null-terminated strings.

Sorrry the case 3 should be read as:
char str[] = {'H', 'e', 'l', 'l', 'o', '\0'}

and the result is the same for all 3 cases. and as mentioned previously, the
call strlen to case 2
gave me the result of 5 strangely, and the code compiled successfully. What
is happening??
The call strlen for case 2 should gave me undefined behaviour, but it was
not, even after compiling and
executing it so many times.

Thanks for any further comments
 
G

Glen Herrmannsfeldt

Artie Gold said:
Kayle said:
How should we check if the '\0' characters exists in the string as I am
confused that some books mentioned
that we have to check whether we need to make sure that we pass the
'null-terminated-string' to some functions,
such as 'atoi'. (We assume that the string was extracted using an array, not
string literal)
(snip)
char *str = "Hello"; // Case1
char str[] = {'H', 'e', 'l', 'l', 'o'}; // Case2
char str[] = {'H', 'e', 'l', 'l', 'o'}; // Case3
int length = strlen(str);
char *p;
int i;
(snip)

In your example, you've used `strlen' to get the length -- which
returns the number of `char's up to *but not including* the
terminator ('\0').

Case1 is a pointer to the chars 'H', 'e', 'l', 'l', 'o', '\0'.

In Case2 and Case3, you just got (un)lucky.
As an exercise, print out what `length' is after the strlen call. If
it happens to be 5, it's purely happenstance.

It may not be completely happenstance. The string has an odd length, and
reasonably likely the compiler generates constants and variables starting on
a boundary a multiple of 2, 4, or 8. It might then have to fill in the
extra space. In years past there were some that would write out whatever
happenned to be in the buffer at the time, but not so much anymore. It can
cause security problems, and also it makes comparing object files harder.

Anyway, yes, you can't depend on null termination in case 2 or 3. What is
the difference between 2 and 3, anyway?

-- glen
 
N

Nicholas

Glen Herrmannsfeldt said:
array,
not
string literal)
(snip)
char *str = "Hello"; // Case1
char str[] = {'H', 'e', 'l', 'l', 'o'}; // Case2
char str[] = {'H', 'e', 'l', 'l', 'o'}; // Case3
int length = strlen(str);
char *p;
int i;
(snip)

In your example, you've used `strlen' to get the length -- which
returns the number of `char's up to *but not including* the
terminator ('\0').

Case1 is a pointer to the chars 'H', 'e', 'l', 'l', 'o', '\0'.

In Case2 and Case3, you just got (un)lucky.
As an exercise, print out what `length' is after the strlen call. If
it happens to be 5, it's purely happenstance.

It may not be completely happenstance. The string has an odd length, and
reasonably likely the compiler generates constants and variables starting on
a boundary a multiple of 2, 4, or 8. It might then have to fill in the
extra space. In years past there were some that would write out whatever
happenned to be in the buffer at the time, but not so much anymore. It can
cause security problems, and also it makes comparing object files harder.

Anyway, yes, you can't depend on null termination in case 2 or 3. What is
the difference between 2 and 3, anyway?
The Case 3 should be char str[] = {'H', 'e', 'l', 'l', 'o', '\0'};
I forgot to put the null character.
 
M

Malcolm

Kayle said:
the call strlen to case 2 gave me the result of 5 strangely, and the code
compiled successfully. What is happening??
The compiler isn't intelligent to warn you that you are passing a non-NULL
terminated array to strlen().
strlen is probably implemented as

size_t strlen(const char *str)
{
size_t answer =0;
while(*str)
{
answer++;
str++;
}
return answer;
}

You see that it will simply charge through the memory blindly until it
ahppens to hit a NUL.
The call strlen for case 2 should gave me undefined behaviour, but it
was not, even after compiling and executing it so many times.
undefined behaviour means the program is allowed to do anything, including
giving "correct" results. An apparently correct result is in fact the most
dangerous behaviour of all, since the programmer might submit incorrect code
as correct, only to find it fail at some vital moment.
If you get lucky, you will get an error message, but you can't rely on this.
 
J

Jirka Klaue

those who know me have no need of my name wrote:
....
char *s4 = {'H','e','l','l','o'}; /* case 4 */ ....
#define validstring(s,l) memchr(s,0,l)

if (validstring(s4, 6)) puts("s4 is a string"); ....
in case 4 we have a sequence of char's without an explicit null byte, hence
s4 does not point to a string, so the puts will not execute.

You never know. ;-)
If this compiles at all, it could print anything.

Jirka
 
G

Gordon Burditt

How should we check if the '\0' characters exists in the string as I am
confused that some books mentioned
that we have to check whether we need to make sure that we pass the
'null-terminated-string' to some functions,

Unless you know how big the buffer is, you CANNOT make this check.
If you try, either you (a) find the '\0', or (b) find a '\0' somewhat
after the intended end of the string but still in the buffer, or (c) run
off the end of the buffer, which might crash your program or find a '\0'
outside the buffer.

Gordon L. Burditt
 
A

Artie Gold

Glen said:
Kayle said:
How should we check if the '\0' characters exists in the string as I am
confused that some books mentioned
that we have to check whether we need to make sure that we pass the
'null-terminated-string' to some functions,
such as 'atoi'. (We assume that the string was extracted using an array,
not
string literal)

(snip)

char *str = "Hello"; // Case1
char str[] = {'H', 'e', 'l', 'l', 'o'}; // Case2
char str[] = {'H', 'e', 'l', 'l', 'o'}; // Case3
int length = strlen(str);
char *p;
int i;

(snip)


In your example, you've used `strlen' to get the length -- which
returns the number of `char's up to *but not including* the
terminator ('\0').

Case1 is a pointer to the chars 'H', 'e', 'l', 'l', 'o', '\0'.

In Case2 and Case3, you just got (un)lucky.
As an exercise, print out what `length' is after the strlen call. If
it happens to be 5, it's purely happenstance.


It may not be completely happenstance. The string has an odd length, and
reasonably likely the compiler generates constants and variables starting on
a boundary a multiple of 2, 4, or 8. It might then have to fill in the

Well, *I* know that! ;-) [But I suspect the OP wouldn't -- and at
this point, probably shouldn't.]
extra space. In years past there were some that would write out whatever
happenned to be in the buffer at the time, but not so much anymore. It can
cause security problems, and also it makes comparing object files harder.

Anyway, yes, you can't depend on null termination in case 2 or 3. What is
the difference between 2 and 3, anyway?
OP answered elsethread.
Cheers,
--ag
 
T

those who know me have no need of my name

in comp.lang.c i read:
those who know me have no need of my name wrote:
If this compiles at all,

heh. that was originally (char[]){...} then i chopped the cast so the c99
haters wouldn't whine. i should have checked it more thoroughly. thanks
for catching it. i should just stick with posting c99 and let the whiners
whine.
 
L

Lew Pitcher

Kayle said:
How should we check if the '\0' characters exists in the string as I am
confused that some books mentioned

By definition, a string is an array of characters, terminated by a \0
character. So, by definition, if it is a string then it must have a \0.

I assume that this tautology is not what you are looking for, and instead, you
are looking for some method to determine if an array of char contains a \0,
and thus can be called a string.

If so, then the obvious way would be to inspect each element of the array for
a \0, starting at the [0] element of the array. If you reach the end of the
array without finding a \0, then the array does not represent a string. OTOH,
if you find a \0 character within the array, then the array represents a
string. Simple.


--
Lew Pitcher

Master Codewright and JOAT-in-training
Registered Linux User #112576 (http://counter.li.org/)
Slackware - Because I know what I'm doing.
 
M

MikeyD

How should we check if the '\0' characters exists in the string as I am
confused that some books mentioned
that we have to check whether we need to make sure that we pass the
'null-terminated-string' to some functions,
such as 'atoi'. (We assume that the string was extracted using an array, not
string literal)

This program shows blank for '\0' for all 3 cases. Why ? And I was trying to
pass some strings formed using an array, without
appending '\0' and it worked. Was there any inconsistencies here?

char *str = "Hello"; // Case1
char str[] = {'H', 'e', 'l', 'l', 'o'}; // Case2
char str[] = {'H', 'e', 'l', 'l', 'o'}; // Case3
int length = strlen(str);
char *p;
int i;

// Testing whether '0' exists in the string
for (p = str, i = 0; i <= length; p++, i++) {
printf("Character %d is: %c\n",i,*p);
}

Anybody can clarify this issue? Thanks
If strlen() comes up with the right length for the string, then it must
terminate in \0, so you may as well just use atoi(). You can only really
test if you know the length the string should be, or at least the maximum
length. (Otherwise the string carries on into other memory) Try this way,
you can use if(flag) for your atoi() calls.
#define MAX_LEN 20
//or whatever max size you have
int flag=0;
for(int i=0;i<=MAX_LEN;i++)
flag=flag||str=='\0';
if(flag)
printf("Str terminates before or at %d characters",MAX_LEN);
else
printf("Str is not a valid terminated string")
 

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

Forum statistics

Threads
473,744
Messages
2,569,484
Members
44,903
Latest member
orderPeak8CBDGummies

Latest Threads

Top