Member 13933893 Ответов: 1

Как сравнить 2 пароля от пользовательского ввода и записи в файл только с помощью системных вызовов


Привет ребята,

Я изучаю язык Си, мне нужно знать, как принимать входные данные от пользователя и сравнивать их с помощью системных вызовов.

Мне не разрешается использовать какие-либо библиотечные функции, так как они дают ошибку при компиляции с shellforge,

Может ли кто-нибудь помочь мне с тем же самым.

Что я уже пробовал:

Я очень новый ученик, так что любая помощь будет оценена по достоинству.

Я знаю о функции записи, но не могу обойти эту программу.

1 Ответов

Рейтинг:
1

Jochen Arndt

Если вы осознаете, что write() функция вы также должны быть осведомлены о read() функция. Для чтения с клавиатуры передайте ноль в качестве первого параметра (дескриптор файла стандартный ввод).

Использовать while цикл для чтения отдельных символов и хранения их в массиве до появления новой строки ('\n') происходит (пользователь нажал клавишу ENTER). Сохраните количество символов, прочитанных в переменной, и/или завершите строку нулевым байтом.

Сравните эти два массива. Первая проверка-это сравнение длин, которые были сохранены в переменных после чтения пользовательского ввода. Если они не совпадают, сравнение не удалось. В противном случае итерации по массивам, используя for цикл сравнения каждого символа до тех пор, пока не возникнет несоответствие (сравнение не удалось) или цикл не завершится (сравнение удалось).

Наконец использовать open() чтобы создать файл для записи выходных данных.

Если вам нужно описание системных функций, вы можете использовать справочные страницы Linux, такие как read(2) - Страница руководства Linux[^]. Их можно просто найти, поискав в интернете "man 2 <function_name>". "2" - это раздел man-страницы для системных вызовов. Все функции из этого раздела должны быть пригодны для использования с Шеллфордж.


Member 13933893

#включить <stdio.h>


тап_п()
{
int fd;
имя пользователя char[10];
int ret;

fd = open("test.text", O_CREAT | O_RDWR,0666);
if(fptr == -1)
{
printf("ошибка!");
выход(1);
}

printf("введите свое имя пользователя");
ret = read(0, username, 10);
write(fd,username,strlen(username));



@User-2223753 | Йохен, это то, что у меня есть до сих пор, пожалуйста, вы можете направлять меня дальше.
Дайте мне знать, если я на правильном пути и как именно продолжить сравнение двух паролей. если можно было бы предоставить какой - либо пример кода.

Jochen Arndt

printf() и strlen () - это библиотечные функции языка Си. Вы должны использовать write(1, ...) вместо printf. Просто найдите "man printf" (или введите его в оболочке Linux, если таковая имеется), и вы заметите, что они принадлежат к разделу 3, который содержит функции библиотеки C.

Вы также должны использовать цикл для чтения символа за символом с клавиатуры, как описано в моем решении (которое также позволяет избежать использования strlen() при подсчете символов в цикле).

Ваш код будет ждать, пока не будет введено 10 символов, и не добавит нулевой байт, так что strlen() и printf() все равно потерпят неудачу.

Member 13933893

Пройдя через ваши предложения и детали.

Вот что у меня есть до сих пор :
#включить <stdio.h>


тап_п()
{
int fd;
имя пользователя char[10];
char passwordone[15];
char passwordtwo[15];

int ret;
fd = open("test.text", O_CREAT | O_RDWR,0666);
if(fptr == -1)
{
printf("ошибка!");
выход(1);
}

напишите(1,"введите имя пользователя",18);
ret = read(0, username, 10);
write(fd,username,10));

а (1)
{
напишите(1,"введите пароль",18);
читать(0, пароль, 15);

напишите(1,"введите пароль еще раз",25);
читать(0, passwordtwo, 15);

if ( strcmp(passwordone, passwordtwo) == 0)
перерыв;

напишите(1,"Пароли не совпадают",28);
}

напишите(1,"совпадение паролей",20);
запись(fd, passwordone, 15);

возвращает 0;

}


Не могли бы вы дать мне знать , правильно ли это, если нет, то не могли бы вы помочь мне и указать, где находятся ошибки .
Очень ценю вашу помощь
@User-2223753 | Йохен

Jochen Arndt

Вы должны читать отдельные символы в цикле while, например
char kbinput[KBINPUT_SIZE];
char c;
int count = 0;
do
{
 read(0, &c, 1);
 if (c == '\n')
  break;
 kbinput[count++] = c;
}
while (count < KBINPUT_SIZE - 1);
kbinput[count] = 0;


Кроме того: strcmp () - это снова библиотечная функция языка Си.
Вы пробовали "man strcmp", как предлагалось?

Member 13933893

Если бы я запросил вашу дальнейшую помощь, то цикл в основном считывает ввод с клавиатуры и сохраняет его в символе C до тех пор, пока пользователь не нажмет клавишу Enter.

Я не могу получить вторую часть о том, что это делает .

Кроме того, не могли бы вы помочь мне реализовать проверку в моей программе .
Это то, что я сделал, и я не знаю, правильно это или нет .

#включить <stdio.h>


тап_п()
{
int fd;
имя пользователя char[10];
char kbinput[KBINPUT_SIZE];
чар с;
int count = 0;

int ret;
fd = open("test.text", O_CREAT | O_RDWR,0666);
if(fptr == -1)
{
printf("ошибка!");
выход(1);
}

напишите(1,"введите имя пользователя",18);
ret = read(0, username, 10);
write(fd,username,10));


делать
{
читать(0, &c, 1);
если (c == '\n')
перерыв;
kbinput[count++] = c;
}
while (count < KBINPUT_SIZE - 1);
kbinput[count] = 0;
напишите(1,"совпадение паролей",20);
запись(fd, passwordone, 15);

возвращает 0;

}


@User-2223753 | Йохен

Jochen Arndt

Вы должны использовать фрагмент из моего предыдущего поста для каждый входная строка. То есть: для имени пользователя, пароля и passord2.

Member 13933893

@User-2223753 | Йохен, я сделал так , как было предложено , изменил несколько переменных, попросив вас пройти через них и сообщить мне, все ли в порядке. Я не уверен, где происходит сравнение .

Небольшая просьба, если бы вы могли изменить мою программу и показать мне, где я иду не так .

#включить <stdio.h>


тап_п()
{
int fd;
Чара логин;
char kbinput[KBINPUT_SIZE];
чар passwordone;
чар passwordtwo;
int count = 0;

int ret;
fd = open("test.text", O_CREAT | O_RDWR,0666);
if(fptr == -1)
{
printf("ошибка!");
выход(1);
}

напишите(1,"введите имя пользователя",18);
делать
{
read(0, &username, 1);
if (username == '\n')
перерыв;
kbinput[count++] = имя пользователя;
}
while (count < KBINPUT_SIZE - 1);
kbinput[count] = 0;
write(fd,username,10));


напишите(1,"введите пароль",18);
делать
{
read(0, &passwordone, 1);
if (passwordone == '\n')
перерыв;
kbinput[count++] = пароль;
}
while (count < KBINPUT_SIZE - 1);
kbinput[count] = 0;


напишите(1,"введите пароль еще раз",25);
делать
{
read(0, &passwordtwo, 1);
if (passwordtwo == '\n')
перерыв;
kbinput[count++] = passwordtwo;
}
while (count < KBINPUT_SIZE - 1);
kbinput[count] = 0;


напишите(1,"совпадение паролей",20);
запись(fd, passwordone, 15);

возвращает 0;

}

Jochen Arndt

Пожалуйста, потратьте некоторое время и подумайте, прежде чем писать код.

Имеет ли смысл хранить все строки, введенные пользователем, в одном и том же массиве kbinput?

Member 13933893

@User-2223753 , поскольку я очень новичок в codign, спасибо вам за все ваши входные данные , как и было предложено, я создал 3 различных массива( kbinput, kbinputpassone и kbinputpasstwo) . Однако я все еще не уверен, где происходит сопоставление паролей перед записью в файл .

Ниже приводится то, что я делал до сих пор в соответствии с вашими предложениями :
---------

#включить <stdio.h>


тап_п()
{
int fd;
Чара логин;
char kbinput[KBINPUT_SIZE];
char kbinputpassone[KBINPUTPASSONE_SIZE];
char kbinputpasstwo[KBINPUTPASSTWO_SIZE];
чар passwordone;
чар passwordtwo;
int count = 0;

int ret;
fd = открыть("test.txt", O_CREAT | O_RDWR,0666);
если(fd == -1)
{
printf("ошибка!");
выход(1);
}

напишите(1,"введите имя пользователя",18);
делать
{
read(0, &username, 1);
if (username == '\n')
перерыв;
kbinput[count++] = имя пользователя;
}
while (count < KBINPUT_SIZE - 1);
kbinput[count] = 0;
write(fd,username,10);


напишите(1,"введите пароль",18);
делать
{
read(0, &passwordone, 1);
if (passwordone == '\n')
перерыв;
kbinputpassone[count++] = пароль;
}
while (count < KBINPUTPASSONE_SIZE - 1);
kbinputpassone[count] = 0;


напишите(1,"введите пароль еще раз",25);
делать
{
read(0, &passwordtwo, 1);
if (passwordtwo == '\n')
перерыв;
kbinputpasstwo[count++] = passwordtwo;
}
while (count < KBINPUTPASSTWO_SIZE - 1);
kbinputpasstwo[count] = 0;


напишите(1,"совпадение паролей",20);
запись(fd, passwordone, 15);

возвращает 0;

}

------------------------------------------
Хотел бы знать, где происходит сравнение и проверка соответствия пароля, а если этого не происходит, не могли бы вы добавить это для меня и исправить мою программу. Я пройду через него и постараюсь понять все, что вы упомянули, и использовать это в будущем.

Jochen Arndt

Где это должно произойти-совершенно очевидно:
После ввода данных и перед записью в файл.
Затем перечитайте мое решение о том, как это сделать. Это в основном реализация вашей собственной версии memcmp().

Member 13933893

Как и было предложено , я реализовал проверку, чтобы увидеть, совпадают ли длины массивов, попросив вас проверить, правильно ли это или нет, и, если возможно, направлять дальше.

#включить <stdio.h>


тап_п()
{
int fd;
Чара логин;
char kbinput[KBINPUT_SIZE];
char kbinputpassone[KBINPUTPASSONE_SIZE];
char kbinputpasstwo[KBINPUTPASSTWO_SIZE];
чар passwordone;
чар passwordtwo;
int count = 0;
int результат;
int ret;


fd = открыть("test.txt", O_CREAT | O_RDWR,0666);
если(fd == -1)
{
printf("ошибка!");
выход(1);
}

напишите(1,"введите имя пользователя",18);
делать
{
read(0, &username, 1);
if (username == '\n')
перерыв;
kbinput[count++] = имя пользователя;
}
while (count < KBINPUT_SIZE - 1);
kbinput[count] = 0;
write(fd,username,10);


напишите(1,"введите пароль",18);
делать
{
read(0, &passwordone, 1);
if (passwordone == '\n')
перерыв;
kbinputpassone[count++] = пароль;
}
while (count < KBINPUTPASSONE_SIZE - 1);
kbinputpassone[count] = 0;


напишите(1,"введите пароль еще раз",25);
делать
{
read(0, &passwordtwo, 1);
if (passwordtwo == '\n')
перерыв;
kbinputpasstwo[count++] = passwordtwo;
}
while (count < KBINPUTPASSTWO_SIZE - 1);
kbinputpasstwo[count] = 0;


результат = memcmp(passwordone,passwordtwo,10)
если (результат == 0)
напишите(1,"длина пароля равна",25);
еще
запись(1,"длина пароля не совпадает",30);


напишите(1,"совпадение паролей",20);
запись(fd, passwordone, 15);

возвращает 0;

}

Member 13933893

#включить <stdio.h>


тап_п()
{
int fd;
Чара логин;
char kbinput[KBINPUT_SIZE];
char kbinputpassone[KBINPUTPASSONE_SIZE];
char kbinputpasstwo[KBINPUTPASSTWO_SIZE];
чар passwordone;
чар passwordtwo;
int count = 0;
int результат;
int ret;


fd = открыть("test.txt", O_CREAT | O_RDWR,0666);
если(fd == -1)
{
printf("ошибка!");
выход(1);
}

напишите(1,"введите имя пользователя",18);
делать
{
read(0, &username, 1);
if (username == '\n')
перерыв;
kbinput[count++] = имя пользователя;
}
while (count < KBINPUT_SIZE - 1);
kbinput[count] = 0;
write(fd,username,10);


напишите(1,"введите пароль",18);
делать
{
read(0, &passwordone, 1);
if (passwordone == '\n')
перерыв;
kbinputpassone[count++] = пароль;
}
while (count < KBINPUTPASSONE_SIZE - 1);
kbinputpassone[count] = 0;


напишите(1,"введите пароль еще раз",25);
делать
{
read(0, &passwordtwo, 1);
if (passwordtwo == '\n')
перерыв;
kbinputpasstwo[count++] = passwordtwo;
}
while (count < KBINPUTPASSTWO_SIZE - 1);
kbinputpasstwo[count] = 0;


результат = memcmp(passwordone,passwordtwo,10)
если (результат == 0)
напишите(1,"длина пароля равна",25);
еще
запись(1,"длина пароля не совпадает",30);


напишите(1,"совпадение паролей",20);
запись(fd, passwordone, 15);

возвращает 0;

}

Jochen Arndt

Еще раз: не торопитесь, читайте мои посты и думайте о том, что делать.

"Это в основном реализация вашей собственной версии memcmp()"
Это означает, что вы должны написать код, выполняющий то же самое, что и memcmp (), потому что memcmp () - это библиотечная функция языка Си.

"Первая проверка-это сравнение длин, которые были сохранены в переменных после чтения пользовательского ввода."

Это означает, что вам нужна длина password1 и password2 в двух переменных.

Member 13933893

Привет Йохен , я могу понять , что вы пытаетесь сказать, но я не уверен, как добавить это в мою программу, я пытался искать ссылки, но у меня есть много трудностей в achieiving этого, надеясь, что вы могли бы дать мне дальнейшие указания и ясность в моем коде

Jochen Arndt

Это не поможет вам узнать, если я дал вам готовый к использованию код, когда вы не понимаете, что код на самом деле делает.

Я повторяю: Не торопитесь и подумайте об этом.
Что вам нужно, чтобы сравнить две строки?

Подсказка: чтение документации memcmp() или strcmp() может помочь даже тогда, когда их использование запрещено.

Очевидно, вам нужны две переменные, содержащие две строки. И вам нужна длина для memcmp(). Для strcmp() строки должны быть завершены NULL, потому что это определяет внутреннюю длину (если вы не знаете об этом, прочитайте о строках в C).

Подумайте о коде, который я дал вам для чтения пользовательского ввода. Вы понимаете, что делает этот код?
Я повторяю:
Он считывает отдельные символы, введенные пользователем, и сохраняет их в массиве (входной строке). При этом он подсчитывает количество введенных символов. Он прекращает чтение, когда пользователь нажимает клавишу ENTER, которая обозначается чтением нового символа строки ('\n' resp. 0x0A). Наконец, он добавляет нулевой байт к массиву, чтобы создать допустимую строку C.

Итак, у вас есть массив (входная строка) и его длина.

Сделайте это для всех необходимых пользовательских входов, хранящих результаты в различных переменных. Используйте эти переменные для выполнения дополнительных задач (здесь сравните две строки).

Если у вас есть задача, которая должна быть реализована на языке программирования, выполните анализ, подобный приведенному выше, прежде чем писать любую строку кода.

Затем разбейте его на подзадачи (здесь: чтение ввода с клавиатуры, сравнение строк, запись в файл) и определите, как эти части взаимодействуют друг с другом (здесь: переменные, необходимые для ввода и вывода задач).

Когда все вышесказанное будет сделано, начните реализовывать его с помощью кода.

Member 13933893

char kbinput[KBINPUT_SIZE]; // массив, в котором хранится полная строка.
char c; // единственный символ, который он читает
int count = 0;
делать
{
read(0, &c, 1); // Чтение 1 алфавита в переменную c
if (c == '\n') // когда вы нажмете enter, выйдите из цикла.
перерыв;
kbinput[count++] = c; // увеличивает массив до следующей позиции, чтобы взять следующий алфавит?
}
while (count < KBINPUT_SIZE - 1);
kbinput[count] = 0;

Я не понимаю последних 2 строк, не могли бы Вы уточнить это для меня

Jochen Arndt

С основы:
Массивы, индексы массивов, оператор постинкремента
Цикл while (здесь: не находится вне границ массива доступе)
Строки с нулевым завершением (массив символов)

Member 13933893

Я решаю эту проблему по частям, как это было рекомендовано, и прошу прощения за все вопросы. Я только что сделал код, чтобы открыть файл, прочитать пользовательский ввод и записать его в файл .

Не могли бы вы сказать мне, насколько это верно?

----

тап_п()
{

int fd;

fd = fd("user.dat", O_CREAT | O_RWDR, 0666);
если (fd == -1)
{
напишите(1,"есть ошибка открытия файла",35);
}

напишите(1,"введите имя пользователя",18);


char username[USERNAME_SIZE];
чар с;
int count = 0;
делать
{
читать(0, &c, 1);
если (c == '\n')
перерыв;
имя пользователя[count++] = c;
}
while (count < USERNAME_SIZE - 1);
имя пользователя[count] = 0;

write(fd,username,USERNAME_SIZE);

Jochen Arndt

Как вы думаете, какова цель переменной count?
Это число символов, которое было введено и указывает, какие из элементов входного массива являются допустимыми.

USERNAME_SIZE определяет размер массива и, следовательно, макс. количество символов, разрешенных для ввода, должно быть определено сначала с помощью оператора #define.

Таким образом, вы должны использовать count при записи в файл или экран. В противном случае у вас были бы дополнительные символы мусора в вашем файле или на экране.

Member 13933893

@User-2223753 | Йохен, спасибо за объяснение. Я внес изменения, о которых вы упомянули. Надеюсь, что на этот раз все будет правильно.
Пожалуйста исправьте везде где ошибаетесь и я попробую реализовать то же самое для пароля 1 и пароля 2 а затем позже перейду к сравнению
---

#DEFINE USERNAME_SIZE=10

тап_п()
{

int fd;

fd = fd("user.dat", O_CREAT | O_RWDR, 0666);
если (fd == -1)
{
напишите(1,"есть ошибка открытия файла",35);
}

напишите(1,"введите имя пользователя",18);


char username[USERNAME_SIZE];
чар с;
int count = 0;
делать
{
читать(0, &c, 1);
если (c == '\n')
перерыв;
имя пользователя[count++] = c;
}
while (count < USERNAME_SIZE - 1);
имя пользователя[count] = 0;

write(fd,username,sizeof(count));

закрыть(fd);

возвращает 0;
}

Jochen Arndt

Пожалуйста, прочтите документацию, если вы используете ключевое слово или функцию.

Переменная count содержит число введенных символов if. Вот чего ты хочешь. sizeof () - это фиксированный размер в байтах, который переменная занимает в памяти. Для int это 4 байта на большинстве платформ.

Читайте также об операторе #define. Он не требует '=' и должен быть в нижнем регистре:
#define USERNAME_SIZE 10

Это также можно обнаружить, просто скомпилировав код.

Member 13933893

Итак правильным способом записи в файл будет :
писать(ФД,имя пользователя граф);

fd-это файловый дескриптор, username-массив, count-количество алфавитов, которые нужно записать?

Я надеюсь, что мое понимание этого правильно.

@Пользователь-2223753