10

I have a loop that has to go from j to 0 (inclusively). My j variable is of type size_t which is usually unsigned.

My code:

#include<stdio.h>
#include<conio.h>

#define SIZE 100

int main(){
    char str[SIZE];
    size_t i=0;
    size_t j;
    puts("Enter any string");
    scanf("%s",str);
    while(str[i]!='\0'){
        i++;
    }


    for(j=i-1;j>=0;j--){

        printf("%c",str[j]);
    }


    getch();
    return 0;
}

I get an infinite loop. If I remove the equality of zero it outputs the reverse of string without the first letter. so what's the problem here?

mojtaba al moussawi
  • 1,360
  • 1
  • 13
  • 21

7 Answers7

9
for(j=i; j>0; j--) {
    printf("%c", str[j-1]);
}

Would be another option.
For a beginner maybe easier to understand.
But the other answers would be better.

edit: i'd say the best would be for(j=i; j-- > 0;) by l3x.
decrementing j after checking if it is greater then 0.

Using a do{}while() loop would also work.

j = i;
do {
   j--;
   printf("%c", str[j]);
} while (j > 0);
Flikk
  • 520
  • 3
  • 10
6

size_t is an unsigned integer and it's never going to be less than 0. So the condition in for loop is always true:

for(j=i;j>=0;j--)

You can modify the condition to (a bit ugly though):

for(j=i; j-- > 0;){
   ...
}

Note that in your condition, you are printing the \0 null byte too, which is a non-printable character. (since the j starts with a value equal to the string length). The above condition takes care of that too.

Also:

  • you can use strlen()instead of looping over it yourself.
  • Check the return value of scanf() if input reading wad successful.
P.P
  • 117,907
  • 20
  • 175
  • 238
  • Yes i have noticed that j should start form i-1 and i fixed thank you – mojtaba al moussawi Jan 25 '16 at 11:50
  • Thank you my problem is solved with many solution and i know that i can use strlen()..But please can you explain to my why mu code is causing infinite loop??and why if i just replace size_t by int the output will be correct??what's the problem with size_t ??suppose that the loop comes to j=0 it should print the element zero and after that should be exit since the condition will be false so why it's entering in infinite loop?? – mojtaba al moussawi Jan 25 '16 at 12:27
  • 1
    `size_t`, an unsigned integer can't have a value less than 0. So if you do j-- when j was 0, then it will become SIZE_MAX (the maximum value size_t can hold). Let's say SIZE_MAX is 4294967295 then the loop would run from j -> 0 -> 4294967295 -> 0 -> and the cycle will go on. if you use `int`, it'll work as you expected. But `size_t` is the right type to use to find the length of the string.Hence, you get infinite loop. if you use `int`, it'll work as you expected. But `size_t` is the right type to use to find the length of the string. – P.P Jan 25 '16 at 12:38
6

You could change j from size_t to long this makes sure all the data still fits and you can reach the -1 value.

Another option is to end the for loop with the following statement:

for (j = i - 1;;--j)
{
    // code
    if (j == 0) break;
}

as a side-note: your first while loop does the same as the strlen() in string.h.

3limin4t0r
  • 19,353
  • 2
  • 31
  • 52
5

Down counting loops tend to end up a bit obscure and hard to read. Consider using this alternative instead:

const size_t max = i-1; // maximum value that j can have

for(j=0; j<=max; j++)
{
  ... str[max-j];
}
Lundin
  • 195,001
  • 40
  • 254
  • 396
3

Unsigned integers will wrap in C. Any unsigned integer is always equal or larger than 0, in code: uint >= 0, is always true.

You can use a comparison with SIZE_MAX, since that is the largest value for type size_t. The code will iterate and print down to 0, as it should, then wrap to SIZE_MAX, and the loop will end. (This assumes the length of the string isn't SIZE_MAX.)

for(j=i; j < SIZE_MAX ;j--){

    printf("%c",str[j]);
}

Also note that your code prints the null character. So the starting index should be j=i-1, which works nicely with the wrapping behavior, since if the string's length is 0, the for loop will not print anything, because i-1 == SIZE_MAX.

2501
  • 25,460
  • 4
  • 47
  • 87
2

The problem is that j >= 0 is always true because j is unsigned.

When counting down to zero with an unsigned, I usually use postfix --:

while (j-- > 0)
Emil Laine
  • 41,598
  • 9
  • 101
  • 157
0

Unsigned value wraps around so when j == 0 and the loop does j--, j >= 0 is still true.

A basic and easy to read solution goes like this:

void reversePrint(char str[])
{
    size_t j = strlen(str);
    while (j-- > 0)
        printf("%c", str[j]);
}

Will print the string in reverse order : olleH.

Chnossos
  • 9,971
  • 4
  • 28
  • 40
  • Not the downvoter though, I think they didn't like the way you said *"...easy to read solution goes like..."* : `..while (j --> 0)...` which will make users [ask this question](http://stackoverflow.com/questions/1642028/what-is-the-name-of-the-operator-in-c) ; And secondly your superfulous use of `strlen` on the *string literal*, `str` whose size length is known at compile time. – WhiZTiM Aug 22 '16 at 23:55