Hjälp med 2-dimensionell array i c++

Permalänk
Medlem

Hjälp med 2-dimensionell array i c++

Hej!
Jag ska göra ett program som slumpar fram tal i en 2-dimensionell array och sen sortera den med avseende på den första kolumnen i första hand.

Jag har 2 problem.
Det första är att när jag ska byta plats på två rader så blir det fel.
Min funktion ser ut så här:

void debug (arr2 array, int i) { cout << array[i][0] << "," << array[i][1] << " " << array[i+1][0] << "," << array[i+1][1] << endl; } void swap (arr2& array, int i) { int temp = array[i][0]; int temp2 = array[i][1]; debug(array, i); array[i][0] = array[i+1][0]; debug(array, i); array[i][1] = array[i+1][1]; debug(array, i); array[i+1][0] = temp; debug(array, i); array[i+1][1] = temp2; debug(array, i); }

Debug-funktionen skriver ut de två raderna för att jag ska se vad som blir fel.
När jag testkör får jag följande:

16,5 5,4 5,5 5,4 5,4 4,4 5,16 16,4 5,16 16,5

Jag försöker alltså få 16,5 och 5,4 att byta plats men istället får jag 5,16 16,5.
Det första steget verkar fungera, men när jag ska sätta array[i][1] till array[i+1][1] så ändras även array[i+1][0] och array[i+1][1] av någon anledning.

Mitt andra problem är min randomiserings-funktion som ser ut så här:

void randomize(arr2& array) { srand ( time(NULL) ); for (int i = 0 ; i < 20 ; i++) { array[i][0] = rand() % 18 + 1; array[i][1] = rand() % 8 + 1; } }

Jag vill att slumptalen i andra kolumnen ska gå från 1 till 8, men den går till 18 verkar det som.

Här är hela koden:

#include <iostream> #include <cmath> #include <cstring> #include <time.h> #include <cstdlib> using namespace std; typedef int arr[1]; typedef arr arr2[19]; void randomize(arr2& array) { srand ( time(NULL) ); for (int i = 0 ; i < 20 ; i++) { array[i][0] = rand() % 18 + 1; array[i][1] = rand() % 8 + 1; } } void print (arr2 array) { for (int i = 0 ; i < 20 ; i++) { cout << "Bana: " << array[i][0] << " Antal slag: " << array[i][1] << endl; } } void debug (arr2 array, int i) { cout << array[i][0] << "," << array[i][1] << " " << array[i+1][0] << "," << array[i+1][1] << endl; } void swap (arr2& array, int i) { int temp = array[i][0]; int temp2 = array[i][1]; debug(array, i); array[i][0] = array[i+1][0]; debug(array, i); array[i][1] = array[i+1][1]; debug(array, i); array[i+1][0] = temp; debug(array, i); array[i+1][1] = temp2; debug(array, i); } void sort (arr2& array) { int j; int temp; int temp2; int temp3; int temp4; bool ingafel = false; while (ingafel == false) { ingafel = true; j = 0; for (int i = 0 ; i < 19 ; i++) { if (array[i][0] > array[i+1][0]) { cout << endl; cout << "Före :"; debug(array, i); cout << "Byter plats på array[" << i << "][0] och array[" << i + 1 << "][0] för att " << array[i][0] << " > " << array[i+1][0] << endl; swap(array, i); cout << "Efter :"; debug(array, i); ingafel = false; } else if (array[i][0] == array[i+1][0]) { if (array[i][1] > array[i+1][1]) { cout << endl; cout << "Före :"; debug(array, i); cout << "Byter plats på array[" << i << "][1] och array[" << i+1 << "][1] för att " << array[i][1] << " > " << array[i+1][1] << endl; swap(array, i); ingafel = false; cout << "Efter: "; debug(array, i); } } } } } int main () { arr2 array; randomize(array); cout << "Osorterad:" << endl; print(array); sort(array); cout << "Sorterad:" << endl; print(array); return 0; }

Permalänk
Medlem

array[0][1] och array[1][0] refererar till samma del av minnet, för att:

typedef int arr[1];

Visa signatur

Bra, snabbt, billigt; välj två.

Ljud
PC → ODAC/O2 → Sennheiser HD650/Ultrasone PRO 900/...
PC → S.M.S.L SA300 → Bowers & Wilkins 607

Permalänk
Medlem
Citat:

Ursprungligen inskrivet av Phod
array[0][1] och array[1][0] refererar till samma del av minnet, för att:

typedef int arr[1];

array[][] är väl en pekare till en pekare, eller array-av-pekare, dvs array[0] pekar till en minnesadress och array[1] pekar till en annan? Då borde array[0][1] och array[1][0] inte nödvändigtvis vara samma..

edit: nu förstår jag vad du menade

Visa signatur

Kom-pa-TI-bilitet

Permalänk
Medlem

Enklaste sättet att göra detta är att INTE hantera minnet tvådimensionelt.
Skapa en array som är width*height stor:

const unsigned int WIDTH = 2; const unsigned int HEIGHT = 20; int arr[WIDTH*HEIGHT];

sedan låter du dina funktioner ta en int* och parametrar som säger hur stor din array är

int func(const int* data, unsigned int width, unsigned int height) { ... arr[x + y*width]; // ta ut ett element ... }

Du kan också wrappa detta i en klass om du skulle vilja.

Visa signatur

void@qnet
teeworlds, stålverk80, evil schemer, c, c++
Languages shape the way we think, or don't.

Permalänk
Medlem

Tack för svaren!
Jag ändrade min array som jdv föreslog

Citat:

const unsigned int WIDTH = 2;
const unsigned int HEIGHT = 8;

typedef int arr[WIDTH*HEIGHT];

Och min swap-funktion ser nu ut så här:

Citat:

void swap (arr& array, int i)
{
int temp = array[i + 0*WIDTH];
int temp2 = array[i + 1*WIDTH];
array[i + 0*WIDTH] = array[i+1 + 0*WIDTH];
array[i + 1*WIDTH] = array[i+1 + 1*WIDTH];
array[i+1 + 0*WIDTH] = temp;
array[i+1 + 1*WIDTH] = temp2;
}

Men nu får jag ett annat fel.
När jag startar programmet så ser den osorterade listan ut t.ex. så här:

Citat:

Bana: 17 Antal slag: 4
Bana: 7 Antal slag: 2
Bana: 4 Antal slag: 15
Bana: 2 Antal slag: 1
Bana: 15 Antal slag: 16
Bana: 1 Antal slag: 13
Bana: 16 Antal slag: 6
Bana: 13 Antal slag: 5

Sedan byter min swap-funktion plats på den första och andra raden, men rad 3 och 4 ändras också av någon anledning.

Citat:

Bana: 7 Antal slag: 2
Bana: 17 Antal slag: 4
Bana: 2 Antal slag: 15
Bana: 4 Antal slag: 1
Bana: 15 Antal slag: 16
Bana: 1 Antal slag: 13
Bana: 16 Antal slag: 6
Bana: 13 Antal slag: 5

Första kolumnen på rad 3 och 4 byter plats.
Jag försökte att spara raderna i temp-variabler och återställa dem, men då blev andra rader ändrade.

Här är hela koden:

Citat:

#include <iostream>
#include <cmath>
#include <cstring>
#include <time.h>
#include <cstdlib>

using namespace std;

const unsigned int WIDTH = 2;
const unsigned int HEIGHT = 8;

typedef int arr[WIDTH*HEIGHT];

void randomize(arr& array)
{
srand ( time(NULL) );
for (int i = 0 ; i < 8 ; i++)
{
array[i + 0*WIDTH] = rand() % 18 + 1;
array[i + 1*WIDTH] = rand() % 8 + 1;
}
}

void print (arr array)
{
for (int i = 0 ; i < 8 ; i++)
{
cout << "Bana: " << array[i + 0*WIDTH] << " Antal slag: " << array[i + 1*WIDTH] << endl;
}
}

void debug (arr array, int i)
{
cout << array[i + 0*WIDTH] << "," << array[i + 1*WIDTH] << " " << array[i+1 + 0*WIDTH] << "," << array[i+1 + 1*WIDTH] << endl;
}
void swap (arr& array, int i)
{
int temp = array[i + 0*WIDTH];
int temp2 = array[i + 1*WIDTH];
//debug(array, i);
array[i + 0*WIDTH] = array[i+1 + 0*WIDTH];
//debug(array, i);
array[i + 1*WIDTH] = array[i+1 + 1*WIDTH];
//debug(array, i);
array[i+1 + 0*WIDTH] = temp;
//debug(array, i);
array[i+1 + 1*WIDTH] = temp2;
//debug(array, i);

}

void sort (arr& array)
{
int j;
int temp;
int temp2;
int temp3;
int temp4;
bool ingafel = false;
while (ingafel == false)
{
ingafel = true;
j = 0;
for (int i = 0 ; i < 7 ; i++)
{
if (array[i + 0*WIDTH] > array[i+1 + 0*WIDTH])
{
cout << endl;
cout << "Före :";
debug(array, i);
cout << "Byter plats på array[" << i + 0*WIDTH<< "] och array[" << i + 1 + 0*WIDTH << "] för att " << array[i + 0*WIDTH] << " > " << array[i+1 + 0*WIDTH] << endl;
swap(array, i);

cout << "Efter :";
debug(array, i);
ingafel = false;
print(array);
}
else if (array[i + 0*WIDTH] == array[i+1 + 0*WIDTH])
{
if (array[i + 1*WIDTH] > array[i+1 + 1*WIDTH])
{
cout << endl;
cout << "Före :";
debug(array, i);
cout << "Byter plats på array i[" << i + 1*WIDTH<< "] och array[" << i+1 + 1*WIDTH << "] för att " << array[i + 1*WIDTH] << " > " << array[i+1 + 1*WIDTH] << endl;
swap(array, i);
ingafel = false;
cout << "Efter: ";
debug(array, i);
print(array);
}
}
}
}
}

int main ()
{
arr array;
randomize(array);
cout << "Osorterad:" << endl;
print(array);
sort(array);
cout << "Sorterad:" << endl;
print(array);
return 0;
}

Permalänk
Medlem

Samma fel som förut. I jdvs kod användes variablerna x och y för att ange en position i arrayen, medans du använder en enda variabel som anger ett offset. Då kan du använda dig av kod som denna:

void swap (arr& array, int i) { int temp = array[i * 4]; int temp2 = array[i * 4 + 2]; array[i] = array[i * 4 + 1]; array[i * 4 + 2] = array[i * 4 + 3]; array[i * 4 + 1] = temp; array[i * 4 + 3] = temp2; }

Visa signatur

Bra, snabbt, billigt; välj två.

Ljud
PC → ODAC/O2 → Sennheiser HD650/Ultrasone PRO 900/...
PC → S.M.S.L SA300 → Bowers & Wilkins 607

Permalänk
Medlem

Tack! Nu fungerar det.

Permalänk
Medlem
Citat:

Ursprungligen inskrivet av Snejk
Jag använder variabeln i för vilken rad man är på och lägger på 1*width ifall jag menar kolumn 2, är inte det ett koordinatsystem?

Sen undrar jag varför du multiplicerar i med 4 i ditt kodexempel.

Det är inte riktigt så du måste göra. Din array kommer att se ut typ så här:

0 1 2 3 4 5 6 7 8 9 10 11

Där siffrorna representerar positionen i din array. Vill du ha elementet vid rad 3, kolonn 2 så måste du alltså gå till element 5, dvs (3-1)*width + (2-1).

Permalänk
Medlem
Citat:

Ursprungligen inskrivet av Teknocide
array[][] är väl en pekare till en pekare, eller array-av-pekare, dvs array[0] pekar till en minnesadress och array[1] pekar till en annan? Då borde array[0][1] och array[1][0] inte nödvändigtvis vara samma..

Arrayer och pekare är i C++ snarlika, men inte detsamma.

"int array[2][3]" är en "array av 2 array(-er) av 3 int(-ar)" och har exakt storleken "2*3*sizeof(int)". Det finns inga pekare inblandade här.

Citat:

Ursprungligen inskrivet av jdv
Enklaste sättet att göra detta är att INTE hantera minnet tvådimensionelt.
Skapa en array som är width*height stor:

const unsigned int WIDTH = 2; const unsigned int HEIGHT = 20; int arr[WIDTH*HEIGHT];

sedan låter du dina funktioner ta en int* och parametrar som säger hur stor din array är

int func(const int* data, unsigned int width, unsigned int height) { ... arr[x + y*width]; // ta ut ett element ... }

Du kan också wrappa detta i en klass om du skulle vilja.

Enligt 8.3.4.8 i ISO 14882 så hanteras arrayer i C++ just på detta sätt.

Visa signatur

"Nothing is impossible because impossible itself says I M Possible..."

Permalänk
Medlem
Citat:

Ursprungligen inskrivet av Weeblie
Enligt 8.3.4.8 i ISO 14882 så hanteras arrayer i C++ just på detta sätt.

Som TS redan har demonstrerat med sitt första exempel.

Visa signatur

Bra, snabbt, billigt; välj två.

Ljud
PC → ODAC/O2 → Sennheiser HD650/Ultrasone PRO 900/...
PC → S.M.S.L SA300 → Bowers & Wilkins 607