Одна конкретная ссылка на переменную пропускается - PullRequest
0 голосов
/ 12 февраля 2019

Кажется, что %s в окончательном printf полностью пропускается.

Весь код:

#include <stdio.h>

int main(void){
    char address[100];
    char city[100];
    char state[2];
    char zip[15];

    printf("Enter street address: ");
    scanf(" %[^\n]",&address);

    printf("Enter city: ");
    scanf(" %[^\n]",&city);

    printf("Enter state: ");
    scanf(" %s",&state);

    printf("Enter ZIP Code: ");
    scanf(" %s",&zip);

    printf("%s\n%s, %s %s",address,city,state,zip);

    return 0;
}

Когда этот адрес введен:

1 Main Street
New York City, NY 12345

Программа печатает:

1 Main Street
, NY 12345

Я не могу выяснить причину этой проблемы.
Любая помощь будетБуду очень признателен, потому что у меня нет идей.

Ответы [ 3 ]

0 голосов
/ 12 февраля 2019

Следующий код хорошо работает на моей рабочей станции.

#include <stdio.h>
int main(void){
    char address[100];
    char city[100];
    char state[2];
    char zip[15];
    printf("Enter street address: ");
    scanf(" %[^\n]",address);
    printf("Enter city: ");
    scanf(" %[^\n]",city);
    printf("Enter state: ");
    scanf(" %s",state);
    printf("Enter ZIP Code: ");
    scanf(" %s",zip);
    printf("%s\n%s, %s %s",address,city,state,zip);
    return 0;
}
0 голосов
/ 12 февраля 2019

Как отмечено в комментариях и других ответах, у вас есть ряд проблем.Первые два, которые немедленно вызывают неопределенное поведение :

  1. Попытка прочитать состояние "NY" в виде строки в char state[2];.Чтобы быть допустимой строкой в ​​C, символы должны заканчиваться символом nul-terminating .Это означает, что для хранения двухсимвольной аббревиатуры необходимо 3-х символьное хранилище (минимум).Например, {'N', 'Y', '\0'}.(Мастер @ JonathanLeffler сделал вывод, как непосредственное последствие короткого хранения для state может привести к тому, что символ '\0' будет сохранен как первый символ в city, в результате чего city станет пустым-string);
  2. При чтении строк с помощью scanf вы должны предоставить указатель на достаточный объем памяти для строки, которую вы читаете.Поскольку address, city, state, zip являются символьными массивами, при обращении они преобразуются в указатель на первый символ (см .: Стандарт C11 - 6.3.2.1 Другие операнды - L-значения, массивы и обозначения функций (p3) )Таким образом, каждый из них уже является указателем при использовании в качестве аргумента для scanf, и никакой оператор '&' (адрес) не должен предшествовать им в списке аргументов.

Дополнительные примечания, избегайте использования магические числа в вашем коде, кроме случаев, когда это абсолютно необходимо.100, 2, 15 являются магическими числами ниже.

    char address[100];
    char city[100];
    char state[2];
    char zip[15];

Если вам нужна константа для количества символов в address, city, state, zip, #define по одному для каждого или используйте глобальный enum, чтобы сделать то же самое, например,

enum { STSZ = 3, ZIPSZ = 15, CIADDR = 100 };    /* constants */

( note city и address оба 100, поэтому подойдет одна CIADDR константа)

Когда номер абсолютно необходим в вашем коде?При предоставлении модификатора field-width для защиты границ массива при чтении с помощью семейства функций scanf.Кроме того, при использовании семейства scanf вы должны каждый раз проверять возврат .В противном случае может произойти сбой , соответствующий или , (или пользователь может сгенерировать руководство EOF для отмены ввода), и вы будете вслепую продвигаться вперед, используя переменную, которая не была заполнена и, вероятно,оставлено неопределенным, вызывая неопределенное поведение .

Собирая эти кусочки и думая, что вы можете столкнуться с более чем одним адресом в вашем коде, ниже приведен пример, который может прочитатьcity, state zip значения в одной строке текста и значения хранятся в структуре.(который позволяет объявлять массив struct или указатель и выделять его при необходимости при работе с более чем одним адресом позже)

#include <stdio.h>

enum { STSZ = 3, ZIPSZ = 15, CIADDR = 100 };    /* constants */

typedef struct {            /* simple struct presuming in the future */
    char address[CIADDR],   /* you may have more than 1 address */
        city[CIADDR],
        state[STSZ],        /* STSZ must be 3 to read a string of 2-char */
        zip[ZIPSZ];
} loc_t;

int main (void) {

    loc_t location1 = { .address = "" };    /* declare/initialize struct */

    printf ("enter street address: ");      /* prompt/read/validate address */
    if (scanf (" %99[^\n]", location1.address) != 1) {
        fputs ("sscanf() error: invalid address.\n", stderr);
        return 1;
    }

    printf ("enter city: ");                /* prompt/read/validate city */
    if (scanf (" %99[^,],", location1.city) != 1) {
        fputs ("sscanf() error: invalid city.\n", stderr);
        return 1;
    }

    printf ("enter state: ");               /* prompt/read/validate state */
    if (scanf (" %2s", location1.state) != 1) {
        fputs ("sscanf() error: invalid state.\n", stderr);
        return 1;
    }

    printf ("enter zip: ");                 /* prompt/read/validate zip */
    if (scanf (" %14s,", location1.zip) != 1) {
        fputs ("sscanf() error: invalid zip.\n", stderr);
        return 1;
    }

    /* output results preceeded by 2-newlines */
    printf ("\n\n%s\n%s, %s %s\n", location1.address, location1.city,
            location1.state, location1.zip);
}

( note: числа для *Модификаторы 1073 * field-width включены в каждый вызов scanf для защиты границ вашего массива.Кроме того, кратное '\n' перед выводом компенсирует неиспользуемые приглашения, когда все city, state zip вводятся в приглашении "city: ")

Пример использования / Вывод

Ввод "New York City, NY 12345" в виде одной строки в подсказке "enter city: ":

$ ./bin/readaddr
enter street address: 1 Main Street
enter city: New York City, NY 12345
enter state: enter zip:

1 Main Street
New York City, NY 12345

Просмотрите все идайте мне знать, если у вас есть дополнительные вопросы.

0 голосов
/ 12 февраля 2019
#include <stdio.h>

int main(void){
    char address[100];
    char city[100];
    char state[2];
    char zip[15];

    printf("Enter street address: ");
    scanf(" %[^\n]",&address);

    printf("Enter city: ");
    scanf(" %[^\n]",&city);

    printf("Enter state: ");
    scanf(" %s",&state);

    printf("Enter ZIP Code: ");
    scanf(" %s",&zip);

    printf("\nONE: %s\n",address);
    printf("TWO: %s\n",city);
    printf("THREE: %s\n",state);
    printf("FOUR: %s\n",zip);

    return 0;
}

Скопируйте и вставьте это в https://www.codechef.com/ide, и вы увидите следующий вывод:

Enter street address: Enter city: Enter state: Enter ZIP Code: 
ONE: 1 Main Street
TWO: New York City, NY 12345
THREE: 
FOUR: @

Вы храните все в городе, а не останавливаетесь на запятой.Как вы думаете, что делает ваш сканф для города?

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