traversing C string: get the last word of a string
Asked Answered
M

5

5

how would you get the last word of a string, starting from the '\0' newline character to the rightmost space? For example, I could have something like this where str could be assigned a string:

char str[80];
str = "my cat is yellow";

How would I get yellow?

Maxa answered 9/2, 2012 at 22:34 Comment(0)
G
11

Something like this:

char *p = strrchr(str, ' ');
if (p && *(p + 1))
    printf("%s\n", p + 1);
Guesthouse answered 9/2, 2012 at 22:36 Comment(5)
That + 1 can be done within initialization: char *p = strrchr(str, ' ') + 1;Delp
@LihO: Then you would be left to check if the return value was 1 (meaning not found). This is not a win.Ukase
@Delp Thanks :-) I added some checking to make sure the space is not the last character.Guesthouse
Well, if space is the last character nothing bad should happen-the +1 pointer will point the '\0' character.Laclos
@Laclos Yeah, but maybe the OP wants to avoid printing an empty line :-? Either way, the check is optional.Guesthouse
A
1

In case you don't want to use 'strrchr' function, Here is the solution.

i = 0;
char *last_word;

while (str[i] != '\0')
{
    if (str[i] <= 32 && str[i + 1] > 32)
        last_word = &str[i + 1];
    i++;
}
i = 0;
while (last_word && last_word[i] > 32)
{
    write(1, &last_word[i], 1);
    i++;
}
Arrant answered 16/10, 2018 at 3:44 Comment(0)
C
0

I would use function strrchr()

Cordage answered 9/2, 2012 at 22:36 Comment(0)
W
-2

The best way to do this is to take advantage of existing solutions. One such solution (to a much more general problem) is Perl Compatible Regular Expressions, an open-source regular expression library for C. So, you can match the string "my cat is yellow" with the regular expression \b(\w+)$ (expressed in C as "\b(\w+)$") and keep the first captured group, which is "yellow."

Washy answered 9/2, 2012 at 22:38 Comment(2)
A rule: if you are able not to use regex, don't use them )))Cordage
no need to use regex for something that simple (and i think it's homework)Pouf
T
-2

(heavy sigh) The original code is WRONG in standard / K&R / ANSI C! It does NOT initialize the string (the character array named str)! I'd be surprised if the example compiled. What your program segment really needs is

if strcpy(str, "my cat is yellow")
    {
    /* everything went well, or at least one or more characters were copied. */
    }

or, if you promised not to try to manipulate the string, you could use a char pointer to the hard-coded "my cat is yellow" string in your source code.

If, as stated, a "word" is bounded by a space character or a NULL character, then it would be faster to declare a character pointer and walk backwards from the character just before the NULL. Obviously, you'd first have to be sure that there was a non-empty string....

#define NO_SPACE 20
#define ZERO_LENGTH -1

int iLen;
char *cPtr;

if (iLen=strlen(str) ) /* get the number of characters in the sting */
    { /* there is at least one character in the string */
    cPtr = (char *)(str + iLen); /* point to the NULL ending the string */
    cPtr--; /* back up one character */
    while (cPtr != str)
        { /* make sure there IS a space in the string
             and that we don't walk too far back! */
        if (' ' == *cPtr)
            { /* found a space */
/* Notice that we put the constant on the left?
   That's insurance; the compiler would complain if we'd typed = instead of == 
 */
            break;
            }
        cPtr--; /* walk back toward the beginning of the string */
        }
    if (cPtr != str)
        { /* found a space */
        /* display the word and exit with the success code */
        printf("The word is '%s'.\n", cPtr + 1);
        exit (0);
        }
    else
        { /* oops.  no space found in the string */
        /* complain and exit with an error code */
        fprintf(STDERR, "No space found.\n");
        exit (NO_SPACE);
        }
    }
else
    { /* zero-length string.  complain and exit with an error code. */
    fprintf(STDERR, "Empty string.\n");
    exit (ZERO_LENGTH);
    }

Now you could argue that any non-alphabetic character should mark a word boundary, such as "Dogs-chase-cats" or "my cat:yellow". In that case, it'd be easy to say

if (!isalpha(*cPtr) )

in the loop instead of looking for just a space....

Theo answered 10/2, 2012 at 6:15 Comment(9)
uncompilable code as is; terribly convoluted and way way over commented.Pouf
Comments are included for the benefit of both people new to C and (in a production environment) to the programmers who must maintain the code. Remember, the size of the comments has zero to do with the size of the executable.Theo
If you believe the code to be uncompilable, you should feel free to explain what is wrong. Sniping does no good.Theo
for anyone who is learning to program your snippet teaches them bad habits. (for example printing errors out on stdout using printf); using arbitrary exit code; poor choice of variable names; horrible use of the while loop; incorrect placement of decrement (actual semantic mistake in logic). then it is not actually bundled in a function of any sort so code is not compilable. For prod: C programmers understand C; explaining code line by line is a waste; a brief desc. of function will do; if there is some black art stuff, most QA would reject that unless absolutely necessary.Pouf
i am not sniping at you, you are trying to help and that is very much appreciated. I am simply pointing out your errors so that you can correct them too.Pouf
When people believe that they have a better way of completing some task, they should provide examples. For example,Theo
For example, if I wanted to be perfectly correct, I would #define specific error codes and fprintf to STDERR. Do you need examples?Theo
The first decrement of the variable cPtr is correct. (What IS missing in the loop is ANOTHER decrement. That's where the logic error lies.) cPtr is first assigned the address of the '\0' in the string, then decremented on the following line of code, so that it points at the presumed last character in the string. Please remember that a pre-increment, post-increment, pre-decrement, or post-decrement can appear virtually anywhere. The programming convention is to use a post-decrement (or post-increment) when no other work is being done with the variable (e.g., no comparison).Theo
There ave various standard conventions for naming variables; one is to use a lowercase letter (indicating variable type) as the first character of the variable name, followed by an uppercase letter to begin the specific name. For example, iLen should be a hint that the variable contains an integer value and is apt to be some kind of length. Likewise, cPtr probably is a pointer to a character (whether variable or constant!). (There is a name for this kind of notation: Hungarian Notation. An Internet search will give you some examples.)Theo

© 2022 - 2024 — McMap. All rights reserved.