Permalänk

Dynamisk array i C

Försöker skapa en dynamisk array men får det inte att fungera får felmeddelandet invalid allocation size 4294967288 bytes.

int number; int booksInStocks[100]; printf("Hur många böcker vill du hantera? "); scanf("%d", &number); booksInStocks[number]; void* malloc(size_t size); int * booksInStock; booksInStock = (int*)malloc(number* *booksInStocks);

Visa signatur

CPU: Intel core i5 3450 | GPU: Asus Radeon HD 7870 | PSU: Corsair GS 600W | Moderkort: MSI b75a-g43 | HDD WD blue 500 GB | RAM: Crucial ballistiX 2x4gb DDR3 1600MHz | Ljudkort: Asus Xonar DG |

Permalänk
Medlem
Skrivet av turbogeten:

Försöker skapa en dynamisk array men får det inte att fungera får felmeddelandet invalid allocation size 4294967288 bytes.

int number; int booksInStocks[100]; printf("Hur många böcker vill du hantera? "); scanf("%d", &number); booksInStocks[number]; void* malloc(size_t size); int * booksInStock; booksInStock = (int*)malloc(number* *booksInStocks);

Vad menar du med number* *booksInStocks? Borde det inte svarare vara något i stil med number * sizeof(booksInStocks)?

EDIT: Ifall det är otydligt är det alltså parametern till malloc jag snackar om här.

Visa signatur

Fractal Design Define R5 | MSI Z97-GD65 Gaming | MSI Geforce GTX 970 Gaming 4G | Intel i5 4690k | Cooler Master Hyper 212 EVO | EVGA Supernova G2 750W | 2x8GB Corsair Vengeance Low Profile DDR3 1600Mhz | Samsung 850 EVO | Seagate 1TB SATA3.5

Permalänk
Medlem

Din rad:
booksInStocks[number];
kommer att ställa till det för dig eftersom number inte är initierad till något värde.
Eftersom du dynamiskt ska allokera booksInStock så ta bort den raden helt.
Vidare så vill du allokera minne för att hålla "number" antal element. Där varje element är av typen int som ofta har storleken 4Bytes, således number*4 Bytes vill du allokera ... du kan använda sizeof för att få storleken på en datatyp.

int number; printf("Hur många böcker vill du hantera? "); scanf("%d", &number); int *booksInStock = (int*)malloc(number*sizeof(int));

Visa signatur

weeeee

Permalänk
Medlem

*booksInStocks returnerar värdet på det första elementet i booksInStocks. Men eftersom du aldrig tilldelar booksInStocks så innehåller den arrayen bara skräp, vilket gör att den kan returnera precis vilket värde som helst. Jag antar att du egentligen vill allokera number * sizeof(*booksInStocks) istället? Dvs. number * storleken på en bok.

Raden under scanf, booksInStocks[number], gör förresten ingenting. Den returnerar elementet på plats number från booksInStocks, och kastar sedan bort värdet eftersom det inte tilldelas till någonting. Kompilatorn kommer förmodligen att bara ta bort den raden.

Permalänk
Medlem
Skrivet av mounte:

Din rad:
booksInStocks[number];
kommer att ställa till det för dig eftersom number inte är initierad till något värde.
Eftersom du dynamiskt ska allokera booksInStock så ta bort den raden helt.
Vidare så vill du allokera minne för att hålla "number" antal element. Där varje element är av typen int som ofta har storleken 4Bytes, således number*4 Bytes vill du allokera ... du kan använda sizeof för att få storleken på en datatyp.

int number; printf("Hur många böcker vill du hantera? "); scanf("%d", &number); int *booksInStock = (int*)malloc(number*sizeof(int));

Jodå, number blir initierad av scanf("%d", &number), så den har ett värde. Däremot så är raden helt meningslös för den pekar inte på något riktigt värde och han använder inte returen över huvudtaget.

Visa signatur

Fractal Design Define R5 | MSI Z97-GD65 Gaming | MSI Geforce GTX 970 Gaming 4G | Intel i5 4690k | Cooler Master Hyper 212 EVO | EVGA Supernova G2 750W | 2x8GB Corsair Vengeance Low Profile DDR3 1600Mhz | Samsung 850 EVO | Seagate 1TB SATA3.5

Permalänk

Tror att jag löste de med sizeof

int number; int booksInStocks[100]; printf("Hur många böcker vill du hantera? "); scanf("%d", &number); //booksInStocks[number]; void* malloc(size_t size); int * booksInStock; booksInStock = malloc(sizeof(number* *booksInStocks));

Hur kan jag enkelt testa så att jag ser att den faktiskt gjort arrayen till den storlek jag vill?

Visa signatur

CPU: Intel core i5 3450 | GPU: Asus Radeon HD 7870 | PSU: Corsair GS 600W | Moderkort: MSI b75a-g43 | HDD WD blue 500 GB | RAM: Crucial ballistiX 2x4gb DDR3 1600MHz | Ljudkort: Asus Xonar DG |

Permalänk
Medlem

Googla på länkad lista. Så brukade jag lösa dynamiska arrayer.
Man kan lägga till element. Läsa valfritt element. Ta bort valfritt element, och peka om för att upprätthålla listan.

Permalänk
Medlem
Skrivet av turbogeten:

Tror att jag löste de med sizeof

int number; int booksInStocks[100]; printf("Hur många böcker vill du hantera? "); scanf("%d", &number); //booksInStocks[number]; void* malloc(size_t size); int * booksInStock; booksInStock = malloc(sizeof(number* *booksInStocks));

Hur kan jag enkelt testa så att jag ser att den faktiskt gjort arrayen till den storlek jag vill?

Du får väl skriva kod som läser arrayen och kollar, men din kod är inte korrekt. sizeof(number* *booksInStocks) är väldigt ologiskt. Vill du allokera minne för en array av integers med mängd number så ska det vara malloc(number * sizeof(int)), inte något annat. Förstår inte heller varför du skrivit int booksInStocks[100]; överst, då skapar du ju redan en array som du sen ignorerar.

Visa signatur

Fractal Design Define R5 | MSI Z97-GD65 Gaming | MSI Geforce GTX 970 Gaming 4G | Intel i5 4690k | Cooler Master Hyper 212 EVO | EVGA Supernova G2 750W | 2x8GB Corsair Vengeance Low Profile DDR3 1600Mhz | Samsung 850 EVO | Seagate 1TB SATA3.5

Permalänk
Medlem

i skriver man i code blocks kan man se allt möjligt om jag inte minns fel. Jag tyckte att det var väldigt hjälpsamt back in the day

Visa signatur

Custom Built Chassis|CM Silent 1000W Mod|Asus P6X58D-E|i7 930@4.2ghz ht on| 6Gb Corsair Dominator @1604MHz| Evga & Zotac Gtx 470 SLI @ 800,1600,1674 & Asus 8600gt physX dedicated| WD Green 1Tb+1Tb WD Black sata 3 +1Tb extern|Intel SSD 80Gb X25-M G2|Logitech MX518 & G15| H2O|Shure SRH840
http://valid.canardpc.com/show_oc.php?id=2223280

Permalänk
Skrivet av Tobberoth:

Du får väl skriva kod som läser arrayen och kollar, men din kod är inte korrekt. sizeof(number* *booksInStocks) är väldigt ologiskt. Vill du allokera minne för en array av integers med mängd number så ska det vara malloc(number * sizeof(int)), inte något annat. Förstår inte heller varför du skrivit int booksInStocks[100]; överst, då skapar du ju redan en array som du sen ignorerar.

Måste jag inte skapa en array innan jag ändrar storleken på den då? Och sen är de tänkt att jag ska lagra en struct som jag ännu inte riktigt vet hur jag ska göra men tänkte först få den dynimiska arrayen att fungera

Visa signatur

CPU: Intel core i5 3450 | GPU: Asus Radeon HD 7870 | PSU: Corsair GS 600W | Moderkort: MSI b75a-g43 | HDD WD blue 500 GB | RAM: Crucial ballistiX 2x4gb DDR3 1600MHz | Ljudkort: Asus Xonar DG |

Permalänk
Medlem

Man behöver inte göra en typomvandling av pekaren malloc returnerar:
http://stackoverflow.com/questions/605845/do-i-cast-the-resul...

Om du inkluderar stdlib.h behöver du heller inte deklarera malloc.

Tänker mig man kan göra så här:

#include <stdio.h> #include <stdlib.h> int main(void) { int number; int *books_in_stock; printf("Hur många böcker vill du hantera? "); scanf("%d", &number); books_in_stock = malloc(number * sizeof *books_in_stock); if (books_in_stock != NULL) { /* Gör något med arrayen */ free(books_in_stock); // Frigör minnet när det inte längre behövs } else { /* malloc returnerade NULL, kunde alltså inte allokera minnet */ printf("Fel, kundeinte allokera minne!\n"); return EXIT_FAILURE; } return EXIT_SUCCESS; }

Behövs inga paranteser efter sizeof när det är en variabel efter
Permalänk
Medlem
Skrivet av turbogeten:

Måste jag inte skapa en array innan jag ändrar storleken på den då? Och sen är de tänkt att jag ska lagra en struct som jag ännu inte riktigt vet hur jag ska göra men tänkte först få den dynimiska arrayen att fungera

malloc är vad som skapar den dynamiska arrayen, malloc skapar upp minnesutrymmet du behöver i heapen. När du skriver int Blabla[100]; så skapar du en array för 100 intar på stacken.

int* bookArray = malloc(10 * sizeof(int)); skapar en array för 10 intar. För att sedan ändra storleken använder man realloc() istället för malloc.

EDIT: Det är inte mycket svårare när du vill göra det med structer, det är därför man använder sizeof() i malloc(). Skriver du in structens namn där istället (eller en pointer till en sådan struct) så räknar C själv ut hur mycket minne som krävs för en sådan struct. Är därför du vill ha number * sizeof().

Visa signatur

Fractal Design Define R5 | MSI Z97-GD65 Gaming | MSI Geforce GTX 970 Gaming 4G | Intel i5 4690k | Cooler Master Hyper 212 EVO | EVGA Supernova G2 750W | 2x8GB Corsair Vengeance Low Profile DDR3 1600Mhz | Samsung 850 EVO | Seagate 1TB SATA3.5

Permalänk
Medlem

I mitt kodexempel ovan satte sizeof *books_in_stock för att få storleken på den data som pekaren books_in_stock pekar till (vilket i detta fallet var en int). Hade books_in_stock varit en pekare till en struct så hade det blivit storleken hos denna struct som beräknats av sizeof. Detta multiplicerades med antalet sådana som behövdes för den dynamiska arrayen. Sedan kan man använda arrayen som en vanlig Array med hakparenteser.

Funktionen free() frigör minnet när man inte längre behöver det. I och för sig frigörs minnet av operativsystemet när programmet avslutas men är det ett program som körs längre tid gäller det att inte glömma att frigöra minne som inte längre kommer att användas för att undvika minnesläckor. Har man allokerat minne inuti en funktion och sedan lämnar funktionen utan att frigöra minnet så blir det allokerat minne som "hänger i luften" oåtkomligt för programmet (om det inte deklarerats som static i funktionen).

Dessutom ska man alltid testa om malloc returnerar NULL. Försöker man allokera mer minne än vad som finns ledigt kommer det att misslyckas och då blir det ju fel om man försöker använda minne som inte har tilldelats.

Permalänk
Medlem
Skrivet av Tobberoth:

int* bookArray = malloc(10 * sizeof(int)); skapar en array för 10 intar. För att sedan ändra storleken använder man realloc() istället för malloc.

Det kanske också ska nämnas att det inte är säkert att det går att ändra storleken på en array. När man anropar malloc så tilldelas man ju ett block med minne av operativsystemet, men det finns inga garantier på att det finns mer ledigt minne runt omkring det blocket. Vad realloc gör är att ändra storleken på blocket om det är möjligt, t.ex. om man vill minska storleken eller om det råkas finnas tillräckligt med ledigt minne efter blocket så att man bara kan utöka blocket. Om det inte är möjligt så allokeras istället ett nytt block minne med den efterfrågade storleken, och sen kopieras datan från det gamla blocket till det nya. Dvs:

Ledigt minne, varje plats är en byte: [ ][ ][ ][ ][ ][ ][ ][ ][ ][ ][ ][ ][ ][ ][ ][ ][ ][ ][ ][ ][ ][ ][ ][ ] A = malloc(4) // Allokera 4 byte till en array [A][A][A][A][ ][ ][ ][ ][ ][ ][ ][ ][ ][ ][ ][ ][ ][ ][ ][ ][ ][ ][ ][ ] B = malloc(4) // Allokera 4 byte till en annan array [A][A][A][A][B][B][B][B][ ][ ][ ][ ][ ][ ][ ][ ][ ][ ][ ][ ][ ][ ][ ][ ] A = realloc(A, 8) // Öka storlek på A till 8. B är i vägen, så vi måste flytta på A: [ ][ ][ ][ ][B][B][B][B][A][A][A][A][A][A][A][A][ ][ ][ ][ ][ ][ ][ ][ ] A = realloc(A, 6) // Minska storlek på A till 6. Inga problem, bara lämna tillbaks lite av A: [ ][ ][ ][ ][B][B][B][B][A][A][A][A][A][A][ ][ ][ ][ ][ ][ ][ ][ ][ ][ ]

Permalänk
Skrivet av ronnylov:

I mitt kodexempel ovan satte sizeof *books_in_stock för att få storleken på den data som pekaren books_in_stock pekar till (vilket i detta fallet var en int). Hade books_in_stock varit en pekare till en struct så hade det blivit storleken hos denna struct som beräknats av sizeof. Detta multiplicerades med antalet sådana som behövdes för den dynamiska arrayen. Sedan kan man använda arrayen som en vanlig Array med hakparenteser.

Funktionen free() frigör minnet när man inte längre behöver det. I och för sig frigörs minnet av operativsystemet när programmet avslutas men är det ett program som körs längre tid gäller det att inte glömma att frigöra minne som inte längre kommer att användas för att undvika minnesläckor. Har man allokerat minne inuti en funktion och sedan lämnar funktionen utan att frigöra minnet så blir det allokerat minne som "hänger i luften" oåtkomligt för programmet (om det inte deklarerats som static i funktionen).

Dessutom ska man alltid testa om malloc returnerar NULL. Försöker man allokera mer minne än vad som finns ledigt kommer det att misslyckas och då blir det ju fel om man försöker använda minne som inte har tilldelats.

Försöker göra med struct men vet inte om jag gör rätt

printf("Hur många böcker vill du hantera? "); scanf("%d", &number); void* malloc(size_t size); int * booksInStock; booksInStock = malloc(number* sizeof (struct booksToDo)); struct booksToDo* lager(int number); { struct booksToDo * newStruct = (struct booksToDo*) malloc(sizeof(struct booksToDo) * number); for (int i = 0; i < number; i++) { printf("Bok %d titel? \n", i + 1); scanf("%s", &newStruct[i].title, sizeof (newStruct[i].title)); printf("Bok %d ISBN-nummer? \n", i + 1); scanf("%d", &newStruct[i].isbNummer, sizeof (newStruct[i].isbNummer)); printf("Låntagarens id? \n"); scanf("%d", &newStruct[i].personId, sizeof (newStruct[i].personId)); } }

Visa signatur

CPU: Intel core i5 3450 | GPU: Asus Radeon HD 7870 | PSU: Corsair GS 600W | Moderkort: MSI b75a-g43 | HDD WD blue 500 GB | RAM: Crucial ballistiX 2x4gb DDR3 1600MHz | Ljudkort: Asus Xonar DG |

Permalänk
Medlem
Skrivet av perost:

Det kanske också ska nämnas att det inte är säkert att det går att ändra storleken på en array. När man anropar malloc så tilldelas man ju ett block med minne av operativsystemet, men det finns inga garantier på att det finns mer ledigt minne runt omkring det blocket. Vad realloc gör är att ändra storleken på blocket om det är möjligt, t.ex. om man vill minska storleken eller om det råkas finnas tillräckligt med ledigt minne efter blocket så att man bara kan utöka blocket. Om det inte är möjligt så allokeras istället ett nytt block minne med den efterfrågade storleken, och sen kopieras datan från det gamla blocket till det nya. Dvs:

Ledigt minne, varje plats är en byte: [ ][ ][ ][ ][ ][ ][ ][ ][ ][ ][ ][ ][ ][ ][ ][ ][ ][ ][ ][ ][ ][ ][ ][ ] A = malloc(4) // Allokera 4 byte till en array [A][A][A][A][ ][ ][ ][ ][ ][ ][ ][ ][ ][ ][ ][ ][ ][ ][ ][ ][ ][ ][ ][ ] B = malloc(4) // Allokera 4 byte till en annan array [A][A][A][A][B][B][B][B][ ][ ][ ][ ][ ][ ][ ][ ][ ][ ][ ][ ][ ][ ][ ][ ] A = realloc(A, 8) // Öka storlek på A till 8. B är i vägen, så vi måste flytta på A: [ ][ ][ ][ ][B][B][B][B][A][A][A][A][A][A][A][A][ ][ ][ ][ ][ ][ ][ ][ ] A = realloc(A, 6) // Minska storlek på A till 6. Inga problem, bara lämna tillbaks lite av A: [ ][ ][ ][ ][B][B][B][B][A][A][A][A][A][A][ ][ ][ ][ ][ ][ ][ ][ ][ ][ ]

Precis, så det kommer ju fungera förutsatt att det finns tillräckligt med kontinuerligt minne ledigt. Dock antar jag att man kanske får kass performance om den tvingas flytta datan?

Visa signatur

Fractal Design Define R5 | MSI Z97-GD65 Gaming | MSI Geforce GTX 970 Gaming 4G | Intel i5 4690k | Cooler Master Hyper 212 EVO | EVGA Supernova G2 750W | 2x8GB Corsair Vengeance Low Profile DDR3 1600Mhz | Samsung 850 EVO | Seagate 1TB SATA3.5

Permalänk
Medlem
Skrivet av turbogeten:

Försöker göra med struct men vet inte om jag gör rätt

printf("Hur många böcker vill du hantera? "); scanf("%d", &number); void* malloc(size_t size); int * booksInStock; booksInStock = malloc(number* sizeof (struct booksToDo)); struct booksToDo* lager(int number); { struct booksToDo * newStruct = (struct booksToDo*) malloc(sizeof(struct booksToDo) * number); for (int i = 0; i < number; i++) { printf("Bok %d titel? \n", i + 1); scanf("%s", &newStruct[i].title, sizeof (newStruct[i].title)); printf("Bok %d ISBN-nummer? \n", i + 1); scanf("%d", &newStruct[i].isbNummer, sizeof (newStruct[i].isbNummer)); printf("Låntagarens id? \n"); scanf("%d", &newStruct[i].personId, sizeof (newStruct[i].personId)); } }

Jag tror du tänker lite fel med hur du definierar upp allting. Här har jag skrivet ett simpelt C program som nog gör ungefär vad du vill. (Jag byggde det med visual studio 2013, använder scanf_s för det är säkrare och VS2013 stoppar en från att bygga med vanliga scanf, men du kan nog byta tillbaka utan problem).

#include <stdio.h> struct book { char title[20]; }; int main() { int number; printf("Hur många böcker vill du hantera? "); scanf_s("%d", &number); struct book* bookArray = malloc(number * sizeof(struct book)); for (int i = 0; i < number; ++i) { struct book b1; printf("Insert Book title:"); scanf_s("%s", &b1.title, sizeof (b1.title)); bookArray[i] = b1; } for (int i = 0; i < number; ++i) { printf("%s", bookArray[i].title); } return 0; }

Visa signatur

Fractal Design Define R5 | MSI Z97-GD65 Gaming | MSI Geforce GTX 970 Gaming 4G | Intel i5 4690k | Cooler Master Hyper 212 EVO | EVGA Supernova G2 750W | 2x8GB Corsair Vengeance Low Profile DDR3 1600Mhz | Samsung 850 EVO | Seagate 1TB SATA3.5

Permalänk
Medlem
Skrivet av turbogeten:

Försöker göra med struct men vet inte om jag gör rätt

printf("Hur många böcker vill du hantera? "); scanf("%d", &number); void* malloc(size_t size); int * booksInStock; booksInStock = malloc(number* sizeof (struct booksToDo)); struct booksToDo* lager(int number); { struct booksToDo * newStruct = (struct booksToDo*) malloc(sizeof(struct booksToDo) * number); for (int i = 0; i < number; i++) { printf("Bok %d titel? \n", i + 1); scanf("%s", &newStruct[i].title, sizeof (newStruct[i].title)); printf("Bok %d ISBN-nummer? \n", i + 1); scanf("%d", &newStruct[i].isbNummer, sizeof (newStruct[i].isbNummer)); printf("Låntagarens id? \n"); scanf("%d", &newStruct[i].personId, sizeof (newStruct[i].personId)); } }

Vid en snabbtitt så känns det fel att tilldela en pekare till int en mängd minne motsvarande ett visst antal structs.
BooksInStock borde väl ges samma typ som booksToDo? Tror det blev fel med int.

Är lager en funktion? Var definieras den?
Känns lite rörigt.

Permalänk
Skrivet av Tobberoth:

Jag tror du tänker lite fel med hur du definierar upp allting. Här har jag skrivet ett simpelt C program som nog gör ungefär vad du vill. (Jag byggde det med visual studio 2013, använder scanf_s för det är säkrare och VS2013 stoppar en från att bygga med vanliga scanf, men du kan nog byta tillbaka utan problem).

#include <stdio.h> struct book { char title[20]; }; int main() { int number; printf("Hur många böcker vill du hantera? "); scanf_s("%d", &number); struct book* bookArray = malloc(number * sizeof(struct book)); for (int i = 0; i < number; ++i) { struct book b1; printf("Insert Book title:"); scanf_s("%s", &b1.title, sizeof (b1.title)); bookArray[i] = b1; } for (int i = 0; i < number; ++i) { printf("%s", bookArray[i].title); } return 0; }

Jo det är åt det här hållet jag vill ha det, men jag förstår inte riktigt vad den här b1 gör. Varför sätter du bookArray[i] = b1 ?

Visa signatur

CPU: Intel core i5 3450 | GPU: Asus Radeon HD 7870 | PSU: Corsair GS 600W | Moderkort: MSI b75a-g43 | HDD WD blue 500 GB | RAM: Crucial ballistiX 2x4gb DDR3 1600MHz | Ljudkort: Asus Xonar DG |

Permalänk
Medlem
Skrivet av turbogeten:

Jo det är åt det här hållet jag vill ha det, men jag förstår inte riktigt vad den här b1 gör. Varför sätter du bookArray[i] = b1 ?

Det är för att jag är sämst på C och har skrivit koden mer likt C# kod hehe. Du behöver inte skriva så, det går att skriva innerloopen som fyller arrayen såhär istället:

for (int i = 0; i < number; ++i) { printf("Insert Book title:"); scanf_s("%s", &bookArray[i].title, 20 * sizeof(char)); }

Visa signatur

Fractal Design Define R5 | MSI Z97-GD65 Gaming | MSI Geforce GTX 970 Gaming 4G | Intel i5 4690k | Cooler Master Hyper 212 EVO | EVGA Supernova G2 750W | 2x8GB Corsair Vengeance Low Profile DDR3 1600Mhz | Samsung 850 EVO | Seagate 1TB SATA3.5

Permalänk
Skrivet av Tobberoth:

Det är för att jag är sämst på C och har skrivit koden mer likt C# kod hehe. Du behöver inte skriva så, det går att skriva innerloopen som fyller arrayen såhär istället:

for (int i = 0; i < number; ++i) { printf("Insert Book title:"); scanf_s("%s", &bookArray[i].title, 20 * sizeof(char)); }

Aha sjyst tack för hjälpen

Visa signatur

CPU: Intel core i5 3450 | GPU: Asus Radeon HD 7870 | PSU: Corsair GS 600W | Moderkort: MSI b75a-g43 | HDD WD blue 500 GB | RAM: Crucial ballistiX 2x4gb DDR3 1600MHz | Ljudkort: Asus Xonar DG |

Permalänk
Datavetare

Finns ingen anledning att använda scanf_s, dels är det en Microsoft specifik utökning dels så stödjer ANSI-C sedan 1999 både dynamisk allokering av strängar och begränsning av antal lagrade tecken (vilket tyvärr inte garanterar att MSVC++ implementerar det då MS verkar tycka 1989 års standard räcker för C...).

Formatsträngen man skickar till scanf har formatet %[*][width][length]specifier (hela dokumentationen här). Din "for-loop" blir då

for (int i = 0; i < number; ++i) { printf("Insert Book title:"); // Går att göra helt dynamiskt rätt enkelt, men för enkelhet använder jag längden // direkt här. Ska vara längden minus ett, så 19 då 'title' kan hålla 20 tecken. scanf("%19s", bookArray[i].title); }

Vill man alltid läsa alla tecken och låta scanf sköta minnesallokeringen fungerar detta (kräver C99 eller senare).

char *my_string; scanf("%ms", &my_string); if (my_string != NULL) { // allt inläst free(my_string); }

Visa signatur

Care About Your Craft: Why spend your life developing software unless you care about doing it well? - The Pragmatic Programmer

Permalänk
Medlem
Skrivet av Yoshman:

Finns ingen anledning att använda scanf_s, dels är det en Microsoft specifik utökning dels så stödjer ANSI-C sedan 1999 både dynamisk allokering av strängar och begränsning av antal lagrade tecken (vilket tyvärr inte garanterar att MSVC++ implementerar det då MS verkar tycka 1989 års standard räcker för C...).

Formatsträngen man skickar till scanf har formatet %[*][width][length]specifier (hela dokumentationen här). Din "for-loop" blir då

for (int i = 0; i < number; ++i) { printf("Insert Book title:"); // Går att göra helt dynamiskt rätt enkelt, men för enkelhet använder jag längden // direkt här. Ska vara längden minus ett, så 19 då 'title' kan hålla 20 tecken. scanf("%19s", bookArray[i].title); }

Vill man alltid läsa alla tecken och låta scanf sköta minnesallokeringen fungerar detta (kräver C99 eller senare).

char *my_string; scanf("%ms", &my_string); if (my_string != NULL) { // allt inläst free(my_string); }

Jag brukar alltid göra fel när man ska göra scanf till en medlem i en struct.
Scanf ska ju ha en pekare till värdet som ska sparas.
http://stackoverflow.com/questions/6228239/scanf-to-struct-do...
Lätt hänt att man försöker med

scanf("%19s", bookArray[i]->title);

Men det brukar bli fel.
Det är nog att bookArray[i] inte är en pekare.
-> använder man väl om man vill åt värdet i en struct som man har en pekare till.
Men nu vill vi ha en pekare till värdet.
(Ursäkta denna kringsvävning om ett fel jag brukar göra, är inte direkt relevant till tråden).

Jag tror jag skulle ha försökt med

scanf("%19s", &(bookArray[i].title));

Men är osäker på om det blir rätt. Behövs parentesen efter & förresten?
Tror det funkar utan den parentesen.
Överhuvudtaget är det lätt att missa &-tecknet vid scanf tycker jag.
Gör det felet nästan varje gång jag använder scanf trots att jag vet att det behövs.

Så det fattas nog ett & i scanf i din kod Yoshman.

Permalänk
Datavetare
Skrivet av ronnylov:

Jag brukar alltid göra fel när man ska göra scanf till en medlem i en struct.
Scanf ska ju ha en pekare till värdet som ska sparas.
http://stackoverflow.com/questions/6228239/scanf-to-struct-do...
Lätt hänt att man försöker med

scanf("%19s", bookArray[i]->title);

Men det brukar bli fel.
Det är nog att bookArray[i] inte är en pekare.
-> använder man väl om man vill åt värdet i en struct som man har en pekare till.
Men nu vill vi ha en pekare till värdet.
(Ursäkta denna kringsvävning om ett fel jag brukar göra, är inte direkt relevant till tråden).

Jag tror jag skulle ha försökt med

scanf("%19s", &(bookArray[i].title));

Men är osäker på om det blir rätt. Behövs parentesen efter & förresten?
Tror det funkar utan den parentesen.
Överhuvudtaget är det lätt att missa &-tecknet vid scanf tycker jag.
Gör det felet nästan varje gång jag använder scanf trots att jag vet att det behövs.

Så det fattas nog ett & i scanf i din kod Yoshman.

Definitionen av strukturen i detta fall är

struct book { char title[20]; };

där 'title' är en array-of-chars.
Denna assert kommer inte trigga, vilket betyder att båda uttrycken ger samma resultat, vilket i sin tur betyder att jag inte saknar en

struct book b; assert(b.title == &b.title[0]);

Däremot så tillåter C redundant användning av "address-of" operatorn i vissa lägen, ett sådan fall är användning av den på något som är en array. Så även detta är sant.

struct book b; assert(b.title == &b.title);

Det sista kan man dock skjuta sig i foten med då det inte är samma sak om title i stället är av typen pointer-to-char i stället för array-of-char, trots att de i övrigt kan hanteras identiskt rent syntaktiskt. Faktum är att detta fall enbart är sant om det handlar om en medlem som är en array-of-something.

Att det inte behöves en '&' har alltså att göra med att det handlar om en array-of-something. Vill jag skicka en referens till någon annan typ inuti en struct till scanf så måste man använda address-of operatorn, är garanterat därför man just explicit tillåter redundant användning av den operatorn även för array-of-something fallet.

Visa signatur

Care About Your Craft: Why spend your life developing software unless you care about doing it well? - The Pragmatic Programmer

Permalänk
Medlem

Javisst ja, du scannar ju in en sträng och då kör man ju utan & eftersom man skickar in en pekare till första tecknet i strängen (också ett vanligt fel med scanf om man alltid kör & av gammal vana).

Fasen, det här med pekare kan röra till det...

Permalänk

Löst

Misstag
Visa signatur

CPU: Intel core i5 3450 | GPU: Asus Radeon HD 7870 | PSU: Corsair GS 600W | Moderkort: MSI b75a-g43 | HDD WD blue 500 GB | RAM: Crucial ballistiX 2x4gb DDR3 1600MHz | Ljudkort: Asus Xonar DG |