Link to home
Start Free TrialLog in
Avatar of chenwei
chenwei

asked on

I am looking for a function which can move out the spaces from the front of a string

I use fgets to read lines from a file. And I am going to use the first char as a mark. But the first char of many lines is not a char but space or tab. I want to trim out the spaces. Which function can do this in C?
Avatar of cookre
cookre
Flag of United States of America image

Use scanf with a leading blank in the format before the %s.  This says you want to start storing into the specified string with the first non-white space character .
Avatar of chenwei
chenwei

ASKER

Thanks for your help first. Maybe I haven't explained my question exactly. There are sometimes not only one space but several spaces before a string as follow:
"
! here is the head
   # here is the format

      110  ..................
      150  ................
    2100  ................
 340000  .................

  ...
  ...
"

Can I use the method you said to overcome it? Besides, I will check if the first char is neither '!' nor '#' ,that means the data is comimg.

You could also write a function that trims the whitespace off the beginning to a string.  The following function trims leading space and returns the length of the new string.

int stringTrim(char *s)
{
int len = strlen(s);
int i;

for ( i = 0; isspace(s[i]); i++ )
    ;
len -= i;
if ( i )
    memmove(s, s + i, len + 1); /* Grab the NULL terminator */

return len; /* This is the new strlen */
} /* stringTrim */
Avatar of chenwei

ASKER

Thanks for your help first. Maybe I haven't explained my question exactly. There are sometimes not only one space but several spaces before a string as follow:
"
! here is the head
   # here is the format

      110  ..................
      150  ................
    2100  ................
 340000  .................

  ...
  ...
"

Can I use the method you said to overcome it? Besides, I will check if the first char is neither '!' nor '#' ,that means the data is comimg.

How about using strspn:

#include <string.h>

size_t strspn(char *string1,char *string2);

Returns the position of the first non-matching character in string1.


So for example if fgets returns its result in line:

int i;
i=strspn(line," \t");

then i, in this example, will be the index of the first nonblank nontab character.
scanf(" %s",LineIn)

will strip ALL leading whitespace from the line.  You'll end up seeing those sample lines as:


! here is the head
# here is the format
110  ..................
150  ................
2100  ................
340000  .................
for the file fscanf is used as follows

 
      FILE *fp;
      char str[100];
      fp = fopen("test.txt","r");
      while(!feof(fp))
      {
            fscanf(fp,"%s",str);
            printf("%s",str);
                // str is having no leading and trailing spaces
      }
I think so better to  use fgetc().
cookre,

Your solution is nice - it trims all leading white spaces, but won't it trim everything AFTER the first word too? This could cause a problem if chenwei's data lines contain embedded spaces.

For instance, if chenwei's first data line is
   12345 AndSomeData SomeMoreData
then your solution would make LineIn
as only "12345"; it would drop the rest of the line because of the space immediately following "12345". Won't it?

Imladris's solution
-------------------
Imladris's solution is more general, I think. But s/he didn't explain what to do after getting the index. It may be obvious to most C programmers, but not to a beginner. So please permit me to clarify.

a. Note that in the line
i=strspn(line," \t");
there is a space _and_ a tab (\t). Don't miss the space. It is not visually obvious that there is a space there.

b. chenwei, once you get an index i, you should use (line+i) instead of line in further processing. (line+i) will be a pointer that will point to the first non-space character, and therefore will in effect, represent a null-terminated string that starts from first non-space character and ends at the null character (so takes the whole line)

my own suggestion
-----------------
chenwei, since you said you were using fgets, let me proceed on that line.

Let me assume that you read the line into a buffer called InputLine, with a statement somewhat like
fgets(InputLine, 256, filepointer);

What I would suggest you do is this:

a. Declare a char * pointer at the start of the function, say
char *C;

b. to 'trim' the InputLine by removing leading spaces, just write a statements at an appropriate place;

C = InputLine;
while (*C == ' ' || *C == '\t') C++;

c. Now, just use C in place of InputLine.

Hope you understand this logic. It is simple, and it will do what you need in a very general way.

By the way, instead of
while (*C == ' ' || *C == '\t') C++;

you could have said

while (isspace(*C)) C++;

but that would involve explaining isspace() macro or function, which may not exist on all compilers.

Hope this helps

- stochastic
Sorry marcjb,

I didn't see your posting earlier. You had already suggested what I did. Still, I think it may not be necessary to copy the remaining text backward in the buffer like you did (whether this is needed or not depends on what exactly chenwei wants to do; but I feel for most purposes, one may be able to do without it). Also, if chenwei takes your suggestion, you could explain what happens in your code, in greater detail for the asker's benefit.

Let me illustrate a bit further.

Imagine that InputLine contained
"   12345 AndSomeData SomeMoreData"

With marcjb's answer,
InputLine becomes "12345 AndSomeData SomeMoreData"

with my answer, InputLine stays the same, but C becomes "12345 AndSomeData SomeMoreData"; without the need to move any data around. Also, C is merely a pointer to the same actual data storage; so no new data storage needs to be allocated.

I hope I have added at least _some_ value with the explanation.

- stochastic
Sorry marcjb,

I didn't see your posting earlier. You had already suggested what I did. Still, I think it may not be necessary to copy the remaining text backward in the buffer like you did (whether this is needed or not depends on what exactly chenwei wants to do; but I feel for most purposes, one may be able to do without it). Also, if chenwei takes your suggestion, you could explain what happens in your code, in greater detail for the asker's benefit.

Let me illustrate a bit further.

Imagine that InputLine contained
"   12345 AndSomeData SomeMoreData"

With marcjb's answer,
InputLine becomes "12345 AndSomeData SomeMoreData"

with my answer, InputLine stays the same, but C becomes "12345 AndSomeData SomeMoreData"; without the need to move any data around. Also, C is merely a pointer to the same actual data storage; so no new data storage needs to be allocated.

I hope I have added at least _some_ value with the explanation.

- stochastic
Avatar of chenwei

ASKER

Thanks for the tips and help from all sites. The following is my code:
***************************
stream=fopen("myfile","r");
      
while(!feof(stream))
{
  fgets( line, 100, stream);
  if(strlen(line)!=0)
  {
     sscanf(line, "%s", trim_line );
     if((trim_line[0]!='!') && (trim_line[0]!='#'))
     {
         sscanf(line, "%d %lf %lf \n", &a,&b,&c);
     }
  }
}
***************************

chenwei,

I edited your code as follows:
you may have declared trim_line as
char trim_line[100]; or something similar. Please change that to
char *trim_line;


************
stream=fopen("myfile","r");

while(!feof(stream))
{
  fgets( line, 100, stream);
  if(strlen(line)!=0)
  {
     trim_line = line;
     while (*trim_line == ' ' || *trim_line == '\t') trim_line++;
     if((trim_line[0]!='!') && (trim_line[0]!='#'))
     {
         sscanf(line, "%d %lf %lf \n", &a,&b,&c);
     }
  }
}
***************************
this should work fine, except that I would suggest that the line
     if((trim_line[0]!='!') && (trim_line[0]!='#'))
should be changed to
     if(*trim_line!='!' && *trim_line!='#')

Hope this helps
- stochastic



Avatar of chenwei

ASKER

Thanks for your help, stochastic. But as I run the program till
sscanf(line, "%d %lf %lf \n", &a,&b,&c);

It shows a runtime error. Why?
chenwei,

Sorry,
sscanf(line, "%d %lf %lf \n", &a,&b,&c);
should actually be
sscanf(trim_line, "%d %lf %lf \n", &a,&b,&c);
     
I overlooked that.

If that doesn't fix it ... hmmm.    
What is the runtime error? How about posting the full program and a couple of lines of the sample input file? It would be hard to tell otherwise.

Hope you have declared a,b,c correctly.
int a;
double b, c;
is what I guess from your sscanf statement.


- stochastic


Avatar of chenwei

ASKER

I've solved the problem. There is a mistyping in my program.

Please lock my question so I can give you the points.

Thanks!
ASKER CERTIFIED SOLUTION
Avatar of stochastic
stochastic
Flag of India image

Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
Avatar of chenwei

ASKER

I've solved the problem. There is a mistyping in my program.

Please lock my question so I can give you the points.

Thanks!