2016-01-25 12 views
10

Ho un ciclo che deve passare da j a 0 (incluso). La mia variabile j è di tipo size_t che di solito non è firmata.iterazione di un array all'indietro in Per condizione di ciclo da arrestare a 0 quando si utilizzano numeri interi senza segno che causano un ciclo infinito

Il mio codice:

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

ottengo un ciclo infinito. Se rimuovo l'uguaglianza di zero, restituisce l'inverso della stringa senza la prima lettera. quindi qual è il problema qui?

risposta

6

size_t è un numero intero senza segno e non sarà mai inferiore a 0. Così la condizione in for ciclo è sempre vero:

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

è possibile modificare la condizione (un po 'brutto però):

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

Nota che nella sua condizione, si stampa il \0 nullo anche il byte, che è un carattere non stampabile. (poiché j inizia con un valore uguale alla lunghezza della stringa). Anche la condizione di cui sopra si prende cura di questo.

anche:

  • è possibile utilizzare strlen(), invece di loop su voi stessi.
  • Controllare il valore di ritorno di scanf() se l'input ha avuto esito positivo.
+0

Sì ho notato che j dovrebbe iniziare il modulo I-1 e ho fissato grazie –

+0

Grazie il mio problema è risolto con molte soluzioni e so che posso usare strlen() .. Ma per favore puoi spiegare al mio perchè il codice mu sta causando loop infinito? e perché se io sostituisco solo size_t con int l'output sarà corretto ?? qual è il problema con size_t ?? supponiamo che il ciclo arrivi a j = 0 dovrebbe stampare l'elemento zero e dopo dovrebbe uscire perché la condizione sarà falsa, quindi perché sta entrando nel ciclo infinito ?? –

+1

'size_t', un numero intero senza segno non può avere un valore inferiore a 0. Quindi se j - quando j era 0, allora diventerà SIZE_MAX (il valore massimo size_t può contenere). Diciamo che SIZE_MAX è 4294967295 quindi il ciclo verrebbe eseguito da j -> 0 -> 4294967295 -> 0 -> e il ciclo proseguirà. se usi 'int', funzionerà come previsto. Ma 'size_t' è il tipo giusto da usare per trovare la lunghezza della stringa. Quindi, ottieni un ciclo infinito. se usi 'int', funzionerà come previsto. Ma 'size_t' è il tipo giusto da usare per trovare la lunghezza della stringa. –

2

Numeri interi senza segno si avvolgeranno in C. Qualsiasi numero intero senza segno è sempre uguale o maggiore di 0, nel codice: uint >= 0, è sempre true.

È possibile utilizzare un confronto con SIZE_MAX, poiché questo è il valore più grande per tipo size_t. Il codice verrà iterato e stampato a 0, come dovrebbe, quindi eseguire il wrapping su SIZE_MAX e il ciclo terminerà. (Premesso che la lunghezza della stringa non è SIZE_MAX.)

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

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

Si noti inoltre che il codice stampa il carattere null. Quindi l'indice iniziale dovrebbe essere j=i-1, che funziona bene con il comportamento del wrapping, poiché se la lunghezza della stringa è 0, il ciclo for non stampa nulla, perché i-1 == SIZE_MAX.

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

Sarebbe un'altra opzione.
Per un principiante forse più facile da capire.
Ma le altre risposte sarebbero migliori.

modifica: direi che il migliore sarebbe for(j=i; j-- > 0;) di l3x.
decrementando j dopo aver verificato se è maggiore di 0.

Utilizzare anche un ciclo do {} while().

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

Sembra un semplice esempio di brutto codice con una bizzarra formattazione. – Malina

5

Si potrebbe cambiare j da size_t a long Questo assicura tutti i dati si adatta ancora e si può raggiungere il valore -1.

Un'altra opzione è quella di terminare il ciclo for con la seguente dichiarazione:

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

come un lato-nota: il vostro primo ciclo while fa la stessa cosa come il strlen() in string.h.

+0

'j = i; fare { ...; j--; } while (j! = 0); 'probabilmente è più leggibile. – Lundin

3

I cicli di conteggio in basso tendono a risultare un po 'oscuri e difficili da leggere. Considerare l'utilizzo di questa alternativa, invece:

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

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

valore senza segno avvolge in modo che quando j == 0 e il ciclo fa j--, j >= 0 è ancora vero.

una soluzione di base e di facile lettura è questa:

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

stamperà la stringa in ordine inverso: olleH.

+0

Downvoters, cura di spiegare? – Chnossos

+0

Non è il downvoter, penso che non gli piacesse il modo in cui hai detto * "... la soluzione facile da leggere va come ..." *: '..while (j -> 0) ...' che renderà gli utenti [fare questa domanda] (http://stackoverflow.com/questions/1642028/what-is-the-name-of-the-operator-in-c); E in secondo luogo il tuo superfulous uso di 'strlen' sul * string letterale *,' str' la cui lunghezza è nota al momento della compilazione. – WhiZTiM

+0

Ho capito il tuo punto. Forse questa modifica avrebbe funzionato? – Chnossos

1

Il problema è che j >= 0 è sempre true perché j è unsigned.

Quando il conto alla rovescia a zero con un unsigned, io di solito uso postfix --:

while (j-- > 0) 
Problemi correlati