!!!Я должен придерживаться этих функций, так как мне не разрешено использовать другие!!!
Небольшое пояснение, что мне нужно сделать: пользователь вводит каталог поиска, затем, если ничего не найдено, появляется сообщение об ошибке. Если что-то найдено, я создаю массив из одной строки, потому что хотя бы один файл был найден, и он сохраняет имя найденного файла. Затем, если FindNextFIle находит что-либо, я добавляю одну строку в существующий массив, и эта новая строка сохраняет новое найденное имя файла.
Первый вывод — это прямой вывод функции, а второй — тестовый вывод массива, чтобы убедиться, что он работает правильно. Но не получается сказать, что нарушен доступ к памяти, поэтому дальше работать не могу.
Вероятно, есть 2 причины, по которым он не работает правильно:
Вот main()
:
system("chcp 1251");
drtctrAr drctr;
drctr = createDAr();
WIN32_FIND_DATA FindFileData;
HANDLE hf;
hf = FindFirstFile(drctr.str, &FindFileData);
while (hf == INVALID_HANDLE_VALUE)
{
printf("Error opening files or no files found!\n Try changing the search directory or correct your input!\n");
return 1;
break;
}
StringArray fileNames;
int len;
fileNames.str = (wchar_t**)malloc(sizeof(wchar_t*) * fileNames.rows);
len = wcslen(FindFileData.cFileName)+1;
fileNames.sym = (wchar_t*)malloc(sizeof(wchar_t) * len);
wcscpy_s(fileNames.sym, len, FindFileData.cFileName);
while (FindNextFile(hf, &FindFileData) != 0)
{
printf("Found file: %ls", FindFileData.cFileName);
printf("\n");
fileNames.rows++;
fileNames.str = (wchar_t**)realloc(fileNames.str, sizeof(wchar_t*) * (fileNames.rows));
int len = wcslen(FindFileData.cFileName) + 1;
fileNames.str[fileNames.rows-1] = (wchar_t*)malloc(sizeof(wchar_t) * len);
wcscpy_s(fileNames.str[fileNames.rows-1], len, FindFileData.cFileName);
}
FindClose(hf);
freeDAr(drctr);
printSA(fileNames);
filterSA(fileNames);
freeSA(fileNames);
system("pause");
return 0;
А это функция печати в отдельном .cpp
:
void printSA(StringArray arr)
{
printf("...........................\n");
for (int i = 0; i < arr.rows; i++)
{
for(int j=0;j<arr.sym[i];j++)
printf("Current file: %ls", arr.str[i][j]);
printf("\n");
}
}
И саму структуру массива забыл добавить:
struct StringArray
{
wchar_t** str = NULL;
wchar_t* sym = NULL;
int rows = 1;
};
Я упомянул обе возможные причины, к сожалению, это не означает, что это правильное предположение, что-то в самом начале выделения массива может быть неправильным
Куда вылетает по отладчику?
Каким должен быть arr.sym[i]
? Почему вы используете его как j < arr.sym[i]
? Это не имеет никакого смысла.
Кроме того, помните ли вы, что строки в стиле C в C++ должны заканчиваться нулем?
std::vector<std::wstring> fileNames; while (FindNextFile(hf, &FindFileData) != 0) fileNames.push_back(FindFileData.cFileName);
-- и это все, что нужно.
Вы пытались сделать что-то сложным путем (malloc/realloc и т. д.), и у вас есть ошибка. Итак, пришло время научиться делать что-то простым способом с std::vector<std::wstring>
. На данный момент ваш код написан на C, а не на C++, так что самое время немного изучить C++.
И почему вы используете свою собственную явную обработку памяти как для массивов, так и для строк? Почему вы не используете std::vector
и std::wstring
? C++ — это гораздо больше, чем просто «C с классами».
Я не могу использовать какие-либо объектно-ориентированные функции, так как это часть моего курсового проекта. хотел бы, но мне не разрешено. Я должен придерживаться этих функций, std::vector
не является частью программы первого курса, и я делаю курсовой проект в течение первого года. Опять же, я бы хотел, но я не могу ничего использовать из второго курса
В любом случае, здесь есть одна ошибка fileNames.sym = (wchar_t*)malloc(sizeof(wchar_t) * len); wcscpy_s(fileNames.sym, len, FindFileData.cFileName);
должна быть fileNames.sym = (wchar_t*)malloc(sizeof(wchar_t) * (len + 1)); wcscpy_s(fileNames.sym, len + 1, FindFileData.cFileName);
, как уже указал SomeProgrammerDude, но, возможно, вы ее пропустили.
@john нет, это ничего не меняет, все еще ошибка нарушения прав доступа на printf("Current file: %ls", arr.str[i][j]);
в printSA
@ssbssa Вылетает на printf("Current file: %ls", arr.str[i][j]);
в функции печати
Возможно, проблема в объекте StringArray
, но вы этого не опубликовали. На самом деле я думаю, что вам следует научиться пользоваться отладчиком. Кому-то еще сложно отлаживать ваш код, если они видят только его часть.
@Alfredison Хорошо, проблема не в этом.
Вместо этого попробуйте printf("Current file: %ls", arr.str[i]);
, но удалите внутренний цикл for.
@Alfredison Если вы не знаете, как использовать отладчик, то расставляйте операторы печати повсюду, в конце концов вы это отследите (хотя использование отладчика было бы намного быстрее).
@ssbssa теперь даже показывает ucrtbased.pdb not loaded
страницу
@john Проблема в том, что его оператор печати дает сбой.
@ssbssa Я только что понял, что пытался сравнить j со строкой. Я использовал тот же метод создания массива для массива int **, но эта строка содержала количество чисел в строке! Возможно, я неправильно скопировал свой собственный код!
@ssbssa нет, он все еще вылетает именно из-за функции печати. Фу, я не такой уж и манекен
Сбой оператора печати @ssbssa в одном месте не означает, что он будет сбой везде. На самом деле точка, в которой он начинает сбой, (вероятно) близка к точке, где произошло повреждение
fileNames.str = (wchar_t**)malloc(sizeof(wchar_t*) * fileNames.rows); len = wcslen(FindFileData.cFileName)+1; fileNames.sym = (wchar_t*)malloc(sizeof(wchar_t) * len); wcscpy_s(fileNames.sym, len, FindFileData.cFileName);
Эта проблема существует в приведенных выше строках. Вы выделяете память для str
, но не выделяете память для *str
/ str[0]
, что является типом wchar_t*
. Затем вы копируете имя файла в fileNames.sym
вместо fileNames.str[0]
, чтобы сразу не найти ошибку. Затем, если второй файл найден, вы выделяете память для fileNames.str[1]
и копируете в него имя файла. Эта часть правильная.
Таким образом, исключение нарушения прав доступа происходит, когда вы пытаетесь получить доступ к содержимому fileNames.str[0]
, потому что это нераспределенная память. Если вы напечатаете fileNames.str[1]
, это будет успех.
Ниже приведена модифицированная версия, основанная на представленном вами коде. Меня устраивает. Вы можете попробовать.
#include <stdio.h>
#include <windows.h>
typedef struct StringArray
{
wchar_t** str;
int rows;
}StringArray;
void printSA(StringArray arr)
{
printf("...........................\n");
for (int i = 0; i < arr.rows; i++)
{
printf("Current file: %ls", arr.str[i]);
printf("\n");
}
}
int main()
{
system("chcp 1251");
WIN32_FIND_DATA FindFileData;
HANDLE hf;
hf = FindFirstFile(L"D:\\*.txt", &FindFileData);
while (hf == INVALID_HANDLE_VALUE)
{
printf("Error opening files or no files found!\n Try changing the search directory or correct your input!\n");
return 1;
break;
}
StringArray fileNames;
fileNames.rows = 1;
int len;
fileNames.str = (wchar_t**)malloc(sizeof(wchar_t*) * fileNames.rows);
len = wcslen(FindFileData.cFileName) + 1;
fileNames.str[fileNames.rows - 1] = (wchar_t*)malloc(sizeof(wchar_t) * len);
wcscpy_s(fileNames.str[fileNames.rows - 1], len, FindFileData.cFileName);
while (FindNextFile(hf, &FindFileData) != 0)
{
printf("Found file: %ls", FindFileData.cFileName);
printf("\n");
fileNames.rows++;
fileNames.str = (wchar_t**)realloc(fileNames.str, sizeof(wchar_t*) * (fileNames.rows));
int len = wcslen(FindFileData.cFileName) + 1;
fileNames.str[fileNames.rows - 1] = (wchar_t*)malloc(sizeof(wchar_t) * len);
wcscpy_s(fileNames.str[fileNames.rows - 1], len, FindFileData.cFileName);
}
FindClose(hf);
printSA(fileNames);
// TODO: Free pointers
// ...
system("pause");
return 0;
}
Что такое
StringArray
? И почему бы не простоstd::vector<std::wstring>
вместо низкоуровневого кодирования в стилеC
с использованиемmalloc
?