Tek-Tips is the largest IT community on the Internet today!

Members share and learn making Tek-Tips Forums the best source of peer-reviewed technical information on the Internet!

  • Congratulations strongm on being selected by the Tek-Tips community for having the most helpful posts in the forums last week. Way to Go!

remove leading zeroes 3

Status
Not open for further replies.

Ghodmode

Programmer
Feb 17, 2004
177
NZ
I'm a C newbie, but a little more experienced in Perl. In Perl, what I want to do would be done like this...

Code:
my $external_id = ($data[$row][1] =~ s/^0+(.*)$/$1/);

That's where I'm coming from, but I need to do this in C. I've devised a way but I'm wondering if there's a better way than this...

Code:
data[row][1] = (char*)malloc(11); /* Account # */
/* stuff */

strncat( data[row][1], line + 6, 10 );
/* stuff */

char external_id[48]     = "";
/* stuff */

char holdvar[48] = "";
/* stuff */

strncpy( holdvar, data[row][1], 48 );
for ( i = 0; i < strlen(holdvar); i++ )
{
    if ( holdvar[i] == '0' )
    {
        continue;
    }

    while ( i < strlen(holdvar) )
    {
        sprintf( external_id, "%s%c", external_id, holdvar[i++] );
    }
}

Stuff happens in between some of those lines of code, but I've put the important lines.

Any ideas?

Thank you.

--
-- GhodMode
 
The following demo shows an easier way of
stripping leading zeros.

Code:
#include <stdio.h>

main()
{
   char *p;
   char holdvar[48];

   strcpy(holdvar, "00000048");

   for (p = holdvar; *p == '0'; p++);

   printf( "Number without leading zeros: %s\n", p);
}

 
Caution: fpmurphy's solution is a trick: it moves a pointer but not a contents of a string. We can't change directly a name of an array (it's constant), and we can't free dynamic (obtained from malloc) array after fpmurphy's loop. Every time we must assign auxiliary pointer then do loop then remember that new pointer refers to non-zero chars but not to original source etc...

Try this:
Code:
char* TrimFaster(char* str) /* Change function name... */
{
  char* p, *q, ch;

  if (str) /* Always protect himself */
  {
    for (p = str;
         ch=*p) == '0' || ch == ' ' || ch == '\t';
         ++p /* or test '0' only if you wish */
         );
    if (p != str)
    {
      q = str;
      do
        *q++ = ch = *p++;
      while (ch);
    }

  }
  return str;
}
/* more universal solution with <string.h> functions */
char* TrimShorter(char* str, const char* skipchars)
{
  int k, n;
  char*  p;
  if (!skipchars)
    skipchars = "\t 0"; /* or "0" only */
  if (str && (n=strspn(str,skipchars)) != 0)
  {
    k = strlen(p=str+n) + 1;
    memmove(str,p,k); /* don't use strcpy: strings overlapped! */
  }
  return str;
}
 
> Caution: fpmurphy's solution is a trick: it moves a pointer but not a contents of a string.

A simple modification to fpmurphy's solution (if you want to change the string contents) would be to do a memmove():
Code:
#include <stdio.h>
#include <string.h>

main()
{
   char *p;
   char holdvar[48];

   strcpy(holdvar, "00000048");

   for (p = holdvar; *p == '0'; p++);

   memmove(holdvar,p,strlen(p)+1);  /* modify holdvar */

   printf( "Number without leading zeros: %s\n", holdvar);
}
 
Thank you all. I ended up using code that is very much like itsgsd's, but I learned from all three. I understand pointers and "overlapping" values a little better now and I know how to use [tt]memmove[/tt].

I should've thought of the method fpmurphy suggested, but even if I had, I wouldn't have realized that I was only getting a pointer to the tail end of the original value.

ArkM had some very good points, but the code is more robust than I need (this time :)). I'm reading the data from a file with fixed width, zero-filled fields. I do need to check the contents of the value after I remove all of the zeroes, though.

My results...
Code:
    char external_id[48]     = "";
    char *p;

    for ( row = 0; row < MAXROWS; row++ ) {
        strncpy( external_id, data[row][1], 48 );

        for( p = external_id; *p == '0'; p++ );

        memmove( external_id, p, strlen(p) + 1 );

        if ( strlen(external_id) < 1 )
        {
            printf( "Row %i has no external ID\n", row );
        }
    }

Thank you,

--
-- GhodMode
 
Status
Not open for further replies.

Part and Inventory Search

Sponsor

Back
Top