Strcat getta errore di segmentazione su semplice getch-like di immissione della password
-
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);
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.