Я делаю банковскую программу по заданию, и мне необходимо создать 2 функции поиска: одну для поиска учетной записи по номеру счета, а другую для поиска учетных записей по именам. Поиск по номеру работает отлично, не работает только поиск по имени. Вот код, который я использую:
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
typedef struct node
{
char name[30];
struct node* NEXT;
}nodeT;
char* searchName(nodeT* top);
void main() {
nodeT* headPtr = NULL;
nodeT test;
printf("Name: ");
scanf("%s", test.name);
printf("%s", searchName(headPtr));
}
char* searchName(nodeT* top)
{
nodeT* temp = top;
char searchName[30];
int found = 0;
printf("Search name: ");
fgets(searchName, 29, stdin);
found = 0;
while (temp != NULL)
{
if (strcmp(searchName, temp->name) == 0)
{
printf("Name: %s", temp->name);
found = 1;
return;
}
temp = temp->NEXT;
}
if (found == 0)
{
printf("Your search was not found\n");
}
}
Выход:
Name: example
Search name: example
Name: example
Exception thrown at 0x00007FFAA42DAC87 (ucrtbased.dll) in MRE.exe: 0xC0000005: Access violation reading location 0x0000000000000066.
Он распечатает результаты запроса, но затем остановит программу. Как я могу это исправить?
Я должен предположить, что проблема в возврате, но я не уверен.
Первоначально у меня был fgets там дважды, потому что он пропускал ввод.
Кроме того, вы говорите, что searchName()
возвращает char *
, но у вас есть return;
, который ничего не возвращает и в конце отсутствует возврат. Последующий printf()
— неопределенное поведение.
@AKX Цикл while()
защищает от этого.
@AllanWind От чего защищается?
@AKX Уважение NULL-указателя. Чтобы ответить на исходный вопрос, оператору следует ожидать запроса «Имя поиска:», читаемой строки и вывода «Ваш поиск не найден\n».
@AllanWind Да, и я никогда не упоминал о возможном разыменовании нулевого указателя – я указывал на логическую проблему: никогда не назначать что-либо headPtr
перед передачей вперед...
Что вы сделали, чтобы попытаться отладить этот код? Можете ли вы поделиться тем, что вы узнали и какие у вас есть гипотезы относительно возможных проблем?
searchName()
должен возвращать char *
, но вы ничего не возвращаете. Это означает, что ваша программа демонстрирует неопределенное поведение.
scanf("%s", ...)
всегда должно включать максимальную ширину поля 1
меньше размера буфера, чтобы защититься от переполнения буфера. Я использовал макрос str(NAME_LEN)
, чтобы сгенерировать его и убедиться, что строка выделена с помощью NAME_LEN+1
.
fgets(..., size, ...)
размер должен быть размером буфера и не 1
меньше его. Предпочитайте использовать sizeof
или ссылаться на ту же символическую константу (NAME_LEN
), которая изначально использовалась для выделения буфера.
fgets()
сохраняет завершающую новую строку. Вы, вероятно, хотите это лишить.
searchName()
: удалите переменную found
при возврате, если значение найдено. Это означает, что found=0
после цикла while
, поэтому нет смысла его проверять.
searchName()
: удалите переменную temp
, поскольку аргументы передаются по значению в c, поэтому это уже копия, которую вы можете изменить по мере необходимости.
Для итерации отдавайте предпочтение от for
до while
.
В main()
вы заполняете test
, но не используете его и запрашиваете у пользователя вторую строку в searchName()
. Наименьшим изменением было удаление интерактивной части из main()
, однако теперь вы выполняете рефакторинг своего кода, чтобы бездействие пользователя происходило только в main()
, и передаете строку поиска в качестве аргумента.
main()
: printf()
ожидает строку, и хотя моя реализация выведет «(null)», это похоже на неопределенное поведение, поэтому я добавил вокруг него защиту.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define str(s) str2(s)
#define str2(s) #s
#define NAME_LEN 29
typedef struct node
{
char name[NAME_LEN+1];
struct node* NEXT;
}nodeT;
char* searchName(const nodeT* top)
{
char searchName[NAME_LEN+1];
printf("Search name: ");
fgets(searchName, sizeof searchName, stdin);
searchName[strcspn(searchName, "\n")] = '\0';
for(; top; top = top->NEXT) {
if (strcmp(searchName, top->name) == 0)
{
printf("Name: %s\n", top->name);
return top->name;
}
}
printf("Your search was not found\n");
return NULL;
}
int main() {
nodeT* headPtr = NULL;
const char *s = searchName(headPtr);
if (s) printf("%s\n", s);
nodeT *headPtr2 =
&(nodeT) { "hello",
&(nodeT) { "word",
&(nodeT) { "test", NULL
}
}
};
const char *s2 = searchName(headPtr2);
if (s2) printf("%s\n", s2);
}
Пример запуска:
Search name: test
Your search was not found
Search name: test
Name: test
test
@chux-ReinstateMonica Готово.
headPtr = NULL;
, а затемsearchName(headPtr)
– что вы ожидаете?