C - усеченный ввод массива символов автоматически назначается следующему массиву символов - PullRequest
0 голосов
/ 16 октября 2018

Я пытался ввести 2 массива символов от пользователя.

Я хочу обрезать входные символы, если они больше указанной длины.Это то, что я сделал до сих пор.

int main(){

    printf("Enter Password: ");
    char password[9]= {0};
    fgets(password, sizeof(password), stdin);


    printf("Enter key file path: ");
    char file_path[200];
    fflush(stdin);
    fgets(file_path, sizeof(file_path), stdin);
    puts(file_path);

    return 0;

}

Я получаю этот вывод:

enter image description here

Если я введу более 8chars, он автоматически назначает charcaters выше 8 моему file_path.Он не запрашивает второй вход!

PS: я пробовал scanf("%8s", password) вместо fgets.Та же проблема.

Пожалуйста, помогите, спасибо

1 Ответ

0 голосов
/ 16 октября 2018

В коде OP вход, который не помещается в первый fgets(), остается для последующего ввода.Более качественный код будет занимать всю строку и обнаружит, что строка слишком длинная.

Используйте fgets() с достаточно длинным буфером для поиска неполных строк ввода.
Прочитайте по крайней мереЕще 2 символа: дополнительный символ и '\n'.


Возможно, используйте свой собственный my_gets() для чтения строки.

// Read a line
// If input, without the \n fits in the destination, return `s`
// else return NULL
// Conditions: line != NULL,  0 < sz <= INT_MAX
char *my_gets(char *line, size_t sz) {
  if (fgets(line, (int) sz, stdin) == NULL) {
    line[0] = '\0';
    return NULL; // EOF
  }

  size_t length = strlen(line);
  if (length > 0 && line[length - 1] == '\n') {
    line[--length] = '\0';  // Chop off \n
  } else if (length == sz - 1) {
    // Consume rest of line
    bool looped = false;
    int ch;
    while ((ch = fgetc(stdin)) != '\n' && ch != EOF) {
      looped = true;
    }
    if (looped) {
      return NULL; // Line too long
    }
  }
  return line;
}

Приложение

int main(void) {
    printf("Enter Password: ");
    char password[9];
    if (my_gets(password, sizeof password) == NULL) {
      return EXIT_FAILURE; 
    }
    puts(password);

    printf("Enter key file path: ");
    char file_path[200];
    if (my_gets(file_path, sizeof file_path) == NULL) {
      return EXIT_FAILURE; 
    }
    puts(file_path);

    return EXIT_SUCCESS;
}

С точки зрения безопасности, неплохо бы отсканировать password[] и line[] после того, как с ним будет выполнен код.

memset(password, 0, sizeof password);

Однако вызов fgets(), fgetc() сам по себе не так безопасен, как онне указано "скрывать свои следы" при возвращении.Это более глубокая тема, чем эта статья.

...