Сложность использования входов в C (мнение?) - PullRequest
0 голосов
/ 12 июня 2019

Я прыгал с текста на текст и обнаружил, что использование функций ввода в C на самом деле не обсуждается до половины. Есть ли способ безумия? Является ли получение пользовательского ввода в C таким сложным предметом, который не считается базовым уровнем знаний?

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

Ответы [ 3 ]

3 голосов
/ 13 июня 2019

Вот мои собственные "правила" для ввода в C. (Они несколько самоуверенны, но это то, что вы просили.)

  1. Никогда не используйте scanf или fscanf.
  2. Если вы читаете строчный текст, читайте строки, используя fgets или эквивалентный, а затем анализируйте при необходимости.(Я обычно использую свою собственную функцию getargs для удаления слов, которая в некоторой степени эквивалентна strtok.)
  3. Если вы читаете нестрочный текст, либо читайте отдельные символы, используя getc, или напишите свой собственный лексический анализатор, который читает токены.
  4. Если вы читаете двоичный ввод, напишите свои собственные функции для чтения любых двоичных структур, которые вы читаете.Запишите их в терминах функций, таких как get16 и get32, которые читают 16- или 32-байтовые целые числа.(Это достаточно просто, чтобы писать машинно-независимым от порядка байтов способом).Для других типов данных используйте fread.
  5. . Не пытайтесь определить структуру C, соответствующую внешнему макету хранилища, и используйте fread, чтобы прочитать все сразу.

Для получения дополнительной информации, вы можете увидеть раздел 12.5 или остальную часть раздел 12 , а затем раздел 17 в этих C ПрограммированиеЗаметки к курсу .См. Также раздел 10.8 для получения дополнительной информации о разбиении строки текста на разделенные пробелами слова.

2 голосов
/ 12 июня 2019

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

В реальном мире, где вы пытаетесь решить реальную проблему с помощью своего кода, а не просто выполняете упражнения по изучению языка, вы не будете иметь дело с подобными вещами в C, если это не очень незначительная вещь в код. Вместо этого вы должны использовать такой язык, как Python, для таких задач.

По сути, по той же причине вы не слишком много знаете о том, как программировать эффективные умножения матриц для больших матриц в Python. Если вам действительно нужно сделать это в вашей программе на Python (и вы по каким-то причинам не можете использовать существующие библиотеки), ответом будет код модуля C и его импорт в Python.

Существуют способы уменьшить головную боль, по крайней мере, на 90% или другое произвольно большое число, которое меньше 99, следуя этим рекомендациям: Всякий раз, когда вы хотите что-то прочитать от пользователя, читайте целую строку. Не используйте scanf. Используйте fgets, чтобы прочитать всю строку, а затем обработайте ее с помощью sscanf. И также не забывайте всегда проверять возвращаемое значение. Вот пример:

#define bsize = 100;

char buffer[bsize];
int x,y;
float f, g;
int r;

printf("Enter two integers: ");
fflush(stdout); // Make sure the printf is executed before reading
if(! fgets(buffer, bsize, stdin)) {
    fprintf(stderr, "An error occured\n");
    exit(1);
}

if((r = sscanf(buffer, "%d%d", &x, &y)) != 2) {
    fprintf(stderr, "An error occured. You entered:\n%s\n" buffer);
    fprintf(stderr, "%d successful conversions", r);
    exit(1);
}

printf("Enter a float and a char: ");
fflush(stdout);
if(! fgets(buffer, bsize, stdin)) {
    fprintf(stderr, "An error occured\n");
    exit(1);
}

if((r = sscanf(buffer, "%f%f", &f, &g)) != 2) {
    fprintf(stderr, "An error occured. You entered:\n%s\n" buffer);
    fprintf(stderr, "%d successful conversions", r );
    exit(1);
}

printf("You entered %d %d %f %f\n", x, y, f, g);

Это часто излишне, и код становится довольно большим, но метод чтения строки сначала, а затем ее обработки значительно облегчает отладку в большинстве случаев. Кроме того, это избавляет вас от головной боли при очистке входного буфера. Я мог бы упомянуть, что fflush(stdin) - неопределенное поведение, поэтому не используйте его.

Я также хочу отметить, что fgets поместит символ новой строки в буфер, так что вы можете удалить его. Один из способов это сделать buffer[strcspn(buffer, "\n")] = 0

0 голосов
/ 13 июня 2019

Так что я абсолютно признателен за все вводимые данные, чтобы указать мне правильное направление более подходящих функций Си, fgets (). Однако комментарий @KonradRudolph к ОП действительно поразил суть вопроса ссылкой на работу Бьярна Страуструпа: Изучение стандарта C ++ как нового языка . Во введении он использует cin vs scanf в качестве темы для обсуждения, чтобы продемонстрировать объем кода, необходимый для использования scanf с той же функциональностью, что и cin. Я просто собираюсь опубликовать код C ++ и полученный код C. Если вы новый парень, как я, я очень рекомендую прочитать работу Страуструпа. Это очень поучительно.

cin с C ++:

#include<iostream> / / get standard I/O facilities
#include<string> / / get standard string facilities

int main()
{
    using namespace std; / / gain access to standard library

    cout<< "Please enter your first name:\n";
    string name;
    cin>> name;
    cout<< "Hello" << name<< ´\n´;
}

scanf в C с функциональностью почти cin:

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

void quit() / / write error message and quit
{
    fprintf(stderr,"memory exhausted\n") ;
    exit(1) ;
}

int main()
{
    int max= 20;
    char* name= (char*)malloc(max) ; / / allocate buffer
    if(name== 0) quit() ;

    printf("Please enter your first name:\n") ;

    while(true) { / / skip leading whitespace
        int c= getchar() ;
        if(c== EOF) break; / / end of file
        if(!isspace(c)) {
            ungetc(c,stdin) ;   
            break;
        }
    }

    int i= 0;
    while(true) {
        int c= getchar() ;
        if(c== ´\n´ || c== EOF) { / / at end; add terminating zero
            name[i] = 0;
            break;
        }
        name[i] = c;
        if(i==max-1) { / / buffer full
            max= max+max;
            name= (char*)realloc(name,max) ; / / get a new and larger buffer
            if(name== 0) quit() ;
        }
        i++;
    }

    printf("Hello%s\n",name) ;
    free(name) ; / / release memory
    return 0;
}

Я еще не запускал его код, но планирую в ближайшее время, к сожалению, работа на первом месте.

Таким образом, ответ прост: да, входные данные в C являются довольно сложными и требуют более значительного опыта, чем понимание новичка, чтобы эффективно их использовать. Особенно, если мы говорим о scanf, который, как я понимаю, сейчас не является предпочтительным методом. Однако это хороший пример, так как, по моему опыту, scanf, как правило, является первой функцией ввода, которой обучают в большинстве текстов, и я отсканировал множество из них. Мысль кажется, что решение проблемы входных данных делает большое упражнение мысли.

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...