Задача: По данным n отрезкам необходимо найти множество точек минимального размера, для которого каждый из отрезков содержит хотя бы одну из точек.
В первой строке дано число 1≤n≤100 отрезков. Каждая из последующих n строк содержит по два числа 0≤l≤r≤109, задающих начало и конец отрезка. Выведите оптимальное число m точек и сами m точек. Если таких множеств точек несколько, выведите любое из них.
Мое решение:
void swap(int *a1, int *a2, int M);
void sort(int **a, int N, int M);
void greedy(int **a, int *x, int N);
int main()
{
int **a;//двумерный массив отрезков
int N;
int M=2;
int *x;//одномерный массив точек
cout << "Enter N: "; //ввод количества отрезков
cin>>N;
x = new int[N]; //инициализация массива, который потом станет массивом точек
for (int i=0; i<N; i++)
x[i]=0;
a = new int *[N];
for (int i = 0; i < N; i++)
a[i] = new int [M];
//ввод концов отрезков
for (int i = 0; i < N; i++)
{
for (int j = 0; j < M; j++)
{
cin >> a[i][j];
}
}
//вывод до сортировки
cout <<endl << "Before sorting:" << endl;
for (int i = 0; i < N; i++)
{
for (int j = 0; j < M; j++)
cout << std::setw(3) << a[i][j] << " ";
cout << endl;
}
sort(a, N, M);//сортировка массива
//вывод после сортировки
cout << endl << "After sorting:" << endl;
for (int i = 0; i < N; i++)
{
for (int j = 0; j < M; j++)
cout << setw(3) << a[i][j] << " ";
cout << endl;
}
//вызов функции с жадным алгоритмом
greedy(a,x, N);
for (int i=0; i<=N; i++)
cout<<x[i]<<' ';
system("pause");
return 0;
}
void swap(int *a1, int *a2, int M)//меняет 2 строки местами
{
for (int i = 0; i < M; i++)
{
int temp = a1[i];
a1[i] = a2[i];
a2[i] = temp;
}
}
void sort(int **a, int N, int M)//сортировка пузырьком отрезков по правой точке
{
for (int i = 0; i < N; i++)
for (int j = N - 1; j > i; j--)
if (a[j - 1][1] >a[j][1])
swap(a[j - 1], a[j], M);
}
void greedy(int **a, int *x, int N)
{
int i=0;
int k=0;
while (i<=N)
{
x[k]=a[i][1];
i++;
while ((x[k]>=a[i][0]) && (x[k]<=a[i][1]))
{i++;}
k++;
}
}
Но программа падает с ошибкой: Нарушение прав доступа при чтении. Может, кто видит, почему?
Не понимаю один момент, который заключается в следующем: мне необходимо получить данные из двоичного файла (.bin), куда раннее были записаны данные в виде двух строчек string и двух чисел int (структуры, в общем), при исполнении кода:
void Opf() {
if ((fl = fopen(flName, "rb")) == NULL) {
cout << "Ошибка открытия файла..." << endl;
exit(1);
}
nst = 0;
TBook book;
while (true)
{
int nwrt = fread(&book, sizeof(TBook), 1, fl);
if (nwrt != 1) { break; }
books[nst] = book;
cout << books[nst].name << " " << " " << books[nst].author << " "
<< books[nst].yearof << " " << books[nst].pages << endl;
nst++;
}
fclose(fl);
}
Выдаёт следующую ошибку:
Вызвано необработанное исключение: нарушение доступа для чтения.
**_Pnext** было 0x61747353.
В чём может быть ошибка или же как можно это обойти?
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 |
#include <iostream> #include <ctime> //#include <stdio.h> using namespace std; struct Node { int key; struct Node* next; struct Node* prev; }; class List { private: int key = 0; size_t size = 0; Node* head = NULL; Node* tail = NULL; public: List() { head = tail; size; cout << "List is created!" << endl; } List (int a) { int elementov{}, N{}, K{}, tmpHand[100] = {}, tmpRand{}; if (a == 2) Rand(); if (a == 1) Hand(); cout << "Elements are created!" << endl; } ~List() { Node* current = head; while (current != 0) { Node* next = current->next; delete current; current = next; } head = 0; cout << "Destructor deleted list!" << endl; } Node* Get_node(int number); Node* Create_node(int key); void Insert(const int key); void Print(); void Pop_front(); void Swap(Node* const before1, Node* const before2); void Append(const int num); int Get_Value(int N); void Inverse_sublist(const int K, const int N); void Hand(); void Rand(); }; // получение адреса элемента по его порядковому номеру (счет от 1 ) Node* List::Get_node(int number) { int i; Node* scan = this->head; if (scan == nullptr) return 0; for (i = 1; i < number; i++) scan = scan->next; return scan; } void List::Hand() { int tmpHand[100]{}, elementov{}; for (int i = elementov; i > 0; i--) { cout << "Введите элемент списка: n" << endl; cin >> tmpHand[i]; Append(tmpHand[i]); } } void List::Rand() { int tmpRand{}, elementov{}; for (int i = 0; i < elementov; i++) { tmpRand = rand() % 100; Insert(tmpRand); } } Node* List::Create_node(int key) { Node* new_node = (Node*)malloc(sizeof(Node)); if (new_node) { new_node->key = key; new_node->next = NULL; } return new_node; } // вставка элемента в начало списка void List::Insert(const int key) { Node* add = Create_node(key); if (this->head != NULL) add->next = this->head; this->head = add; this->size++; } // вывод списка на экран void List::Print() { Node* scan = this->head; printf("List items: "); while (scan) { printf("%d -> %p ", scan->key, scan->next); scan = scan->next; } } // удаление элемента из начала ЛОС void List::Pop_front() { Node* del = this->head; this->head = del->next; free(del); this->size--; } // обмен местами двух элементов ЛОС void List::Swap(Node* const before1, Node* const before2) { Node* self1, * self2, * tmp; // before1 = Get_node(list, N1-1); // before2 = Get_node(list, N2-1); self1 = before1->next; self2 = before2->next; tmp = before1->next; before1->next = before2->next; before2->next = tmp; tmp = self1->next; self1->next = self2->next; self2->next = tmp; } void List::Append(const int num) { Node* const add_node = Create_node(num); this->size++; // если список пуст if (!this->head) { this->head = this->tail = add_node; } this->tail->next = add_node; this->tail = add_node; } int List::Get_Value(int N) { Node* tmp = Get_node(N); return tmp->key; } void List::Inverse_sublist(const int K, const int N) { int i, j; Node* left = Get_node(K - 1); if (left == nullptr) return; Node* right; for (i = 0; i < N / 2; i++) { //right = left->next;//может быть сделать так? right = left; for (j = 0; j < (N - 2 * i) && right->next != nullptr; j++) right = right->next; Swap(left, right); left = left->next; } } //-------------------------------------------------------------- int main(int argc, char* argv[]) { //logo(); printf("В списке целых ненулевых элементов инвертировать K элементов начиная с Nn"); srand((unsigned int)time(NULL)); int i = 0, tmpRand = 0; int tmpHand[100] = {}; //ClassList::Node* node_a = 0; //ClassList::Node* node_b = 0; FILE* config; char Conf_Name[50] = "testo.cfg", buffer[100]; int sposob{}, elementov{}, K{}, N{}; if ((config = fopen(Conf_Name, "r")) == NULL) { puts("Config file error!!!"); puts("Press Enter!!!"); std::cin.get(); exit(0); } fgets(buffer, 80, config); if (!strstr(buffer, "#!MYCONFIG")) { puts("Config file error!!!"); puts("Press Enter!!!"); std::cin.get(); fclose(config); exit(0); } while (true) { fgets(buffer, 80, config); if (feof(config))break; if (buffer[0] == '#')continue; if (buffer[0] == '!') { puts(buffer); continue; } if (strstr(buffer, "sposob=")) { sposob = atoi(buffer + strlen("sposob=")); continue; } if (strstr(buffer, "elementov=")) { elementov = atoi(buffer + strlen("elementov=")); continue; } if (strstr(buffer, "K=")) { K = atoi(buffer + strlen("K=")); continue; } if (strstr(buffer, "N=")) { N = atoi(buffer + strlen("N=")); continue; } } puts("=============Result of parsing config file ========"); cout << "sposob = " << sposob << endl; cout << "elementov = " << elementov << endl; cout << "K = " << K << endl; cout << "N = " << N << endl; cout << "Press Enter!!!" << endl; std::cin.get(); fclose(config); if (elementov > 20) { printf("Слишком много элементов в списке! Выход...n"); return 1; } if (sposob != 1 && sposob != 2) { printf("Некорректный способ заполнения спискаn"); return 1; } if (K + N > elementov) { printf("Некорректные данные в конфигурационном файле (N + K > элементовn)"); return 1; } if (N > elementov) { printf("Некорректные данные: количество инвертируемых элементов больше чем элементов в спискеn"); return 1; } // "объект" ЛОС с инициализацией List list(sposob); list.Print(); list.Inverse_sublist(K, N); list.Print(); } |
I am currently working on the BlackJack project, but there is an error showing «exception Unhandled: Unhandled exception thrown: read access violation. this was 0x4.». I am not quite sure which part I did wrong, and the program sometimes runs normally sometimes shows that exception. In draw_card function, it returns a value of a random number. For example: if we get 13, the value will be 10. It also returns the name of the card and the type of the card such as 13 corresponds to king.
int main()
{
srand(time(0));
unsigned bet;
int player = 0 , dealer = 0;
string card , type;
cout << "You have $100. Enter bet: ";
cin >> bet;
cout << "Your cards are:" << endl;
player += draw_card(card, type, player);
cout << " "+card + " of " + type << endl;
player += draw_card(card, type, player);
cout << " " + card + " of " + type << endl << endl << endl;
}
int draw_card(string& card, string& type, int drawer_points) {
int randomNumber; //between 1 and 13
int suite; //between 1 and 4 to determine the suite of the card.
randomNumber = rand() % 13 + 1;
suite = rand() % 4 + 1;
card = getRank(randomNumber);
type = getSuit(suite);
if (randomNumber == 13 || randomNumber == 12 || randomNumber == 11) {
return 10;
}else if (randomNumber == 1) {
int ace1 = 21 - (drawer_points + 1);
int ace2 = 21 - (drawer_points + 11);
return ace1 < ace2 ? 1 : 11;
}
else
{
return randomNumber;
}
}
string getSuit(int suit) {
switch (suit)
{
case 0:
return "spades";
break;
case 1:
return "clubs";
break;
case 2:
return "diamonds";
break;
case 3:
return "hearts";
break;
default:
break;
}
}
string getRank(int rank) {
switch (rank)
{
case 13:
return "King";
break;
case 12:
return "Queen";
break;
case 11:
return "Jack";
break;
case 1:
return "Ace";
break;
case 2:
return "Two";
break;
case 3:
return "Three";
break;
case 4:
return "Four";
break;
case 5:
return "Five";
break;
case 6:
return "Six";
break;
case 7:
return "Seven";
break;
case 8:
return "Eight";
break;
case 9:
return "Nine";
break;
case 10:
return "Ten";
break;
default:
break;
}
user438383
5,5858 gold badges28 silver badges41 bronze badges
asked Jan 18, 2022 at 18:12
5
You generate
suite = rand() % 4 + 1;
This is a random number between 1 and 4 inclusive.
You then call
getSuit(suite);
But getSuit
only has switch branches for values between 0 and 3 inclusive:
switch (suit)
{
case 0:
return "spades";
break;
case 1:
return "clubs";
break;
case 2:
return "diamonds";
break;
case 3:
return "hearts";
break;
default:
break;
}
Not returning a value from a function that is declared to return a value is undefined behaviour.
answered Jan 18, 2022 at 18:27
konsolaskonsolas
1,00111 silver badges24 bronze badges
A few functions like getSuit
and getRank
in your code don’t return a value if only the default case of their switch
statement is executed.
You can return an empty string in the default cases:
default:
return ""; // empty string
And in the call site, check to see if the returned value is empty using the empty
function.
Another way is to use std::optional<T>
like below:
std::optional<string> getSuit( const int suit )
{
switch (suit)
{
case 0:
return "spades";
case 1:
return "clubs";
case 2:
return "diamonds";
case 3:
return "hearts";
default:
return { }; // empty optional
}
}
And in the call site:
std::optinal<std::string> type { getSuit(suite) };
if ( type ) // if optional has value
{
// extract and use the value inside of optional
type.value( );
}
Keep in mind that if the optional does not have a value, using value()
will throw. You can use value_or()
instead which does not throw.
answered Jan 18, 2022 at 18:28
digito_evodigito_evo
3,1742 gold badges13 silver badges40 bronze badges
2
#c #pointers #exception #null #sdl
#c #указатели #исключение #null #sdl
Вопрос:
Всякий раз, когда я запускаю свою программу, я получаю исключение, генерируемое для двух отдельных строк кода, если я закомментирую одну из них, проблема переходит к другой, но обе ссылаются на одну и ту же переменную.
GameScreenManager.cpp:
#pragma once
#include <SDL.h>
#include "Commons.h"
#include "GameScreenManager.h"
#include "GameScreenLevel1.h"
#include "GameScreen.h"
GameScreenManager::GameScreenManager(SDL_Renderer* renderer, SCREENS startScreen)
{
SDL_Renderer* mRenderer;
mRenderer = NULL;
ChangeScreen(startScreen);
}
GameScreenManager::~GameScreenManager()
{
mRenderer = NULL;
delete mCurrentScreen;
mCurrentScreen = NULL;
}
void GameScreenManager::Render()
{
mCurrentScreen->Render();
}
void GameScreenManager::update(float deltaTime, SDL_Event e)
{
mCurrentScreen->Update(deltaTime, e);
}
void GameScreenManager::ChangeScreen(SCREENS newScreen)
{
//Clear up the old screen
if (mCurrentScreen != NULL)
{
delete mCurrentScreen;
}
GameScreenLevel1* tempScreen;
switch (newScreen)
{
case SCREEN_INTRO:
break;
case SCREEN_MENU:
break;
case SCREEN_LEVEL1:
tempScreen = new GameScreenLevel1(mRenderer);
mCurrentScreen = (GameScreen*)tempScreen;
tempScreen = NULL;
break;
case SCREEN_LEVEL2:
break;
case SCREEN_GAMEOVER:
break;
case SCREEN_HIGHSCORES:
break;
default:
break;
}
}
GameScreenManager.h:
#pragma once
#ifndef _GAMESCREENMANAGER_H
#define _GAMESCREENMANAGER_H
#include <SDL.h>
#include "Commons.h"
class GameScreen;
class GameScreenManager
{
private:
SDL_Renderer* mRenderer;
GameScreen* mCurrentScreen;
public:
GameScreenManager(SDL_Renderer* renderer, SCREENS startScreen);
~GameScreenManager();
void Render();
void update(float deltaTime, SDL_Event e);
void ChangeScreen(SCREENS newScreen);
};
#endif //_GAMESCREENMANAGER_H
В настоящее время проблема возникает в строке 24;
mCurrentScreen->Render();
Однако, если я закомментирую эту строку, она появится в строке 29:
mCurrentScreen->Update(deltaTime, e);
«Возникло необработанное исключение: нарушение доступа для чтения.
это был nullptr. произошло »
Комментарии:
1. Программа часто вылетает за много миль от того места, где на самом деле была ошибка. Сообщение об ошибке
this
было nullptr предполагает, что вы должны выяснить, почемуthis
это былоnullptr
. БылоmCurrentScreen = (GameScreen*)tempScreen;
пропущено?
Ответ №1:
По-видимому, поле mCurrentScreen имеет значение NULL при вызове Render() или update() . Либо защитите вызовы, проверив mCurrentScreen на NULL:
void GameScreenManager::Render()
{
if (mCurrentScreen != NULL)
mCurrentScreen->Render();
}
void GameScreenManager::update(float deltaTime, SDL_Event e)
{
if (mCurrentScreen != NULL)
mCurrentScreen->Update(deltaTime, e);
}
или убедитесь, что установлен mCurrentScreen перед вызовом Render() или Update() .
Комментарии:
1. Я добавил операторы if, чтобы проверить, является ли mCurrentScreen != NULL, и действуйте соответственно, однако я все равно получаю исключение, однако на этот раз для операторов if.
2. установите для mCurrentScreen значение NULL после удаления его в ChangeScreen()
3.Если
mCurrentScreen
не гарантируется, что перед его использованием будет указано на что-то безопасное, вы обречены окружать каждое использование сif (mCurrentScreen != NULL)
помощью . Это воспроизводит ошибку, потому что вы будете постоянно находить случаи, когда она не была установлена. и не проверялось. Вам гораздо лучше убедиться, что этоmCurrentScreen
всегда указывает на что-то безопасное.4. Я установил mCurrentScreen равным NULL после удаления mCurrentScreen и все равно получаю исключение. Я даже полностью удалил этот оператор if и все равно не повезло.
5. Если исключение генерируется в операторе if, вероятно, что-то не так с вашей сборкой — попробуйте очистить / перестроить, удалить все промежуточные файлы и т.д. Вы также должны инициализировать mCurrentScreen равным NULL в конструкторе, но это не поможет вам создавать исключения для «if».
Ответ №2:
Как оказалось, я фактически пропустил строку кода, которая устанавливала mCurrentScreen, и оператор switch проходил неправильно, поэтому он не срабатывал. Кроме того, переменная mRenderer не была настроена правильно ни в одном из моих файлов cpp, поэтому она возвращала «Недопустимый рендеринг» всякий раз, когда я пытался его использовать. Ниже приведен рабочий код, спасибо всем за помощь, он направил меня в правильном направлении;
#pragma once
#include <SDL.h>
#include "Commons.h"
#include "GameScreenManager.h"
#include "GameScreenLevel1.h"
#include "GameScreen.h"
GameScreenManager::GameScreenManager(SDL_Renderer* renderer, SCREENS startScreen)
{
mRenderer = renderer;
GameScreen* mCurrentScreen = NULL;
ChangeScreen(startScreen);
}
GameScreenManager::~GameScreenManager()
{
mRenderer = NULL;
delete mCurrentScreen;
mCurrentScreen = NULL;
}
void GameScreenManager::Render()
{
mCurrentScreen->Render();
}
void GameScreenManager::Update(float deltaTime, SDL_Event e)
{
mCurrentScreen->Update(deltaTime, e);
}
void GameScreenManager::ChangeScreen(SCREENS newScreen)
{
//Clear up the old screen
if (mCurrentScreen != NULL)
{
delete mCurrentScreen;
}
GameScreenLevel1* tempScreen;
switch (newScreen)
{
case SCREEN_INTRO:
break;
case SCREEN_MENU:
break;
case SCREEN_LEVEL1:
tempScreen = new GameScreenLevel1(mRenderer);
mCurrentScreen = (GameScreen*)tempScreen;
tempScreen = NULL;
break;
case SCREEN_LEVEL2:
break;
case SCREEN_GAMEOVER:
break;
case SCREEN_HIGHSCORES:
break;
default:
break;
}
}