У меня есть программа для ввода и сохранения в структурах. Структуры предназначены для контактных данных, имени, адреса и номеров телефонов. Моя программа работает нормально, я могу ввести всю свою информацию в программу, однако, когда я пытаюсь получить результаты 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, а не окно компилятора.
при компиляции всегда включайте предупреждения, а затем исправляйте эти предупреждения. (для gcc, at a minimum use: -Wall -Wextra -Wconversion -pedantic -std = gnu11`) Это заставляет компилятор выводить 10 предупреждений, в основном о строке формата для вызовов scanf(), где спецификатор ввода / формата не соответствует данным, которые нужно установить.
при вызове любой из функций семейства scanf() 1) всегда проверяйте возвращаемое значение, чтобы убедиться, что операция прошла успешно. 2) При использовании спецификатора %s и / или %[...] всегда включайте модификатор максимального количества символов, который на 1 меньше длины входного буфера, поскольку эти спецификаторы всегда добавляют к входному байт нулевой байт. Это также позволяет избежать любой возможности переполнения буфера с его результирующим неопределенным поведением и возможным событием ошибки сегментации.
относительно: scanf(" %c", &addresses.apartmentNumber); Номер моей квартиры - 764, который не умещается в одном символе. Фактически, почти все номера квартир состоят из нескольких символов и могут быть такими, как: 22A, поэтому не являются строго числовыми.
по поводу: char postalCode[8]; этого недостаточно для многих почтовых индексов. Например, в Америке почтовый индекс состоит из 5-значного числа, пробела или тире, 4-значного числа. Поле из 8 символов достаточно велико только для 5-значного числа, терминатора NUL и еще 2 символов.





scanf("%s", &optionName);
Это вызывает неопределенное поведение, которое может привести к ошибке времени выполнения, которую вы получаете, поскольку optionName - это один байт char, а scanf() с% s попытается записать '\0', который, несомненно, выйдет за рамки
Вместо этого я попытался сделать optionName [2], однако, когда я это делаю, циклы while для параметров перестают работать, и в конце программа по-прежнему дает сбой. Следует ли мне изменить optionName другим способом?
Вы можете оставить optionName как char и изменить scanf на scanf ("% c", & optionName); так что он позаботится о пробелах от предыдущего сканирования
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, он должен быть в порядке :)
StreetNumber - это символ, но вы вводите его как строку:
scanf("%s", &addresses.streetNumber);