Несколько вопросов о синтаксисе Си - PullRequest
0 голосов
/ 19 октября 2011

У меня есть несколько вопросов о синтаксисе C.

  1. ch = (char *) malloc( sizeof( char ) * strlen(src) ); Что означают первые скобки (char *)?

  2. c=getch();

    switch(c) {

    case '1' :{

    Мой учитель спросил, почему используются кавычки «такого типа», а не «двойные». Я сказал, что это синтаксис Си, если используется переменная char. Но он сказал НЕТ! Почему используются одинарные кавычки, а не двойные?

  3. Иногда при использовании scanf ничего не происходит, и его использовали два раза для сканирования чего-либо. В чем причина этой проблемы? Например:

    printf("enter string \n");   
    scanf("%s",&str);
    printf("enter char \n");  
    scanf("%c",&ch);  //does not scan my char
    scanf("%c",&ch);  //with this second line do scan my char
    

Ответы [ 8 ]

10 голосов
/ 19 октября 2011

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

Когда вы вводите character и нажимаете клавишу ВВОД, в буфер ввода помещаются два символа: character и символ newline.

Вам необходимо учесть оба эти момента. Поэтому сначала scanf потребляет символ новой строки, а другой читает символ.

Пошаговый анализ кода:

printf("enter string \n");   
scanf("%s",&str);

С двумя приведенными выше утверждениями вы видите Enter the string, и программа ожидает вашего ввода. Предположим, вы ввели символ C и один раз нажали Enter. При выполнении этого действия входной буфер получает два символа:

  1. введенный вами символ C &
  2. Символ новой строки \n

Оператор scanf читает только один символ (C) из входного буфера. Таким образом, символ newline остается непрочитанным в буфере Inuput.

printf("enter char \n");  
scanf("%c",&ch);  //does not scan my char

При наличии двух приведенных выше операторов отображается enter char, но scanf просто пропускает (не ожидает ввода пользователя), это потому, что непрочитанный символ newline во входном буфере читается этим scanf.

Таким образом, для правильного получения следующего входного символа вам понадобится дополнительный scanf.

scanf("%c",&ch);  //with this second line do scan my char
5 голосов
/ 19 октября 2011
ch = (char *) malloc( sizeof( char ) * strlen(src) );

(char*) - это актерский состав. Он говорит, что обрабатывать возвращаемое значение malloc как указатель на char. Однако в этом нет необходимости, поскольку void*, тип возвращаемого значения malloc совместим по присваиванию со всеми переменными указателя в C.

Более того, sizeof(char) является поддельным с sizeof(char) == 1 по определению. Наконец, это распределение почти наверняка выделяет один элемент слишком мало. Там должно быть место для нулевого терминатора.

Итак, вероятно, следует написать:

ch = malloc(strlen(src)+1);

Что касается '1', то это char литерал. Имеет тип int.

Это не слишком путать с "1", который является строковым литералом типа char*, указателем на блок памяти, содержащий два символа, '1', за которым следует \0.


Что касается вопроса 3, мне не ясно, что вы имеете в виду, и в любом случае я буду ссылаться на один вопрос за раз, чтобы оправдать его решение! Другие ответили вам за это.

4 голосов
/ 19 октября 2011

Проще говоря:

1), так как malloc возвращает указатель типа void, вы приводите этот указатель к указателю типа char так, чтобы переменная ch позже содержала массив символов (строку)

2) одинарные кавычки в основном используются, потому что оператор switch в C всегда ожидает INTEGER, а не строку.символ, заключенный в одинарные кавычки, возвращает целочисленное представление символа.

3) Это распространенная проблема при использовании scanf, в основном это вызвано возвратом каретки, введенным с предыдущего scanf.Я бы порекомендовал вам всегда очищать ввод перед использованием.

Вот пример:

#include <stdio.h>

int main (void)
{
    char line[200];
    while(1)
    {
        printf("\nenter a string: ");
        fflush(stdout);         // safety flush since no newline in printf above
        scanf(" %[^\n]",line);  // note space character
        printf("you entered >%s<\n",line);
    }
    return 0;
}
2 голосов
/ 19 октября 2011

В:

char *ch = (char *) malloc( sizeof( char ) * strlen(src) );

Первый (char *) возвращает возвращаемое значение в char *. В C это совершенно не нужно, и может маскировать ошибку до #include <stdlib.h>.

Кроме того, sizeof(char) всегда 1, поэтому никогда не требуется.

Символьный литерал '1' имеет тип int в C .

Скорее всего getch возвращает int. Строковый литерал "1" состоит из двух символов. Цифра 1 и символ конца строки NUL. Если бы вы использовали case "1":, возвращаемое значение getch сравнивалось бы со значением указателя на "1" (после неявного преобразования в int).

Что касается scanf, буфер ввода может содержать ввод, который не был обработан вашей программой.

См. Также Почему все говорят, что не следует использовать scanf? Что я должен использовать вместо этого? .

2 голосов
/ 19 октября 2011
  1. Это заклинание; он обрабатывает возвращаемое значение malloc (a void*) как char*.

  2. Это обычный char литерал.

1 голос
/ 19 октября 2011
  1. (char *) - это приведение ; это означает «обрабатывать следующее значение как указатель на char». В данном конкретном случае это избыточно и считается плохой практикой.

  2. '1' - символьная константа ; несколько неинтуитивно, он имеет тип int (это отличается от C ++, где символьные константы имеют тип char). «1» будет строковой константой , которая на самом деле является выражением массива типа char [2] и имеет содержимое {'1', 0}.

  3. Это потому, что во входном потоке осталась новая строка из предыдущей операции ввода. Предположим, вы набрали «foo» и нажали «Return»; тогда входной поток будет содержать символы 'f', 'o', 'o', '\ n'. Первый вызов scanf читает и назначает "foo" для str, оставляя завершающий символ '\ n' во входном потоке. Эта случайная новая строка выбирается следующим вызовом scanf, потому что спецификатор преобразования %c не пропускает пробелы (в отличие от любого другого спецификатора преобразования).

1 голос
/ 19 октября 2011
  1. (char ) в начале первого оператора является типизированным.По умолчанию malloc возвращает void , который можно назначить для символа *, но в других случаях требуется приведение типов.

  2. Вы должны использовать одинарные кавычки вокруг символов.

  3. Сказать, что scanf иногда не работает, - бессмысленное утверждение без примера кода.

0 голосов
/ 27 декабря 2013

Я хотел бы добавить в ответ @Alok Save s. Однако он правильно проанализировал, для этого случая существует другое простое решение, которое заключается в использовании scanf с пробелами в строковом формате следующим образом:

scanf(" %c", &variable);

Это потому, что% c не воспринимает символ новой строки, как другие (например,% d). Любой пробел в строке формата заставит сканирование поглотить все последовательные пробелы, тем самым устраняя необходимость в другом операторе scanf.

Надеюсь, это поможет!

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