Уважаемые коллеги! Предлагаем вам разработку программного обеспечения под ключ.
Опытные программисты сделают для вас мобильное приложение, нейронную сеть, систему искусственного интеллекта, SaaS-сервис, производственную систему, внедрят или разработают ERP/CRM, запустят стартап.
Сферы - промышленность, ритейл, производственные компании, стартапы, финансы и другие направления.
Языки программирования: Java, PHP, Ruby, C++, .NET, Python, Go, Kotlin, Swift, React Native, Flutter и многие другие.
Всегда на связи. Соблюдаем сроки. Предложим адекватную конкурентную цену.
Заходите к нам на сайт и пишите, с удовольствием вам во всем поможем.
Вариант А: Задан файл (условно, база данных пользовательских учетных записей UNIX) следующего формата:
# comment8
8
username:password:UID:GID:usercomment:home:shell8
username:password:UID:GID:comment:home:shell8
. . .
username:password:UID:GID:comment:home:shell8
# — символ начала комментария,
8 — символ разделителя записей,
: — символ разделителя полей записи,
comment — незначащий комментарий,
username — имя пользователя (строка),
password — пароль пользователя (строка),
UID — идентификатор пользователя (короткое целое),
GID — идентификатор первичной группы пользователя (короткое целое),
comm — комментарий к учетной записи пользователя (строка),
home — путь к домашнему каталогу пользователя (строка),
shell — путь к начальному интерпретатору пользователя (строка).
Разработать определения типов uid_t, gid_t и следующие функции доступа к записям базы данных:
passwd* getpwnam(char *name);— поиск записи по имени пользователя name;
passwd* getpwuid (uid_t uid);— поиск записи по идентификатору пользователя uid;
passwd* getpwent(); — чтение очередной записи из базы данных;
Функции должны возвращать указатель на структуру следующего вида:
struct passwd
{
char *pw_name;
char *pw_passwd;
uid_t pw_uid;
gid_t pw_gid;
char *pw_gecos;
char *pw_dir;
char *pw_shell;
};
При создании кода надо руководствоваться логикой общения с пользователем. Мысленно проигрывайте желаемый сценарий работы с ним и постепенно добивайтесь его воплощения. Начните разработку с создания удобных структур данных. На этой стадии надо учитывать платформу, предпочтения, оказываемые некоторым библиотечным функциям, желаемый стиль и т.д. Предположим, что нам надо разработать приложение в стиле 70-х годов прошлого века на основе функций библиотеки CRT, прототипы которых описаны в файле заголовков stdio.h. Минимальный набор runtime-библиотек задаем в файле stdafx.h:
#include <stdio.h>
#include <conio.h>
#include <stdlib.h>
#include <string.h>
В файле Users.cpp:
¨ Объявляем новые типы данных. В нашем случае они определены и заданы заказчиком,
¨ Объявляем глобальные структуры данных — они вычисляются на основе опыта разработки с учетом частоты использования всеми функциями приложения.
#include "stdafx.h"
typedef unsigned short uid_t; // Глобальные типы данных
typedef unsigned short gid_t;
struct passwd // Тип структур для описания пользователя
{
char *pw_name;
char *pw_passwd;
uid_t pw_uid;
gid_t pw_gid;
char *pw_gecos; // Comment
char *pw_dir; // Home
char *pw_shell;
};
//===== Глобальные переменные
FILE *fp; // Файловый указатель
const int maxLen = 128; // Ограничитель длины строки при вводе данных
char buf[maxLen+maxLen]; // Буфер должен вместить данные и сообщение
long posUsers; // Позиция начала данных в файле (без учета заголовка)
char extension[] = ".users"; // Предполагаемое расширение файла с данными
char defaultFile[] = "Test.users"; // Тестовый файл с данными
const char delim = ':'; // Символ разделителя полей
Теперь можно приступить к разработке главной функции, вставляя в нее вызовы других, несуществующих пока функций. Все вместе они должны реализовывать желаемую функциональность приложения.
void main()
{
puts ("Users Service. Getting info from users files\n");
while (true) // Псевдо-бесконечный цикл диалога с пользователем
{
char *fileName = 0;
try
{
fileName = GetFileName(); // Выясняем имя файла с учетными записями
OpenUserFile (fileName); // Попытка открыть файл
QueryUser(); // Диалог, запрашивающий и выполняющий операцию с данными
}
catch (char* s)
{
if (strcmp(s, "Stop") == 0) // Нормальное завершение приложения
{
printf ("Users service: Bye\n");
if (fp)
fclose(fp);
break;
}
printf ("\nError: %s", s); // Ненормальное завершение приложения
if (No ("\nTry again? (Y/N)"))
break;
delete [] fileName;
fileName = 0;
}
}
puts ("\n\n");
}
Здесь определены правила игры с функциями: GetFileName, OpenUserFile и QueryUser, No. Их предстоит разработать. Вставив вызовы несуществующих функций, мы задали желаемые сигнатуры новых строительных кирпичей программы. В процессе создания кода придется реализовать еще какие-то другие операции с данными. При этом используется тот же самый прием: добавить вызовы несуществующих функций, затем приступить к их разработке. Теперь попытаемся разработать новые функции. Их надо либо целиком вставлять перед функцией main, либо вставить их прототипы, а затем давать тела (уже в любом порядке).
Я предпочитаю первый стиль — работать без прототипов. При организации диалога с пользователем распространен такой прием — использовать для временного хранения данных общий буфер (глобальный массив buf). Удобство в том, что его не надо чистить. Некоторые данные, введенные пользователем, удобно отложить в сторону, то есть скопировать их в динамически созданный массив (который надо чистить). В связи с этим целесообразно создать несколько служебных функций (своих маленьких утилит):
bool No (char* prompt) // Просим выбрать ответ: Yes or No
{
printf ("\n%s: ", prompt);
return toupper (getche()) != 'Y';
}
bool Yes (char* prompt) // Просим выбрать ответ: Yes or No
{
printf ("\n%s: ", prompt);
return toupper (getche()) != 'N';
}
char* CopyString() // Часто используемая функция. Она копирует буфер в новую память
{
return strcpy (new char[strlen(buf)+1], buf);
}
char* GetLine (char *prompt) // Просим ввести в буфер buf строку (не более maxLen символов)
{
printf ("%s: ",prompt); // Подсказка пользователю (Что мы у него запрашиваем)
fflush (stdin); // Чистим буфер клавиатуры
char c; int i;
for (i = 0; i<maxLen && (c = getchar()) != EOF && c != '\n'; i++) // Посимвольный ввод
buf[i] = c; // Помещаем символ в буфер buf
buf[i] = 0; // Завершаем строку нулем
return buf;
}
Посимвольный ввод, производимый с помощью getchar, позволяет корректно обработать ситуацию, когда число введенных символов превышает емкость буфера.
char* GetString (char* prompt) // Просим ввести строку символов и возвращаем ее копию
{
GetLine (prompt);
return CopyString();
}
short SetShort (char *s) // Преобразуем строку символов (из буфера) в короткое целое
{
char *stop;
long id = strtol (s, &stop, 0);
if (*stop != 0 || id > 0xffff)
throw "SetShort: Wrong ID field";
if (s != buf)
delete [] s;
return (short)id;
}
Следующая функция понадобится при реализации диалога с пользователем.
char Menu()
{
puts (
"\n\n\tFind a user:\n"
"\n\tn - By name"
"\n\ti - By ID"
"\n\tq - Quit\n");
return getch();
}
Приступим к разработке функций, запланированных при создании главной функции main.
char* GetFileName()
{
//===== Просим ввести имя файла или завершить диалог (вводом символа q)
GetLine ("\n\n\tEnter a users file name (q - quit)");
int len = int(strlen(buf));
if (len == 1 && toupper(buf[0]) == 'Q') // Нормальное завершение приложения
throw "Stop";
char* fileName = 0;
if (len == 0) // Если пользователь не задал имя файла, откроем defaultFile
fileName = strcpy (new char[strlen(defaultFile) + 1], defaultFile);
else
{
int n = int(strlen (extension));
// Если пользователь не задал расширения, дополним имя файла расширением extension
Уважаемые коллеги! Предлагаем вам разработку программного обеспечения под ключ.
Опытные программисты сделают для вас мобильное приложение, нейронную сеть, систему искусственного интеллекта, SaaS-сервис, производственную систему, внедрят или разработают ERP/CRM, запустят стартап.
Сферы - промышленность, ритейл, производственные компании, стартапы, финансы и другие направления.
Языки программирования: Java, PHP, Ruby, C++, .NET, Python, Go, Kotlin, Swift, React Native, Flutter и многие другие.
Всегда на связи. Соблюдаем сроки. Предложим адекватную конкурентную цену.
Заходите к нам на сайт и пишите, с удовольствием вам во всем поможем.
Уважаемый посетитель!
Чтобы распечатать файл, скачайте его (в формате Word).
Ссылка на скачивание - внизу страницы.