[comp.lang.c] A question

m_belanger@mosaic.dec.com (08/17/89)

In message # <1586@sunset.MATH.UCLA.EDU> Tony writes:

>I seemed to have run into a strange problem in C that I can't quite 
>figure out.

>I'm just trying to convert a time value stored in a long integer 
>in the form 111753 into a more presentable format 11:17:53.

> ... (removed)

>In other words strcpy seems to be working fine but strncpy is doing 
>something bizzare, or is it the way I'm strncpy'ing? 

STRNCPY( d, s, n ) copies EXACTLY n bytes from s to d which doesn't place a
NULL character after the nth byte.  When the STRNCAT routineis called it
appends the concatenated string at the end of the initial line.

Try clearing the string using a MEMSET before creating the next string.

Moe Belanger

ping@cubmol.BIO.COLUMBIA.EDU (Shiping Zhang) (08/17/89)

In article <1586@sunset.MATH.UCLA.EDU> tony@MATH.UCLA.EDU () writes:
>Hello netland:
>
>I seemed to have run into a strange problem in C that I can't quite 
>figure out.
>
>I'm just trying to convert a time value stored in a long integer 
>in the form 111753 into a more presentable format 11:17:53.
>
>The variables were declared as follows:
>
>	long        call_time ;
>	char        str_time[21],   local_str[21] ;
>
>In a while loop I got the data and did the following:
>
>	sprintf (local_str,"%06ld",call_time) ;
>	strncpy (str_time,local_str,2) ;
>	strcat  (str_time,":") ;
>	strncat (str_time,&local_str[2],2) ;
>	strcat  (str_time,":") ;
>	strncat (str_time,&local_str[4],2) ;
>	str_time[8]='\0' ;
>
>	fprintf (fp,"%s time = %06ld local_str = %s str_time = %s\n",
>			 	str_date,call_time,local_str,str_time) ;
>
Add the following line after strncpy() will fix the problem:

        str_time[2]='\0';

strcat and strncat append a copy of the second argument to the END of
the first argument, that means the appending begins at the NULL
character. strncpy() does not null-terminate str_time here
because the length of local_str is longer than 2. strncpy worked ok for
the first time because str_time was initiated to null for all
its members. But after the first round of the loop, str_time is filled
with non-null characters upto the 9th position WHERE strcat() and
strncat always begin appending. Then str_time[8]='\0' simply
cuts off what they have appended. That is why only the first two 
characters are changed.

-ping

cpcahil@virtech.UUCP (Conor P. Cahill) (08/17/89)

In article <1586@sunset.MATH.UCLA.EDU>, tony@sonia.math.ucla.edu writes:
> 
> 	sprintf (local_str,"%06ld",call_time) ;
> 	strncpy (str_time,local_str,2) ;
> 	strcat  (str_time,":") ;
> 	strncat (str_time,&local_str[2],2) ;
> 	strcat  (str_time,":") ;
> 	strncat (str_time,&local_str[4],2) ;

The problem is that you are doing a strncpy followed by a strcat().  The
strncpy() does not place a null terminator on the target string if the 
source string contains n characters.  Hence the second time through this
code (and all further times) the strcats are applied to the end of 
the string which is then chopped off with:

> 	str_time[8]='\0' ;

This is why the first digit pair is always correct, while the rest of 
the data gets lost.

Solution:
	1. Place a null in str_time[2] after the strncpy().
	2. Change the strncpy()s and strcats()s to a single sprintf as
	   follows:
		sprintf(str_time, "%2s:%2s:%2s" local_str, local_str+2,
						local_str+4);

As a side issue, doing muliple strcat() gets more and more ineffecient because
for each strcat() a full search through each byte of the target string (looking
for a null) is done.

As another side issue,  strncpy() has another effect in that if the source
string is less than n characters, it fills in nulls up to n character positions.

ping@cubmol.BIO.COLUMBIA.EDU (Shiping Zhang) (08/17/89)

In article <1025@virtech.UUCP> cpcahil@virtech.UUCP (Conor P. Cahill) writes:
>
>Solution:
>	1. Place a null in str_time[2] after the strncpy().
>	2. Change the strncpy()s and strcats()s to a single sprintf as
>	   follows:
>		sprintf(str_time, "%2s:%2s:%2s" local_str, local_str+2,
>						local_str+4);
>

The second solution is wrong. %2s does not limit the number of
characters to 2. It only specifies the MINIMUM feild. If the length
of local_str is 6, then the length of str_time will be 12 after
sprintf().

-ping

dmt@PacBell.COM (Dave Turner) (08/20/89)

In article <322@cubmol.BIO.COLUMBIA.EDU> ping@cubmol.UUCP (Shiping Zhang) writes:
.In article <1025@virtech.UUCP> cpcahil@virtech.UUCP (Conor P. Cahill) writes:
.>	2. Change the strncpy()s and strcats()s to a single sprintf as
.>	   follows:
.>		sprintf(str_time, "%2s:%2s:%2s" local_str, local_str+2,
.>						local_str+4);
.The second solution is wrong. %2s does not limit the number of
.characters to 2. It only specifies the MINIMUM feild. If the length
.of local_str is 6, then the length of str_time will be 12 after
.sprintf().

But %2.2s and %.2s will both work the way the original poster wants.

Try:
		sprintf(str_time, "%2.2s:%2.2s:%2.2s", local_str, local_str+2,
							local_str+4);



-- 
Dave Turner	415/542-1299	{att,bellcore,sun,ames,decwrl}!pacbell!dmt

naras@stat.fsu.edu (B. Narasimhan) (11/26/89)

I have an urgent question to which I can't find an answer because
someone got hold of my references during this weekend and I don't know
who the brat is.

Are there any string handling functions in C? I mean functions that
can concatenate, assign values, etc. I have some strings of length 5000
to handle. Or do I have to write these things myself? ( I have already done
this but I just want to know.)

Next, I can't find the function itoa on our Sun include files. Any help is
welcome. ( I know these are available in Microsoft C in stdlib.h.)   
Thank you.

-B. Narasimhan
naras@stat.fsu.edu

poser@csli.Stanford.EDU (Bill Poser) (11/26/89)

(Regarding query about string handling functions in C.)

The standard library contains functions for searching and concatenation
into space provided by the caller, but not for automatic allocation.
Most such things are easily written.

itoa is not a standard library function, but is easily emulated by:

	sprintf(buf,"%d",foo)

K&R give a version of itoa that one can easily type in. I have written
a modified version of this, that runs somewhat faster, which I will send
by mail. However, at least in my experience even a fast itoa is only around
20% faster than using sprintf as above, so it may not be worth the bother.


							Bill Poser