2016-01-25 4 views
10

У меня есть цикл, который должен идти от j до 0 (включительно). Моя переменная j имеет тип size_t, который обычно является неподписанным.Итерирование массива назад в Условие цикла для остановки при 0 при использовании целых чисел без знака, вызывающих бесконечный цикл

Мой код:

#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; 
} 

Я получаю бесконечный цикл. Если я удалю равенство нулю, он выводит обратную строку без первой буквы. так в чем проблема?

ответ

6

size_t - целое число без знака, и оно никогда не будет меньше 0. Так условие в for цикле всегда верно:

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

Вы можете изменить условие (немного уродливым, хотя):

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

Обрати внимание, что в вашем состоянии, вы печатающие \0 нуля байт, который является непечатаемым символом. (так как j начинается со значения, равного длине строки). Вышеупомянутое условие также заботится об этом.

также:

  • вы можете использовать strlen() вместо зацикливания над ним самостоятельно.
  • Проверьте возвращаемое значение scanf(), если входные данные считываются успешно.
+0

Да я заметил, что J должен начать форму I-1 и я неподвижное спасибо –

+0

Спасибо моей проблема решена многие решения, и я знаю, что я могу использовать strlen() .. Но, пожалуйста, вы можете объяснить мне, почему mu-код вызывает бесконечный цикл? и почему, если я просто заменю size_t на int, результат будет правильным? В чем проблема с size_t ?? Предположим, что цикл приходит к j = 0, он должен печатать нулевой элемент и после этого должен быть завершен, так как условие будет ложным, поэтому почему он вводит бесконечный цикл? –

+1

'size_t', целое число без знака не может иметь значение меньше 0. Так что если вы делаете j--, когда j равно 0, тогда он станет SIZE_MAX (максимальное значение size_t может удерживаться). Предположим, что SIZE_MAX - это 4294967295, тогда цикл будет работать от j -> 0 -> 4294967295 -> 0 ->, и цикл продолжится. если вы используете 'int', он будет работать так, как вы ожидали. Но 'size_t' - это правильный тип, который можно использовать для определения длины строки. У вас есть бесконечный цикл. если вы используете 'int', он будет работать так, как вы ожидали. Но 'size_t' - это правильный тип, который можно использовать для поиска длины строки. –

2

Целые числа без знака будут перенесены в C. Любое беззнаковое целое всегда равно или больше 0, в коде: uint >= 0, всегда верно.

Вы можете использовать сравнение с SIZE_MAX, так как это самое большое значение для type size_t. Код будет перебирать и печатать до 0, как и следовало бы, а затем переносить на SIZE_MAX, и цикл завершается. (Это предполагает, что длина строки не SIZE_MAX.)

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

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

отметить также, что ваш код печатает нулевой символ. Поэтому начальный индекс должен быть j=i-1, который отлично работает с поведением обертывания, поскольку, если длина строки равна 0, цикл for ничего не печатает, потому что i-1 == SIZE_MAX.

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

Был бы еще один вариант.
Для новичка может быть проще понять.
Но другие ответы были бы лучше.

Редактировать: я бы сказал, что лучшим будет for(j=i; j-- > 0;) by l3x.
Уменьшение j после проверки, если оно больше 0.

Использование do do {} while() будет работать также.

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

Это выглядит как чистый пример уродливого кода с причудливым форматированием. – Malina

5

Вы можете изменить j от size_t до long Это гарантирует, что все данные по-прежнему подходит и вы можете достичь значения -1.

Другой вариант закончить цикл со следующим утверждением:

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

в качестве побочного сведению: ваше первое время цикла делает то же самое, как strlen() в string.h.

+0

'j = i; делать { ...; j--; } while (j! = 0); ', вероятно, более читабельна. – Lundin

3

Нижние счетные циклы, как правило, немного неясны и трудно читаются. Рассмотрите возможность использования этой альтернативы вместо:

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

for(j=0; j<=max; j++) 
{ 
    ... str[max-j]; 
} 
0

беззнаковое значение обтекает так, когда j == 0 и петля делает j--, j >= 0 по-прежнему верно.

Основной и легко читается решение выглядит следующим образом:

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

напечатает строку в обратном порядке: olleH.

+0

Downvoters, помогите объяснить? – Chnossos

+0

Однако, я не думаю, что им не понравилось то, что вы сказали * «... легко читаемое решение идет как ...» *: '..while (j -> 0) ...' который заставит пользователей [задавать этот вопрос] (http://stackoverflow.com/questions/1642028/what-is-the-name-of-the-operator-in-c); Во-вторых, ваше превосходное использование 'strlen' в строковом литерале *,' str', размер которого известен во время компиляции. – WhiZTiM

+0

Я получаю вашу мысль. Может быть, это редактирование будет? – Chnossos

1

Проблема в том, что j >= 0 всегда true, потому что j является unsigned.

При отсчете до нуля с unsigned, я обычно использую постфикс --:

while (j-- > 0)