Permalänk
Medlem

Vector i C?

Jag håller på och skriver ett program i c där jag vill ha en global array.
Problemet är att storleken på arrayen ska bero på data från en fil som läses in.
Eftersom jag inte vet storleken på förhand kan jag inte deklarera arrayen globalt.
Tänkte då att jag skulle använda vectorer eftersom då kan jag ändra storleken i efterhand.
Men <vector> classen verkar inte finnas i C.
Jag skulle byta språk till C++ om det inte vore för att en massa andra saker slutar fungera då.
Några tips?

Permalänk
Medlem

Någon 'vector' finns inte i C nej.

Men du kan skriva din egen implementation av vector eller hitta kod som någon annan skrivit för det.

Annars kan du köra med en global pekare till din array istället - vars utrymme du initierar först när du vet hur mycket du behöver. Om du behöver lägga till mer saker i din array allteftersom (t.ex. om det inte finns någon header i filen som talar om hur mycket som kommer behövas) så skulle du kunna göra en länkad lista med önskad information och, om tvunget, göra om listan till en array senare.

Permalänk
Medlem
Skrivet av echo:

Annars kan du köra med en global pekare till din array istället - vars utrymme du initierar först när du vet hur mycket du behöver.

Smart.
Ska prova med det.

Permalänk
Medlem

Jag deklarerar pekaren så här:

char *boardp;

Sen sätter jag pekaren till min char-array;

boardp = &board;

Sen har jag en funktion som ska returnera en char ur arrayen:

char getGrid(int x, int z) { int pos = z*width + x; char res = boardp[pos]; printf("%i %i %i %c\n",x, z, pos, boardp[pos]); return res; }

Problemet är att värdena den hämtar är fel.
Arrayen innehåller endast tecknen för blanksteg, # och S, men funktionen returnerar alla möjliga tecken.
Jag tänkte att den kanske försöker returnera minnesadressen istället för värdet i minnet, men när jag ändrar

char res = boardp[pos];

till

char res = *boardp[pos];

får jag följande fel.
error: invalid type argument of ‘unary *’ (have ‘int’)

Permalänk

Jag tror att du bör göra så här när du tilldelar boardp ett värde

boardp = board;

Permalänk
Medlem

Ett litet exempel på användning av globala variabler samt med lokala (argument till funktioner)

#include "stdlib.h" #include "stdio.h" char* g_board; void createboard(char** res, int r, int c) { int i,j; char *p; char *board = (char*)malloc(sizeof(char)*r*c); if(!board) return; p = board; for(i=0; i<r; ++i) for(j=0; j<c; ++j) *p++ = (i*j)%256; *res = board; g_board = board; } void printboard(char* board, int r, int c) { int i,j; char *p; if(!board) return; p = board; printf("Printing board using argument...\n"); for(i=0; i<r; ++i) { for(j=0; j<c; ++j) { printf("%3.3d ", *p++); } printf("\n"); } } void printboard_g(int r, int c) { int i,j; char *p; if(!g_board) return; p = g_board; printf("Printing board using global var...\n"); for(i=0; i<r; ++i) { for(j=0; j<c; ++j) { printf("%3.3d ", *p++); } printf("\n"); } } int main(int ac, char** av) { char* board; createboard(&board, 10, 10); printboard(board, 10, 10); printboard_g(10, 10); return 0; }

Visa signatur

weeeee

Permalänk
Medlem
Skrivet av mounte:

Ett litet exempel på användning av globala variabler samt med lokala (argument till funktioner)

Tack för exemplen!

Jag har ändrat mina funktioner till följande:

char *boardp; void createboard(char** res, int r, int c) { char *board = (char*)malloc(sizeof(char)*r*c); if(!board) return; board = res; boardp = board; } void printboard_g(int r, int c) { int i,j; char *p; if(!boardp) return; p = boardp; printf("Printing board using global var...\n"); for(i=0; i<r; ++i) { for(j=0; j<c; ++j) { printf("%c", *p++); } printf("\n"); } } void getchars(char buf[], int row, int wide, char board[]) { int temp; temp = row * (wide + 1); for (int i = 0; i <= wide ; i++){ board[temp + i] = buf[i]; } } void display() { FILE* input = fopen("level.txt", "r"); char buf[80]; height = 0; int counter = 0; while(fgets(buf, 80, input) != NULL) { width = strnlen(buf, 80); height++; } fclose(input); width--; char* board[(height)*(width)]; input = fopen("level.txt", "r"); while(fgets(buf, 80, input) != NULL) { getchars(buf, counter, width, &board); counter++; } fclose(input); createboard(&board, height, width); printboard_g(height, width+1); }

Och när jag kör printboard_g(height, width+1); i display-funktionen så får jag:

Printing board using global var... ########## #s # # # # # # b # # # # # # g # # # ##########

Vilket är rätt.
Men när jag gör exakt samma anrop men i en annan funktion får jag:

Printing board using global var... `xy���/ ��� �  � �xy ��L ���������� ����������

Varför?:(

Permalänk
Medlem

Anropar du createboard innan du anropar printboard_g? Om du inte gör det så initieras ju inte boardp, och pekar då bara på en bit minne som kan innehålla vad som helst.

Globala variabler brukar man försöka undvika förresten. Globala variabler gör att koden blir mindre flexibel (det är mycket svårare att återanvända funktioner som beror på globala variabler) och det är lättare att få svårhittade buggar när variabeln kan ändras vart som helst i programmet.

Permalänk
Medlem
Skrivet av perost:

Anropar du createboard innan du anropar printboard_g?

Jag anropar createboard i funktionen som körs innan. När den globala pekaren väl är satt borde man väl kunna använda printboard_g överallt?

Permalänk
Hedersmedlem
Skrivet av Snejk:

Jag anropar createboard i funktionen som körs innan. När den globala pekaren väl är satt borde man väl kunna använda printboard_g överallt?

Du kopierar dock aldrig innehållet i board till det nya fältet du skapar i createBoard och vad som helst kan hända med board när du lämnar display. Använd memcpy eller liknande när du har allokerat det nya minnet.

Permalänk
Medlem
Skrivet av Elgot:

Du kopierar dock aldrig innehållet i board till det nya fältet du skapar i createBoard och vad som helst kan hända med board när du lämnar display.

Det trodde jag gjorde med board = res; och boardp = board; i

void createboard(char** res, int r, int c) { char *board = (char*)malloc(sizeof(char)*r*c); if(!board) return; board = res; boardp = board; }

Permalänk
Hedersmedlem
Skrivet av Snejk:

Det trodde jag gjorde med board = res; och boardp = board; i

void createboard(char** res, int r, int c) { char *board = (char*)malloc(sizeof(char)*r*c); if(!board) return; board = res; boardp = board; }

Nej, du kopierar bara pekaren; inte innehållet (dessutom förlorar du pekaren till det nyss allokerade utrymmet (och kan därför inte radera det senare (en minneslucka alltså))). Testa något i stil med

memcpy(board, res, sizeof(char)*r*c);

istället för

board = res;

Permalänk
Medlem

Ah! Nu fungerar det.
Tack för hjälpen!