-2
#include <string.h>
#include <stdio.h>

#define bool int
#define true 1
#define false 0

static bool is_digit(char c){
    return c > 47 && c < 58;
}

static bool is_all_digit(char *s){
    while(s){
        if(is_digit(*s++)){
            continue;
        }
        return false;
    }
    return true;
}


int main(){
    char *s = "123456";
    int i;
    printf("len = %d\n", strlen(s));
    for(i = 0; i<strlen(s); ++i){
        printf("%c : %s\n", *s, is_digit(*s++)? "true" : "false");
        //printf("%c : %s\n", s[i], is_digit(s[i])? "true" : "false");
    }
    return 0;
}

I want to realize the function as the part commented. But the result is the following:enter image description here

It ends with 3 and 4~6 is disappeared. My running environment is win10 gcc 6.3.0

DryBranch
  • 3
  • 2
  • 2
    Explain, in writing, and in detail, what output you get, what output you expected instead, why, and what you have done to debug the issue. What facts did you discover about your program during your debugging? – Lightness Races in Orbit Mar 02 '19 at 15:00
  • 3
    Please always post output and error messages as text, it is much easier for everyone that way. – hat Mar 02 '19 at 15:02
  • 2
    Do you understand that `strlen(s)` is recalculated on each iteration, and changes because `s` changes? – HolyBlackCat Mar 02 '19 at 15:03
  • Duplicate of https://stackoverflow.com/questions/949433/why-are-these-constructs-using-pre-and-post-increment-undefined-behavior. – melpomene Mar 02 '19 at 15:04
  • 1
    @melpomene: No, it is not a duplicate of that. While the code in this question does have undefined behavior, the problem asked about is almost certainly the use of `strlen(s)` in the loop control and `s++` in the loop body. – Eric Postpischil Mar 02 '19 at 15:06

2 Answers2

3

There are a number of problems with this.

  1. You're printfing with the wrong format string. Use %zu for a size_t, not %d.

  2. Your printf has undefined behaviour because you have *s and *s++ in the same expression, with no sequence point between them.

  3. You're recalculating strlen(s) on every iteration of the loop, and that value goes down and down and down because you keep incrementing s. I'd cache strlen(s) into a variable called n (or somesuch) before you start, as n won't change.

My compiler warned me about all but the third bug.

This program works:

#include <string.h>
#include <stdio.h>

#define bool int
#define true 1
#define false 0

static bool is_digit(char c){
    return c > 47 && c < 58;
}


int main(){
    const char *s = "123456";
    size_t i;
    const size_t n = strlen(s);
    printf("len = %zu\n", n);
    for(i = 0; i<n; ++i){
        printf("%c : %s\n", *s, is_digit(*s)? "true" : "false");
        s++;
    }
    return 0;
}

(live demo)

You could also skip the strlen entirely and just look out for a null terminator:

#include <string.h>
#include <stdio.h>

#define bool int
#define true 1
#define false 0

static bool is_digit(char c){
    return c > 47 && c < 58;
}


int main(){
    const char *s = "123456";
    while (*s) {
        printf("%c : %s\n", *s, is_digit(*s)? "true" : "false");
        s++;
    }
    return 0;
}

(live demo)

Lightness Races in Orbit
  • 378,754
  • 76
  • 643
  • 1,055
3
for(i = 0; i<strlen(s); ++i){
    s++;
}

In this for loop, i is increasing, but strlen(s) is decreasing. Because the operator ++ changes the pointer s; (s++)

At first, s indicate entire string "123456"; But after one loop, pointer s is moved as one byte. So s indicate "23456". Therefore, strlen(s) returns 5 now.

After "3" is printed, strlen(s) returns 3. And i is also 3. So that for loop is ended.

The expression *s++ just means *"increase, and dereference" (Edit : "dereference, and increase".) This will help : https://en.cppreference.com/w/cpp/language/operator_precedence

Thanks to read.

RammerChoi
  • 99
  • 6