-5

I tried to write a function that gets a pointer to array of char, reads a string from the user and remove all spaces in the start of the string till the first char that is not string appear. Finally return the copy of the string without space/s in the begining.

For example,

for input abcd the function should return pointer to the string abcd.

for input 123 123 the function should return pointer to string 123 123.

The function is shown below,

void read_RemoveSpace(char * str)/**read the rest of string**/
{
    char tempRead[30];
    fgets(tempRead,30,stdin);
    char *ptr = strtok(tempRead, " "); /**remove spaces between command and other data**/
    strcpy(str,ptr); /**copy the new string without the spaces.**/
}

But some reason the function strtok() is not working as expected.

In case of input:

   123 456

the function returns only the first part without the spaces but not the rest of the string, i.e. it points to

123

Any suggestions?

Ry-
  • 218,210
  • 55
  • 464
  • 476
Yuval
  • 1,721
  • 4
  • 16
  • 15
  • what is the problem that you are facing?how are you calling the function?what exactly is stored in str after teh call? – Vijay Dec 25 '12 at 12:08
  • `strtok_r()` does work as expected, maybe just your expectations are incorrect... –  Dec 25 '12 at 13:00

3 Answers3

4

strtok is working exactly as expected. It breaks the input apart into the strings 123 and 456.

strtok (tempRead, " "); /* Returns 123 */
strtok (NULL, " "); /* Returns 456 */

I think you can do with a simpler solution:

int i = 0;
char tempRead[30];
...
while (tempRead[i] == ' ' && tempRead[i])
  i++;
strcpy(str,tempRead+i);
StoryTeller - Unslander Monica
  • 165,132
  • 21
  • 377
  • 458
3

It's working exactly as expected.

The first call to strtok will return the first occurrence of the token; subsequent calls will return the rest of the tokens one at a time as long as you're providing the first parameter as NULL; and strtok will return NULL when it runs out of tokens.

EDIT:
Some things might result in weird bugs, so I quote here what the man pages mention and what you should always keep in mind when using strtok:

Be cautious when using these functions. If you do use them, note that:

  • These functions modify their first argument.

  • These functions cannot be used on constant strings.

  • The identity of the delimiting character is lost.

  • The strtok() function uses a static buffer while parsing, so it's not thread safe. Use strtok_r() if this matters to you.

Ry-
  • 218,210
  • 55
  • 464
  • 476
Fingolfin
  • 5,363
  • 6
  • 45
  • 66
0

Using strtok() isn't the obvious way to do it.

void read_RemoveSpace(char *str)
{
    char *dst = str;
    char tempRead[30];
    if (fgets(tempRead, sizeof(tempRead), stdin) != 0)
    {
        char *src = tempRead;
        char c;
        while ((c = *src++) != '\0')
        {
            if (c != ' ')
                *dst++ = c;
        }
    }
    *dst = '\0';
}

This copies the non-blanks in tempRead into str, including a newline; you could use isspace() or isblank() from #include <ctype.h> if you preferred. I'm not convinced that 30 is a good length for the local string, but it is what you had in the question. Arguably, you should specify how big a string is provided in the interface: void *read_RemoveSpace(char *buffer, size_t buflen). You could also usefully have the function return the pointer to the null at the end of the string (thereby indirectly giving the length of the string minus the blanks).

void read_RemoveSpace(char *buffer, size_t buflen)
{
    char *dst = buffer;
    char tempRead[buflen];
    if (fgets(tempRead, sizeof(tempRead), stdin) != 0)
    {
        char *src = tempRead;
        char c;
        while ((c = *src++) != '\0')
        {
            if (!isspace((unsigned char)c))
                *dst++ = c;
        }
    }
    *dst = '\0';
    return dst;
}

Not very different, but a lot safer. It uses a local VLA — variable length array — which is part of C99. It would be possible to forego the VLA and do the copy into the target buffer directly:

void read_RemoveSpace(char *buffer, size_t buflen)
{
    char *dst = buffer;
    if (fgets(buffer, buflen, stdin) != 0)
    {
        char *src = buffer;
        char c;
        while ((c = *src++) != '\0')
        {
            if (!isspace((unsigned char)c))
                *dst++ = c;
        }
    }
    *dst = '\0';
    return dst;
}

Up to the first white space, this copying is a no-op; thereafter, it copies characters into their final position.

Jonathan Leffler
  • 730,956
  • 141
  • 904
  • 1,278