Интерактивный, ограничительный, динамический пользовательский ввод - PullRequest
0 голосов
/ 21 сентября 2018

Я предоставил ссылку на PDF инструкции по назначению.

[TL; DR]

Задайте два вопроса: Вы боитесь темноты?Вы тренируетесь?

Ввод: 'Y' для да , 'N' для нет .

Если ввести в второй вопрос - это 'Y' , Один дополнительный вопрос: Использовано минут в день?

Ввод: Целое число> 0. Однако, если меньше 10 в день, неквалифицирован .

Вывод: Сообщает пользователю, могут ли они пройти обучение ниндзя или нет.


Что у меня возникают трудности с :

  1. Динамическое выделение многомерного строкового массива

Я кодирую только около недели, и я понимаю, что это назначение, вероятно, излишне.С учетом вышесказанного у меня возникла идея, выполняя это задание, и, хотя мне сложно сформулировать свою мысль словами, вот изображение, которое, как мне кажется, отражает то, что я «визуализирую».

Визуальное сообщение, опубликованное Стивом Саммитом https://www.eskimo.com/~scs/cclass/int/sx9b.html

В этом конкретном задании, я думаю, что это пустая трата памяти, чтобы сохранить ответ пользователя.Тем не менее, что если я захочу написать программу, которая запрашивает у пользователя ряд входных данных и в конце коррелирует их или создает ложные корреляции для lulz?

Ложные корреляции http://www.tylervigen.com/spurious-correlationsпо Тайлеру Вигену

Более практическая причина, однако, тест типа личности MBTI?Я не знаю точно всех возможностей, но они кажутся захватывающими.

Это то, чего я хочу достичь с помощью динамического выделения многомерного строкового массива


Буду обновлять позже

Исходное сообщение следует ...

Код работает, но некоторые входные данные все еще разрешены, а именно любые символы, введенные, если первый элемент - Y или N.

Вот код:

#include <stdio.h>
#include <string.h>
#include <stdlib.h>

int main() {
    char reference[][2] = { "Y", "N" };
    char (*ptr_reference)[2] = reference;

    int reference_minutes[1] = { 10 };
    int *ptr_reference_minutes = reference_minutes;

    char **user_input;

    user_input = (char**)malloc(3 * sizeof(char*));

    int i;
    for (i = 0; i < 3; i++)  {
        user_input[i] = (char*)malloc(4 * sizeof(char));
    }
    if (!user_input) {
        printf("Could not allocate memory!/n");
        exit(1);
    }

    i = 0;
    while (i == 0) {
        printf("\nAre you afraid of the dark? Choose either [Y/N], and press enter when finished: \n");
        fgets(user_input[i], 4, stdin);
        user_input[i] = realloc(user_input[i], sizeof(char));

        if (strncmp(user_input[i], *ptr_reference, 1) == 0) {
            printf("\nPatience, Young Grasshoper! You are not ready to become a ninja.");
            i = 3;
            break;
        } else if (strncmp(user_input[i], *(ptr_reference + 1), 1) == 0) {
            i++;
            break;
        } else {
            printf("\nPlease enter Y for yes or N for no.\n\n");
            continue;
        }
    }
    while (i == 1) {
        printf("\nDo you exercise? Input [Y/N], and press enter when finished: \n");
        fgets(user_input[i], 4, stdin);

        if (strncmp(user_input[i], *ptr_reference, 1) == 0) {
            i++;
            break;
        } else if (strncmp(user_input[i], *(ptr_reference + 1), 1) == 0) {
            printf("\nDo you even lift, Bro?");
            i = 3;
            break;
        } else {
            printf("\nPlease enter Y for yes or N for no.\n\n");
            continue;
        }
    }
    while (i == 2) {
        int sscanf_result, answer;

        printf("\nHow many minutes a day do you exercise? Type an integer greater than 9 and press enter when finished.\n");
        fgets(user_input[i], 4, stdin);

        sscanf_result = sscanf(user_input[i], "%d", &answer);

        if ((sscanf_result == 0) | (sscanf_result == EOF)) {
            /* either a non-integer entered or an end-of-line */
            printf ("\nYou have to enter an integer!\n");
            i = 2;
            continue;
        } else if (answer < *ptr_reference_minutes) {
            printf("\nCome on! You kids are soft! You lack discipline!\n");
            i = 3;
            break;
        } else {
            printf("\nYou are a good fit for ninja training.\n");

            for (i = 0; i < 3; i++) {
                free(user_input[i]);
            }
            free(user_input);
            user_input = NULL;
            break;
        }
    }
    return 0;
}

Ответы [ 2 ]

0 голосов
/ 21 сентября 2018

@ Serge Ballesta @Serga Ballesta Спасибо за ваши отзывы.Это было чрезвычайно полезно.Следуя вашим советам, я смог написать лучшую программу, хотя я не уверен, что мне удалось добиться успеха в «Keep It Simple, Stupid».

Я до сих пор не могу понять, как ограничитьсимволы после «Y» или «N», т. е. Nnb или Nq принимаются как N и переходят ко второму вопросу.

#include <stdio.h>
#include <string.h>
#include <stdlib.h>

int main (void) {

char *user_input = NULL;
user_input = (char*)malloc(3*sizeof(char));

int sscanf_result, answer;
int i;
while (!*user_input)
{
printf("\nAre you afraid of the dark? \n\nInput Specifications: Please type 'Y' to indicate yes, or 'N' to indicate no, and then press the 'Enter' or 'return' key when finished.\n\n");

i = 0;        
fgets(user_input, sizeof(user_input), stdin);

/* trim off last character */
user_input[strlen(user_input)-1] = '\0';

if (user_input[i]  == 'Y')
{
printf("\nFear of the dark? Fear those who lurk in the dark, my friend. Ninjas! You may not train as a ninja!");

free(user_input);
for (i = 0; i < 3; i++)
{
user_input[i] = '\0';
}
exit(0);
}
else if (user_input[i]  == 'N')
{
free(user_input);
for (i = 0; i < 3; i++)
{
user_input[i] = '\0';
}
printf("\nDo you exercise?\n\nInput Specifications: Please type 'Y' to indicate yes, or 'N' to indicate no, and then press the 'Enter' or 'return' key when finished.\n\n");

i = 0;                           
fgets(user_input, sizeof(user_input), stdin);
user_input[strlen(user_input)-1] = '\0';
if (user_input[i]  == 'N')
{
printf("\nDo you even lift, Bro?\n");

free(user_input);
for (i = 0; i < 3; i++)
{
user_input[i] = '\0';
}
exit(0);
}
else if (user_input[i]  == 'Y')
{
free(user_input);
for (i = 0; i < 3; i++)
{
user_input[i] = '\0';
}
printf("\nHow many minutes a day do you exercise?\n\nInput Specifications: Please type a positive integer and press the 'Enter' or 'return' key when finished.\n\n");

i = 0;                        
fgets(user_input, sizeof(user_input), stdin);
user_input[strlen(user_input)-1] = '\0';

sscanf_result = sscanf(user_input, "%d", &answer);

if ((sscanf_result == 0) | (sscanf_result == EOF))
{
/* either a non-integer entered or an end-of-line */

printf ("\nPlease type a positive integer and then press the 'Enter' or 'return' key when finished.\n");

free(user_input);
for (i = 0; i < 3; i++)
{
user_input[i] = '\0';
}
continue;
}
if (answer < 10)
{
printf("\nCome on! You kids are soft! You lack discipline!\n");

free(user_input);
for (i = 0; i < 3; i++)
{
user_input[i] = '\0';
 }
 exit(0);
 }
else
{
printf("\nYou may begin training as a ninja!\n");

free(user_input);
for (i = 0; i < 3; i++)
{
user_input[i] = '\0';
}
exit(0);
}
}
else
{
printf("\nInput Error: Please carefully read the input specifications that are provided after each question prompt and then try again.\n");

free(user_input);
for (i = 0; i < 3; i++)
{
user_input[i] = '\0';
}
continue;
}
}
else 
{
printf("\nInput Error: Please carefully read the input specifications that are provided after each question prompt and then try again.\n");

free(user_input);
for (i = 0; i < 3; i++)
{
user_input[i] = '\0';
}
continue;
}
}
return 0;
}
0 голосов
/ 21 сентября 2018

Хорошо, я мог бы взглянуть на вашу программу.Проблема не в распределении, а в управлении строками.В C строка представляет собой массив символов с нулевым символом в конце (пожалуйста, скопируйте это 100 раз ...).

Когда вы читаете строку с fgets, вы получаете символ новой строки (\n) в вашембуфер, поэтому, если пользователь наберет Y Введите , вы получите {'Y', '\n', '\0', undeterminated_char }.Следующее realloc тогда совершенно неверно:

  • это, скорее всего, пустяк: компилятор предоставит вам только буфер , по крайней мере такой же большой , как ваше требование.Как 4> 1, он может (и моя реализация сделала) дать исходный буфер неизменным!

Итак, если вы настаиваете на сравнении строк, вам следует только убедиться, что второй символ равен нулю: user_input[i][2] = '\0';

Но ИМХО, что здесь требуется, это просто:

if (user_input[i][0] == 'Y') {
    ...

Это еще не все.Вы пытаетесь проделать большую работу по обработке ввода, но просто забыли одну деталь: если строка длиннее объявленного размера, fgets заполняет ее буфер и оставляет оставшуюся часть строки доступной для следующего чтения.

Ниже следует только мой совет:

Вы пытались использовать все, что знаете (и, вероятно, вещи, которые не полностью освоили ...), в одной простой программе.Не.Сохраняйте каждую программу как можно более простой (Keep It Stupid Simple - это общая полезная практика ...) и доверяйте своему ученику другие задания для других шаблонов.Итак, здесь вы должны:

  • читать строку, пока не найдете \n (может потребоваться несколько fgets)
  • проверить первый символ буфера на 'Y' или 'N'
  • проверьте второй на '\0'

Поскольку это является обычным требованием в реальном мире, и только после того, как ваша программа заработает, вы можете подумать:

  • игнорирование начальных пустых символов
  • принятие нижнего регистра в качестве верхнего регистра
  • принятие любого символа после первого (для принятия Да и Нет)

Последний совет, если хорошее кодирование имеет для вас значение: как только ваша программа работает правильно, вы должны рассмотреть возможность размещения ее в Code Review , чтобы получить интересные комментарии к ней.

...