Сбой программы ближе к концу компиляции

У меня есть программа для ввода и сохранения в структурах. Структуры предназначены для контактных данных, имени, адреса и номеров телефонов. Моя программа работает нормально, я могу ввести всю свою информацию в программу, однако, когда я пытаюсь получить результаты printf, программа вылетает на полпути. Я думаю, это может быть проблема с памятью или ее повреждение, или что-то в этом роде. Причина, по которой я думаю, что это может быть связано с повреждением, заключается в том, что если я отключу часть своей программы и скомпилирую ее, вместо сбоя программы я получаю ошибку «Ошибка проверки времени выполнения # 2, стек вокруг переменной 'optionAddress' был поврежден». Вот моя программа

#define _CRT_SECURE_NO_WARNINGS

#include <stdio.h>
#include "contacts.h"
int main(void)
{
    // Declare variables here:

    struct Name names;
    char optionName;
    struct Address addresses;
    char optionAddress;
    struct Numbers number;
    char optionCell;
    char optionHome;
    char optionBusiness;

    // Display the title

    printf("Contact Management System\n");
    printf("-------------------------\n");

    // Contact Name Input:

    printf("Please enter the contact's first name: ");
    scanf("%s", &names.firstName);
    printf("Do you want to enter a middle initial(s)? (y or n): ");
    scanf("%s", &optionName);
    while (optionName == 'y' || optionName == 'Y') {
        printf("Please enter the contact's middle initial(s): ");
        scanf("%s", &names.middleInitial);
        break;
    }
    printf("Please enter the contact's last name: ");
    scanf("%s", &names.lastName);

    // Contact Address Input:

    printf("Please enter the contact's street number: ");
    scanf("%s", &addresses.streetNumber);
    printf("Please enter the contact's street name: ");
    scanf("%s", &addresses.street);
    printf("Do you want to enter an apartment number? (y or n): ");
    scanf("%s", &optionAddress);
    while (optionAddress == 'y' || optionAddress == 'Y') {
        printf("Please enter the contact's apartment number: ");
        scanf(" %c", &addresses.apartmentNumber);
        break;
    }
    printf("Please enter the contact's postal code: ");
    scanf("%s", &addresses.postalCode);
    printf("Please enter the contact's city: ");
    scanf("%s", &addresses.city);

    // Contact Numbers Input:

    printf("Do you want to enter a cell phone number? (y or no): ");
    scanf("%s", &optionCell);
    while (optionCell == 'y' || optionCell == 'Y') {
        printf("Please enter the contact's cell phone number: ");
        scanf(" %c", number.cell);
        break;
    }
    printf("Do you want to enter a home phone number? (y or n): ");
    scanf("%s", &optionHome);
    while (optionHome == 'y' || optionHome == 'Y') {
        printf("Please enter the contact's home phone number: ");
        scanf(" %c", &number.home);
        break;
    }
    printf("Do you want to enter a business phone number? (y or n): ");
    scanf("%s", &optionBusiness);
    while (optionBusiness == 'y' || optionBusiness == 'Y') {
        printf("Please enter the contact's business phone number: ");
        scanf(" %c", number.business);
        break;
    }

    // Display Contact Summary Details

    printf("Contact Details\n");
    printf("---------------\n");
    printf("Name Details\n");
    printf("First name: ");
    printf("%s", names.firstName);
    printf("\nMiddle initials(s): ");
    printf("%s", names.middleInitial);
    printf("\nLast name: ");
    printf("%s", names.lastName);
    printf("\n\nAddress Details\n");
    printf("Street number: ");
    printf("%s", addresses.streetNumber);
    printf("\nStreet name: ");
    printf("%s", addresses.street);
    printf("\nApartment: ");
    printf("%s", addresses.apartmentNumber);
    printf("\nPostal code: ");
    printf("%s", addresses.postalCode);
    printf("\nCity: ");
    printf("%s", addresses.city);
    printf("\n\nPhone Numbers: ");
    printf("\nCell phone number: ");
    printf("%s", number.cell);
    printf("\nHome phone number: ");
    printf("%s", number.home);
    printf("\nBusiness phone number: ");
    printf("%s", number.business);

    // Display Completion Message

    printf("\n\nStructure test for Name, Address, and Numbers Done!");

    return 0;
}

И структуры в заголовочном файле:

// Structure type Name declaration
struct Name {
    char firstName[31];
    char middleInitial[7];
    char lastName[36];
};

// Structure type Address declaration
// Place your code here...

 struct Address {
    char streetNumber;
    char street[41];
    char apartmentNumber;
    char postalCode[8];
    char city[41];
 };

 // Structure type Numbers declaration
 // Place your code here...

 struct Numbers {
    char cell[21];
    char home[21];
    char business[21];   
 };

Моя программа достигает точки распечатки "Street number: ", а затем перестает работать. Появляется окно ошибки Windows, а не окно компилятора.

StreetNumber - это символ, но вы вводите его как строку: scanf("%s", &addresses.streetNumber);

Nikolai Shevchenko 13.03.2018 06:03

при компиляции всегда включайте предупреждения, а затем исправляйте эти предупреждения. (для gcc, at a minimum use: -Wall -Wextra -Wconversion -pedantic -std = gnu11`) Это заставляет компилятор выводить 10 предупреждений, в основном о строке формата для вызовов scanf(), где спецификатор ввода / формата не соответствует данным, которые нужно установить.

user3629249 13.03.2018 17:16

при вызове любой из функций семейства scanf() 1) всегда проверяйте возвращаемое значение, чтобы убедиться, что операция прошла успешно. 2) При использовании спецификатора %s и / или %[...] всегда включайте модификатор максимального количества символов, который на 1 меньше длины входного буфера, поскольку эти спецификаторы всегда добавляют к входному байт нулевой байт. Это также позволяет избежать любой возможности переполнения буфера с его результирующим неопределенным поведением и возможным событием ошибки сегментации.

user3629249 13.03.2018 17:19

относительно: scanf(" %c", &addresses.apartmentNumber); Номер моей квартиры - 764, который не умещается в одном символе. Фактически, почти все номера квартир состоят из нескольких символов и могут быть такими, как: 22A, поэтому не являются строго числовыми.

user3629249 13.03.2018 17:27

по поводу: char postalCode[8]; этого недостаточно для многих почтовых индексов. Например, в Америке почтовый индекс состоит из 5-значного числа, пробела или тире, 4-значного числа. Поле из 8 символов достаточно велико только для 5-значного числа, терминатора NUL и еще 2 символов.

user3629249 13.03.2018 17:33
Стоит ли изучать PHP в 2026-2027 годах?
Стоит ли изучать PHP в 2026-2027 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
0
5
57
2

Ответы 2

scanf("%s", &optionName);

Это вызывает неопределенное поведение, которое может привести к ошибке времени выполнения, которую вы получаете, поскольку optionName - это один байт char, а scanf() с% s попытается записать '\0', который, несомненно, выйдет за рамки

Вместо этого я попытался сделать optionName [2], однако, когда я это делаю, циклы while для параметров перестают работать, и в конце программа по-прежнему дает сбой. Следует ли мне изменить optionName другим способом?

user9411342 13.03.2018 05:05

Вы можете оставить optionName как char и изменить scanf на scanf ("% c", & optionName); так что он позаботится о пробелах от предыдущего сканирования

Pras 13.03.2018 05:13

My program reaches the point of printing out "Street number: " then stops working.

Взгляни на:

 struct Address {
    char streetNumber;    // declared as character!
    char street[41];
    char apartmentNumber; // character
    char postalCode[8];
    char city[41];
 };

char optionName;
char optionAddress;
char optionCell;
char optionHome;
char optionBusiness;

Позже вы попытаетесь прочитать значения персонажам:

scanf("%s", &optionName);
scanf("%s", &optionAddress);
scanf("%s", &optionCell);
scanf("%s", &optionHome);
scanf("%s", &optionBusiness);

scanf("%s", &addresses.streetNumber); // <-------------- string read

используя строковый формат %s. Это вызывает UB, поскольку вы читаете как минимум 2 байта. "y" - это строка с нулевым символом конца строки '\0'. Этот дополнительный байт перезаписывает ячейку памяти. Измените объявления переменных на строки или формат чтения на символьный, как вы уже делаете здесь:

  scanf(" %c", &addresses.apartmentNumber);

Пока все номера улиц находятся между -128 и 127, он должен быть в порядке :)

David C. Rankin 13.03.2018 08:41

Другие вопросы по теме