Strcat getta errore di segmentazione su semplice getch-like di immissione della password

StackOverflow https://stackoverflow.com/questions/4093847

  •  28-09-2019
  •  | 
  •  

Domanda

Sto usando Linux e c'è una funzione personalizzata di che restituisce un int ASCII della corrente chiave di ordinamento 'come getch(). Quando si cerca di abituarsi ad esso e come memorizzare la password sono entrato in un problema, il mio codice è il seguente:

int main() {
    int c;
    char pass[20] = "";

    printf("Enter password: ");
    while(c != (int)'\n') {
        c = mygetch();
        strcat(pass, (char)c);
        printf("*");
    }

    printf("\nPass: %s\n", pass);

    return 0;
}

Purtroppo ho l'avviso da GCC:

pass.c:26: warning: passing argument 2 of ‘strcat’ makes pointer from integer without a cast
/usr/include/string.h:136: note: expected ‘const char * __restrict__’ but argument is of type ‘char’

Ho provato ad utilizzare i puntatori invece di un array di char per passaggio, ma la seconda si digita una lettera che segfaults. La funzione lavora da sola, ma non nel ciclo, atleast non come getch () farebbe su un sistema Windows.

Che cosa si può vedere è sbagliato con il mio esempio? Mi sto godendo imparare questo.

Modifica Grazie alle risposte che si avvicinò con il seguente codice sciocca:

int c;
int i = 0;
char pass[PASS_SIZE] = "";

printf("Enter password: ");
while(c != LINEFEED && strlen(pass) != (PASS_SIZE - 1)) {
    c = mygetch();
    if(c == BACKSPACE) {
        //ensure cannot backspace past prompt
        if(i != 0) {
            //simulate backspace by replacing with space
            printf("\b \b");
            //get rid of last character
            pass[i-1] = 0; i--;
        }
    } else {
        //passed a character
        pass[i] = (char)c; i++;
        printf("*");
    }
}
pass[i] = '\0';
printf("\nPass: %s\n", pass);
È stato utile?

Soluzione

Il problema è che si aspetta un strcat char * come secondo argomento (si concatena due stringhe). Non si hanno due stringhe, si dispone di una stringa e uno char.

Se si desidera aggiungere c alla fine del pass, basta tenere un int i che memorizza la dimensione attuale del pass e poi fare qualcosa di simile

pass[i] = (char) c.

Assicurati di null-terminare pass quando si è fatto (impostando l'ultima posizione a 0).

Altri suggerimenti

Un singolo carattere non è la stessa come una stringa contenente un singolo carattere.

In altre parole, 'a' e "a" sono cose molto diverse.

Una stringa, in C, è una matrice con terminazione null di caratteri. Vostro "pass" è un array di 20 caratteri -. Un blocco di memoria contenente spazio per 20 caratteri

La mygetch function () restituisce un char.

Quello che dovete fare è inserire c in uno degli spazi.

Al posto di "strcat (passaggio, c)", si vuole fare "il passaggio [i] = c", dove i parte da zero, e con incrementi di uno per ogni volta che si chiama mygetch ().

Allora avete bisogno di fare un passaggio [i] = '\ 0', quando il ciclo è fatto, con i uguale al numero di volte che si chiamati mygetch (), per aggiungere il terminatore null.

Non Sei altro problema è che non si è impostato un valore per c, la prima volta che si controlla per vedere se si tratta di '\ n'. Si desidera chiamare mygetch () prima di fare il confronto:

int i = 0;
for (;;)
{
    c = mygetch();
    if (c == '\n')
        break;

    c = mygetch();
    pass[i++] = c;
}
pass[i] = '\0';

Al di là della questione in modo corretto con diagnosi di strcat() prendendo due stringhe - perché hai ignorare gli avvisi del compilatore, o se non ci fossero gli avvertimenti, perché non avere avvertimenti attivati? Come dicevo, al di sopra di tale problema, è inoltre necessario considerare che cosa succede se si ottiene EOF, e è anche bisogno di preoccuparsi per il valore iniziale di 'c' (che potrebbe essere accidentalmente '\ n' anche se probabilmente isn 't).

che porta a codice come questo:

int  c;
char pass[20] = "";
char *end = pass + sizeof(pass) - 1;
char *dst = pass;

while ((c = getchar()) != EOF && c != '\n' && dst < end)
    *dst++ = c;
*dst = '\0';  // Ensure null termination

sono passato da 'mygetch ()' a 'getchar ()' - soprattutto perché quello che dico si applica a quella e potrebbe non applicare al 'mygetch ()' la funzione; non abbiamo una specifica di ciò che quella funzione fa su EOF.

In alternativa, se è necessario utilizzare strcat(), è ancora necessario per mantenere una traccia sulla lunghezza della stringa, ma si può fare:

char c[2] = "";
char pass[20] = "";
char *end = pass + sizeof(pass) - 1;
char *dst = pass;

while (c[0] !=  '\n' && dst < end)
{
    c[0] = mygetch();
    strcat(dst, c);
    dst++;
}

Non elegante come tutto ciò che - utilizzando strcat() nel contesto è eccessivo. Si potrebbe, suppongo, fare il conteggio semplice e ripetutamente uso strcat(pass, c), ma che ha un comportamento quadratica come strcat() deve saltare di 0, 1, 2, 3, ... i personaggi sulle iterazioni successive. Al contrario, la soluzione in cui DST punti al NUL alla fine dei mezzi di stringa che strcat() non deve saltare nulla. Con un'aggiunta di dimensioni fisse di 1 carattere, però, si è probabilmente meglio con il primo ciclo.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top