Страница 1 из 1

Телефонный справочник

Добавлено: 15 мар 2016, 15:20
Kazanove
программа телефонный справочник на структурах ... все как бы работает но если ввести номер телефона равный шести символов то при добавлении следующей записи к предыдущему номеру телефона добавляется фамилия ... плиз хелп
вот исходник

Код: Выделить всё

 #include <stdio.h>
#include <string.h>
#include <windows.h>
int count = 1;

struct phonebook{
	char firstname[20];
	char name[20];
	char lastname[20];
	char street[20];
	char home[4];
	char apartament[4];
	char phone[6];
};

void phonebook();
void line(char, int);
char* Rus(const char* text);
void StringToSpace(char*, int);
void main(void){	
	phonebook();
}
void phonebook(){
	system("cls");
	const int maxRecord = 255;
	static struct phonebook book[maxRecord];
	static int count;
	char select;
	const int size = 5;
	int aWitdhCol[size] = { 20, 20, 20, 30, 10 };
	char *aNameCol[size] = { "Фамилия", "Имя", "Отчетво", "Адрес", "Телефон" };
	int witdh = 0;
	for (int i = 0; i < size; i++){
		witdh += aWitdhCol[i];
	}
	witdh += size - 1;
	printf("%c", char(218));
	line(char(196), witdh);
	printf("%c\n", char(191));
	printf("%c", char(179));
	StringToSpace(Rus("Программа \"Телефонная книга\""), witdh);
	printf("%c\n", char(179));
	printf("%c", char(195));
	line(char(196), witdh);
	printf("%c\n", char(180));
	printf("%c", char(179));
	StringToSpace(Rus("1 - Добавить запись; 0 - выйти из программы"), witdh);
	printf("%c\n", char(179));
	printf("%c", char(195));
	line(char(196), witdh);
	printf("%c\n", char(180));
	printf("%c", char(195));
	for (int i = 0; i < size; i++){
		line(char(196), aWitdhCol[i]);
		if (i != size - 1){
			printf("%c", char(194));
		}
	}
	printf("%c\n", char(180));
	printf("%c", char(179));
	for (int i = 0; i < size; i++){
		StringToSpace(Rus(aNameCol[i]), aWitdhCol[i]);
		printf("%c", char(179));
	}
	printf("\n");
	printf("%c", char(195));
	for (int i = 0; i < size; i++){
		line(char(196), aWitdhCol[i]);
		if (i != size - 1){
			printf("%c", char(197));
		}
	}
	printf("%c\n", char(180));
	for (count; count < maxRecord; count++){
		if (*book[count].firstname == NULL){
			break;
		}
	}
	if (count == 0){
		printf("%c", char(179));
		StringToSpace(Rus("В телефонной книге нет записей"), witdh);
		printf("%c\n", char(179));
	}
	else{
		for (int i = 0; i < count; i++){
			int lenAdress=strlen(book[i].street) + strlen(book[i].home) + strlen(book[i].apartament) + 4;
			printf("%c", char(179));
			StringToSpace(book[i].firstname, aWitdhCol[0]);
			printf("%c", char(179));
			StringToSpace(book[i].name, aWitdhCol[1]);
			printf("%c", char(179));
			StringToSpace(book[i].lastname, aWitdhCol[2]);
			printf("%c", char(179));
			printf("%s, %s, %s", book[i].street, book[i].home, book[i].apartament);
			line(*(" "), aWitdhCol[3]-lenAdress);
			printf("%c", char(179));
			StringToSpace(book[i].phone, aWitdhCol[4]);
			printf("%c\n", char(179));
		}
	}

	printf("%c", char(192));
	for (int i = 0; i < size; i++){
		line(char(196), aWitdhCol[i]);
		if (i != size - 1){
			printf("%c", char(193));
		}
	}
	printf("%c\n", char(217));
	printf(Rus("Введите номер действия: "));
	do{
		select = getchar();
	} while ((select != '0') && (select != '1'));

	if (select == '1'){
		printf(Rus("Добавить новую запись\n"));
		StringToSpace(Rus("Фамилия"), 20);
		scanf("%20s", &book[count].firstname);
		StringToSpace(Rus("Имя"), 20);
		scanf("%20s", &book[count].name);
		StringToSpace(Rus("Отчество"), 20);
		scanf("%20s", &book[count].lastname);
		StringToSpace(Rus("Улица"), 20);
		scanf("%20s", &book[count].street);
		StringToSpace(Rus("№ дома"), 20);
		scanf("%4s", &book[count].home);
		StringToSpace(Rus("№ квартиры"), 20);
		scanf("%4s", &book[count].apartament);
		StringToSpace(Rus("№ телефона"), 20);
		scanf("%6s", &book[count].phone);
		count++;
		phonebook();
	}
}
void line(char simbol, int count){
	for (int i = 0; i < count; i++){
		printf("%c", simbol);
	}
}
void StringToSpace(char *string, int witdh){
	int len = strlen(string);
	int space = witdh - len;
	printf("%s", string);
	line(*(" "), space);
}
char bufRus[256];
char* Rus(const char* text){
	CharToOemA(text, bufRus);
	return bufRus;
}


Re: Телефонный справочник

Добавлено: 15 мар 2016, 17:02
Romeo
Дело в том, что ты работаешь с так называемыми null terminataed строками. Из их называния понятно, что это строки, которые оканчиваются нолём (если быть более точным, то символом '\0'). Функция scanf читает телефонный номер с клавиатуры и записывает его в phone, добавляя в конце нулевой символ. Если ввести 6 символов, функция запишет нулевой символ за границу строки, именно туда, где располагается поле firstname у следующего элемента book. Когда же цикл переходит на следующую итерацию, и пользователь вводит firstname для следующего элемента, то scanf перетирает ноль, который был записан до этого, свежесчитанными символами, и граница между полем phone предыдущей записи и полем firstname текущий записи полностью размывается.

Исправить данную проблему можно с помощью расширения поля phone до 7-ми символов, для того, чтобы терминирующий ноль в любом случае поместился.

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

Re: Телефонный справочник

Добавлено: 15 мар 2016, 19:18
Kazanove
да спасибо я забыл про символ конца массива

Re: Телефонный справочник

Добавлено: 15 мар 2016, 22:06
WinMain
Можно пойти другим путём. Поскольку все поля в структуре имеют тип char и размер полей фиксированный, то можно вообще обойтись без завершающих нулевых символов, а все пустые места в строке заполнять пробелами. Т.е. вся запись в справочнике - это одна сплошная строка. Именно так устроен формат табличных файлов DBF. В нём только заголовок файла бинарный, а все данные - это сплошной текст, даже между записями вместо разделителей пробелы используются или символ * (помечает удалённые записи).