Strcat бросает неисправность сегментации на простой введении пароля Getch

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

  •  28-09-2019
  •  | 
  •  

Вопрос

Я использую Linux, и есть пользовательская функция, которая возвращает ASCII int текущего ключа своего рода getch(). Отказ При попытке привыкнуть к нему и как хранить пароль, я вошел в проблему, мой код выглядит следующим образом:

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

К сожалению, я получаю предупреждение от 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’

Я попробовал использовать указатели вместо массива CHAR для пропуска, но второй я вводит букву это SegFaults. Функция работает самостоятельно, но не в цикле, по крайней мере, не похоже на GETCH (), будет в системе Windows.

Что вы можете видеть, не так с моим примером? Я наслаждаюсь изучением этого.

РЕДАКТИРОВАТЬ: Благодаря ответам я придумал следующий глупый код:

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);
Это было полезно?

Решение

Проблема в том, что strcat ожидает А. char * в качестве второго аргумента (он объединяет две строки). У вас нет двух строк, у вас есть одна строка и один char.

Если вы хотите добавить c до конца pass, просто держите int i который хранит текущий размер pass а потом сделать что-то вроде

pass[i] = (char) c.

Убедитесь, что нулевой pass Когда вы закончите (установив последнюю позицию до 0).

Другие советы

Один символ не такой, как строка, содержащая один символ.

Другими словами, «а» и «А» - это очень разные вещи.

Строка в C, является равен нулевым массивом символов. Ваш «проход» - это массив 20 символов - блок памяти, содержащего пространство для 20 символов.

Функция mygetch () возвращает символ.

То, что вам нужно сделать, это вставить C в один из пробелов.

Вместо «Strcat (Pass, C)» вы хотите сделать «Pass [I] = C», где я начинаю с нуля, и прирачивайтесь на один за каждый раз, когда вы звоните Mygetch ().

Тогда вам нужно сделать пропуск [I] = ' 0', когда цикл выполняется, причем я равен количеству раз вы позвонил Mygetch (), чтобы добавить нулевой терминатор.

Вы Другая проблема заключается в том, что вы не установили значение для C, в первый раз вы проверяете, если это « n». Вы хотите позвонить Mygetch (), прежде чем сделать сравнение:

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

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

Более и выше правильно диагностированной проблемой с strcat() Принимая две строки - почему вы игнорировали предупреждения компилятора, или если бы не было предупреждений, почему у вас нет предупреждений? Как я уже говорил, снова и выше этой проблемы, вам также нужно рассмотреть, что произойдет, если вы получите EOF, и вам также нужно беспокоиться о начальном значении «C» (что может случайно быть « N», хотя это, вероятно, это T).

Это приводит к тому, что код такой:

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

Я перешел с «Mygetch ()» на «getchar ()» - в первую очередь потому, что я говорю, применяется к этому и может не применить к функции «Mygetch ()»; У нас нет спецификации того, что эта функция делает на EOF.

В качестве альтернативы, если вы должны использовать strcat(), Вам все еще нужно следить за длиной строки, но вы можете сделать:

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

Не так элегантно, как все это - используя strcat() В контексте сверхугольника. Вы могли бы, я полагаю, простым подсчетом и многократно используете strcat(pass, c), но это имеет квадратичное поведение, как strcat() должен пропустить 0, 1, 2, 3, ... персонажи на последующих итерациях. Напротив, раствор, где DST указывает на нуль в конце струны, означает, что strcat() не нужно ничего пропустить. С добавлением фиксированного размера 1 символа, однако, вы, вероятно, лучше с первой петлей.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top