Ошибка segmentation error
После выполнения одной из функций в программе выходит ошибка segmentation error, как ее исправить

Все что находится в BookContact.txt
Sergey_Kotomkin:154:8(777)777-77-77:
Maks_Loxin:84:8(952)748-41-70:
Andrey_Serov:14:8(952)747-42-70:
Aleks_Sagin:14:8(952)509-08-07:
Dimon_Wanow:17:8(785)124-47-45:
Сам код
#include <stdio.h> //Для printf, fprintf, fopen, fclose
#include <string.h>
#include <stdlib.h>
#define FNAME "BookContact.txt" //Указываем файл для удобства
void startMenu(){ //В нем выдается стартовое меню
printf("---------------------Main Menu---------------------\n");
printf("This is the phone book of the company 'YptRemont'\n");
printf("What do you want to do?\n");
printf("1. View book\n");
printf("2. Find by ...\n");
printf("3. Book editor\n");
printf("4. Exit\n");
printf("---------------------Main Menu---------------------\n");
getsVvod(); //вызом метода ввода
}
void getsVvod(){
char vvod;
scanf("%d", &vvod); //Считываем ввод пользователя
if (vvod == 1) //если ввод равен 1 то вызываем метод ViewBook
{
ViewBook();
}
else if (vvod == 2) //если ввод равен 2 то вызываем метод FindBy
{
FindBy();
}
else if (vvod == 3) //если ввод равен 3 то вызываем метод BookEditor
{
BookEditor();
}
else if (vvod == 4) //если ввод равен 4 то вызываем метод Exit
{
Exit();
}
else // Если не одна из функция не сработала вывод "Ошибки" и запуск метода заново
{
printf("\n \n \nI do not know such a team, return\n \n \n");
startMenu();
}
}
size_t returnCounter(){ //В этом методе считаем колличество строк в файле для получения динамически изменяемтго массива
FILE *file = fopen(FNAME, "r"); //Открываем файл
if (file == NULL) //Если файла нет выдаем ошибку закрываем программу
{
perror("Error opening source file");
return EXIT_FAILURE;
}
size_t counter = 0; // Задаем нужные переменные
int ch, pre = EOF;
while ((ch = fgetc(file)) != EOF) //Проходим весь файл посимвольно и проверяем считываем колличество строк
{
pre = ch;
if (ch == '\n')
++counter;
}
if (pre == EOF) // Эта штука ничего не делает но без нее не работает
{
//Делаем целое ничего
}
else if (pre != '\n') //Если число не равно \n то просто идем дальше
{
++counter;
}
return counter; //Возвращаем число counter
}
int Exit(){ // Самый итересный метод
printf("Exit \n"); //Пишем для наглядности что выходим
exit(0); //Выходим
}
int ViewBook(){ // Метод который выводт все что было считанно из файла
char *tableInfo[returnCounter()][3]; //Тут делается считывание файла и заносится в массив
int i = 0, j = 0; //Для прохода по всему массиву
char neObrabotInfo[256]; //Сюда записываем входные данные
char sep[10] = ":"; //это указание разделителя
char *istr;
FILE *file = fopen(FNAME, "r");
file = fopen("BookContact.txt", "r"); //Открываем файл с возможностью читать(read)
if (file == NULL) // Если файла нет выдаем ошибку
{
perror("Error opening source file");
return EXIT_FAILURE;
}
//Считываение && преобразование строк && запись их в массив
for (i = 0; fgets(neObrabotInfo, 256, file); i++)
{
istr = strtok(neObrabotInfo, sep);
for (j = 0; istr != NULL; j++)
{
tableInfo[i][j] = malloc(strlen(istr) + 1);
strcpy(tableInfo[i][j], istr);
istr = strtok(NULL, sep);
}
}
fclose(file); //Тут заканчивается считывание файла и он закрывается
//Тут мы выводим общую таблицу(опть же просто сделанную через пробелы)
printf(" ""Book Contact""\n");
printf(" Name"" ""|"" ""Cabinet"" " "|"" ""Phone number\n");
printf("-----------------""+""----------------""+""-------------------------\n");
for (int i = 0; i < returnCounter(); i++)//Проход всего массива по высоте
{
for (int j = 0; j < 3; j++)//Проход массива по длинне
{
printf("%s ", tableInfo[i][j]);//Какая классная табуляция для вывода 1000 +1 пробел
}
printf("\n");//Принтим разделитель
}
printf("\n");
}
void FindBy() //Вывод для удобства пользователя что он может сделать
{
printf("Find by \n1. Name\n2. Cabinet\n3. Phone number ");
getVvodFindBy(); //Вызов считывателся
}
void getVvodFindBy(){ //Считываем ввод пользователя и выбор метода
char vvod;
scanf("%d", &vvod); //Считывание что ввел пользователь
if (vvod == 1) //если равно 1 то вызывается метод Name
{
Name();
}
else if (vvod == 2) //если равно 2 то вызывается метод Cabinet
{
Cabinet();
}
else if (vvod == 3) //если равно 3 то вызывается метод PhoneNumber
{
PhoneNumber();
}
else //если не один ввод не подошел выводим"Ошибку" и запускаем метод заново
{
printf("\n \n \nI do not know such a team, return\n \n \n");
FindBy();
}
}
void Name(){ //Поиск по имени
//Опять же используется запихивание данных в массив
char *tableInfo[returnCounter()][3];
int i = 0, j = 0;
char neObrabotInfo[256];
char sep[10] = ":";
char *istr;
FILE *file = fopen(FNAME, "r");
file = fopen("BookContact.txt", "r");
if (file == NULL)
{
perror("Error opening source file");
return EXIT_FAILURE;
}
for (i = 0; fgets(neObrabotInfo, 256, file); i++)
{
istr = strtok(neObrabotInfo, sep);
for (j = 0; istr != NULL; j++)
{
tableInfo[i][j] = malloc(strlen(istr) + 1);
strcpy(tableInfo[i][j], istr);
istr = strtok(NULL, sep);
}
}
fclose(file); //конец запихивание данных в массив
char vvod[256]; //Создем буфер куда будем записывать выбор пользователя
printf("Search by name\nEnter in format FirstName_SecondName\n"); // Визуальная составляющая
scanf("%s", &vvod); //Сканируем
//выводим стандартную таблицу
printf(" Name"" ""|"" ""Cabinet"" ""|"" ""Phone number\n");
printf("-----------------""+""----------------""+""-------------------------\n");
for (int i = 0; i < returnCounter(); i++) //проходим по высоте массива, не используя горизонтальный проход так как он не нужен если мы сравниваем по имени
{
char name[100];
sscanf(tableInfo[i][0], " %79[^:]:%s:", &name); //Та же функция что scanf толь эта для массива
if (strcmp(name, vvod) == 0) // Сравнение имени и ввода
{
printf("%s %s %s\n", tableInfo[i][0], tableInfo[i][1], tableInfo[i][2]); // Класный вывод да)
}
}
}
void Cabinet(){ // поиск по кабинету
//Опять считывание файла и запись в масив
char *tableInfo[returnCounter()][3];
int i = 0, j = 0;
char neObrabotInfo[256];
char sep[10] = ":";
char *istr;
int maxZero;
FILE *file = fopen(FNAME, "r");
file = fopen("BookContact.txt", "r");
if (file == NULL)
{
perror("Error opening source file");
return EXIT_FAILURE;
}
for (i = 0; fgets(neObrabotInfo, 256, file); i++)
{
istr = strtok(neObrabotInfo, sep);
for (j = 0; istr != NULL; j++)
{
tableInfo[i][j] = malloc(strlen(istr) + 1);
strcpy(tableInfo[i][j], istr);
istr = strtok(NULL, sep);
}
}
fclose(file); // заканчиваем считывать файл, снова)
char vvod[256];
/*
Не вижу смысла переписывать коментарии которые уже описанны выше
*/
printf("Cabinet Search\n");
scanf("%s", &vvod);
printf(" Name"" ""|"" ""Cabinet"" ""|"" ""Phone number\n");
printf("-----------------""+""----------------""+""-------------------------\n");
for (int i = 0; i < returnCounter(); i++)
{
// сканирует из строки кабинет (должно)
char kabinet[10];
sscanf(tableInfo[i][1], " %79[^:]:%s:", &kabinet);
// да, такое сравнение нормальное, == тут не работает
if (strcmp(kabinet, vvod) == 0)
{
printf("%s %s %s\n", tableInfo[i][0], tableInfo[i][1], tableInfo[i][2]);
}
}
}
void PhoneNumber() // Тот же метод как поиск по кабинету и имени. Коментарии опять одинаковые тут лишь изменяется горизонтальное число в массиве так как номер идет 2 в массиве
{
char *tableInfo[returnCounter()][3];
int i = 0, j = 0;
char neObrabotInfo[256];
char sep[10] = ":";
char *istr;
FILE *file = fopen(FNAME, "r");
file = fopen("BookContact.txt", "r");
if (file == NULL)
{
perror("Error opening source file");
return EXIT_FAILURE;
}
for (i = 0; fgets(neObrabotInfo, 256, file); i++)
{
istr = strtok(neObrabotInfo, sep);
for (j = 0; istr != NULL; j++)
{
tableInfo[i][j] = malloc(strlen(istr) + 1);
strcpy(tableInfo[i][j], istr);
istr = strtok(NULL, sep);
}
}
fclose(file);
char vvod[256];
printf("Search by number\nEnter in format X(XXX)XXX-XX-XX\n");
scanf("%s", &vvod);
printf(" Name"" ""|"" ""Cabinet"" ""|"" ""Phone number\n");
printf("-----------------""+""----------------""+""-------------------------\n");
for (int i = 0; i < returnCounter(); i++)
{
char phoneNum[256];
sscanf(tableInfo[i][2], " %79[^:]:%s:", &phoneNum);
if (strcmp(phoneNum, vvod) == 0) //Крутое сравнение
{
printf("%s %s %s\n", tableInfo[i][0], tableInfo[i][1], tableInfo[i][2]);
}
}
}
void BookEditor(){ //Это штука дл редактирования
//В этот раз без прохода по массиву
printf("Что вы хотите сделать\n");
printf("1. Create\n");
printf("2. Delete(Удаление последней строки)\n");
char vvod;
//У меня почему то выводил постоянно ошибку Segmentation Error поэтому записал так -_(-_-)_-
scanf("%d", &vvod);
if (vvod == 1)//Вызов Метода создать если сработало
{
Create();
}
else if (vvod == 2) //Вызов метода удалить если сработало
{
Delite();
}
else
{ //Вывод если ничего не сработало
printf("\n \n \nI do not know such a team, return\n \n \n");
}
}
void Create(){ //Метод создания
char vvod[256];
printf("Введтите запись типа:\n");
printf("First_SecondName:KabNumber:X(XXX)XXX-XX-XX:\n");
scanf("%s", &vvod);
// Открываем файл с помощью расширения ab(открытие для записи в конце)
FILE *file = fopen(FNAME, "ab");
fprintf(file, "\n%s", vvod); // Впихиваем в конец считанную строку от пользователя
fclose(file); // закрываем файл
}
void Delite() //Метод удаления
{
}
int main() //Главный метод который запускае меню
{
startMenu();
}
Ответы (1 шт):
Автор решения: Harry
→ Ссылка
Вы портите стек - кодом наподобие
char vvod;
scanf("%d", &vvod);
При этом, так как указан формат %d, записываются 4 байта, а памяти в char vvod; в стеке только один байт. Три байта выходят за границы допустимого, что уже само по себе UB, и переписывают что-то в стеке, приводя к такому вот завершению программы.