-1


I want to find the last element of an string without the use of any functions.
My code seems to work, but I'm not quite sure why it does work in the way it does and would be glad about input.
Here is the code.

#include <stdio.h>

char *find_last(char *s);

int main(void)
{
    char string[] = {"This is an Example"};
    find_last(string);
    return 0;
}

char *find_last(char *s)
{
/*  char last;*/
    while (*s++ != 0) {}
    printf("*s ist %c", *(s-2));
    return 0;
}

I don't understand why I have to print *(s-2) instead of *(s-1) in order to get the last character. (In order to get a futher character back I only have to decrement one more, i.e. *(s-3)).

Oh, and additionally, it seems that the content of *s seems to be the letter O (from me mistaken as zero, until now), independent of the example-string tested with. Why is that? I thought it should be zero (0) because I increment the pointer until it hits the binary zero.

Thanks for any help!

Mika2019
  • 47
  • 9
  • 1
    Because `s` was incremented past the 0 terminator. Be careful of the corner case where the string is empty. – Weather Vane Dec 31 '18 at 16:33
  • `s++` returns the value *before* it was incremented – UnholySheep Dec 31 '18 at 16:33
  • 1
    Possible duplicate of [What is the difference between prefix and postfix operators?](https://stackoverflow.com/questions/7031326/what-is-the-difference-between-prefix-and-postfix-operators) – UnholySheep Dec 31 '18 at 16:34
  • @UnholySheep Ok, yes, you are right. But then the print-result of *s should be 'e' shouldn't it? – Mika2019 Dec 31 '18 at 16:39
  • @Weather Vane I thought so too, but I can't see why? – Mika2019 Dec 31 '18 at 16:40
  • 1
    If you increment it past the null character you are already past the bounds of the array - printing the contents of `*s` invokes *undefined behavior* at that point – UnholySheep Dec 31 '18 at 16:42
  • 1
    `while (*s != 0) {s++;}` would stop with `s` pointing to the `0` terminator. But you have `while (*s++ != 0) {}` and `s` is incremented past the `0` terminator. – Weather Vane Dec 31 '18 at 16:42
  • 1
    Curious, What would you want to print if the string was `""`? – chux - Reinstate Monica Dec 31 '18 at 19:25
  • @chux Hm, yes, you are right, this doesn't work. It prints anything/something at the moment. Do you have an idea what I can check for so that I can print a proper "error" message? – Mika2019 Dec 31 '18 at 21:38

2 Answers2

1

Since ++ is a post-increment operator, this is what happens in the while loop:

  1. *s is compared to 0.
  2. s is incremented.
  3. If the comparison succeeds, the loop exits.

When s reaches the end of the string it's pointing to the null character. It's incremented to point to the character after the null, and then the loop exits. At that point:

*s = the character after the null, which happens to be the letter O in your case.

*(s-1) = the null character.

*(s-2) = the last character in the string.

Adam Liss
  • 47,594
  • 12
  • 108
  • 150
0

OP later asked about handling a corner case involving "".

First recommend to clarify the goal "to find the last element of an string ". By definition: in C,

A string is a contiguous sequence of characters terminated by and including the first null character. C11 §7.1.1 1

Since a string includes a null character and that is last, then the "Finding last character of a string" is always the null character.

Certainly OP is interested in the last character before the null character. Since such a function may receive a valid string "" and not be able to find such a character, then find_last() could error out somehow, or perhaps return an error condition, like NULL below and let the caller decide.

Starting with OP-like code

char *find_last(char *s) {
  printf("Last character before the null character in \"*s\"", s);
  if (*s == '\0') {
    printf(" does not exist.\n");
    return NULL;
  }
  while (*s) {
    s++;
  }
  s--;
  printf(" is '%c'\n", *s);
  return s;
}
chux - Reinstate Monica
  • 143,097
  • 13
  • 135
  • 256