Permalänk
Medlem

C programmering: Inputvalidering

Hej!

Jag håller på att lära mig C programmering och har fastnat lite när det kommer till input validering. Programmet ska byggas med structs och fråga användaren efter 5 stycken varor som ska skrivas in och sedan ska programmet skriva ut en "Inköpslista". På exemelvis "Namn på varan" ska man enbart kunna skriva in bokstäver, inte siffror. Detta har jag försökt lösa med isalpha() som finns i ctype.h.

Problemet jag har är att det inte går att skriva isalpha(Items[i].itemName) i if-satsen. Jag försökte istället att kopiera Item[].itemName till en ny variabel via strcpy() men den funktionen verkar ta bort första bokstaven. Samt att när listan sedan skrivs ut så syns vara nummer 5 på första platsen men utan första bokstaven..

Är det någon som vet hur jag ska lösa detta? Finns det något bättre sätt att göra detta på?

#include <stdio.h> #include <stdlib.h> #include <string.h> #include <ctype.h> struct shoppingList { char itemName[10]; int quantity; char unit[10]; }; int main() { struct shoppingList Item[5]; int i, j, k = 1; char temp; char unit[200]; int num; for(i=0; i < 5; i++) { /**< Detta är det jag behöver hjälp med. */ do { printf("\nNamn p\x86 vara: "); fflush(stdin); scanf("%s", &Item[i].itemName); strcpy(&temp, Item[i].itemName); /**< Verkar tappa bort första bokstaven.. */ if(isalpha(temp) != 0) { break; } else{ printf("\t\n Invalid input, try again!\n\n"); } } while(k = 1); do { printf("Antal: "); if( scanf("%i", &num) == 1) { Item[i].quantity = num; break; } else printf("\t\n Invalid input, try again!\n\n"); } while(k = 1); printf("Enhet: "); scanf("%s", &Item[i].unit); } printf("\nInk\x94pslistan: \n"); for (j = 0; j < 5 ; j++) { printf("\n %6s \t %1i \t %2s\n", Item[j].itemName, Item[j].quantity, Item[j].unit); } return 0; }

Permalänk
Medlem

Kan du inte göra något sådant här?

if(isalpha(Itemi[i].itemName))

Visa signatur

OS: MacOS/ Windows 10 Pro 64-bit MB: ASUS-Z97-A CPU: i7 4790k
NÄTAGG: EVGA SUPERNOVA G2
RAM: 32768 MiB GPU: 1070 FTW Chassi: Fractal Design R4
MBP 13" i5 | 256GB | 16GB RAM | MID 2014

Permalänk
Medlem

Tänk på att isalpha bara testar en int i taget vilket gör att du måste loopa igenom hela inputen om du vill kolla alla. Sen så kopierar strcpy hela strängen till temp just nu vilket gör att du förmodligen kommer att skriva sönder minnet då den bara är deklarerad som en char och inte har plats för annat än null-termineringen som kopieras.

Permalänk
Medlem
Skrivet av N0iZE:

Kan du inte göra något sådant här?

if(isalpha(Itemi[i].itemName))

Det är något sådant jag skulle vilja göra men det verkar inte fungera.. Den verkar returnera 0 hela tiden oavsett om det är bokstäver eller siffror som läses in. Någon som vet om det går att göra på liknande sätt?

Skrivet av jensa86:

Tänk på att isalpha bara testar en int i taget vilket gör att du måste loopa igenom hela inputen om du vill kolla alla. Sen så kopierar strcpy hela strängen till temp just nu vilket gör att du förmodligen kommer att skriva sönder minnet då den bara är deklarerad som en char och inte har plats för annat än null-termineringen som kopieras.

Jaha okej, jag trodde den kollade hela strängen som skrevs in. Hur borde jag göra istället, för isalpha() verkar inte kunna kontrollera en array?

Permalänk
Medlem

Den här ser lite mystisk ut..

while(k = 1)

Visa signatur

"This is VAR, spelled A-U-T-O"

Permalänk
Medlem
Skrivet av Kreppe:

Den här ser lite mystisk ut..

while(k = 1)

Ska inte vara sådär i slutändan. Är bara för att köra loopen tills if-satsen är sann och break; går ur den.

Permalänk
Medlem
Skrivet av Kallgard:

Ska inte vara sådär i slutändan. Är bara för att köra loopen tills if-satsen är sann och break; går ur den.

== för att jämföra, väl?

Ser ut som en uppgift från grundkursen i programmering på MDH btw.

Permalänk
Medlem
Skrivet av era909:

== för att jämföra, väl?

Ser ut som en uppgift från grundkursen i programmering på MDH btw.

Precis, ska vara == istället! Spelade inte någon roll i detta fallet dock

Yes, stämmer bra! Är på mdh men fastnat lite på en av labbarna!

Permalänk
Medlem

Om du vill använda isalpha så borde det väl gå att stega igenom din array med namnet och testa varje tecken med isalpha?

Permalänk

http://www.asciitable.com där hittar du dina villkor för din if-sats.

Visa signatur

(Asus Z87-A && i7-4770K && ASUS Strix GTX 970 && Fractal Design Define R4 && Corsair CX500M && Samsung 840 Evo 500GB && Noctua NH-U9B SE2 && (Arch Linux 4.2.3-1 || Windows 10 Pro))

Permalänk
Medlem

Skriver jag såhär: if(isalpha(Item[0].itemName) != 0) och bara kontrollerar första positionen där jag tex. skrivit in en bokstav a så händer det ingenting. Så antar att det inte fungerar om jag skulle loopa igenom hela arrayen och kolla varje position i och med att den inte kan kolla ens första positionen. Eller har jag fel?

Permalänk
Medlem
Skrivet av era909:

Om du vill använda isalpha så borde det väl gå att stega igenom din array med namnet och testa varje tecken med isalpha?

Ett hett tips är att skriva en ny funktion som bara kollar om en textsträng, eller i ditt fall tar in en shoppingList , dvs Item[i], och sedan för varje bokstav i dess namn kollar om det är en siffra eller inte. Upptäcker du en siffra kan du returnera true och annars inte gör något förutom när du gått igenom hela namnet och inte upptäckt en siffra, då vet du att det inte finns en siffra i namnet och kan returnera false.

Permalänk
Medlem
Skrivet av Kallgard:

Skriver jag såhär: if(isalpha(Item[0].itemName) != 0) och bara kontrollerar första positionen där jag tex. skrivit in en bokstav a så händer det ingenting. Så antar att det inte fungerar om jag skulle loopa igenom hela arrayen och kolla varje position i och med att den inte kan kolla ens första positionen. Eller har jag fel?

ItemName är ju själva en array av storlek 10! Nu försöker du ge in hela namnet till isalpha!

Permalänk
Medlem
Skrivet av kobb3:

Ett hett tips är att skriva en ny funktion som bara kollar om en textsträng, eller i ditt fall tar in en shoppingList , dvs Item[i], och sedan för varje bokstav i dess namn kollar om det är en siffra eller inte. Upptäcker du en siffra kan du returnera true och annars inte gör något förutom när du gått igenom hela namnet och inte upptäckt en siffra, då vet du att det inte finns en siffra i namnet och kan returnera false.

Mm, jag skulle inte använda isalpha() alls i det här fallet. Ex, försök skriva in "Omega 3 kosttillskott" och få det att fungera med isalpha().
Om de inte ändrat uppgiften från förra året så står det: Programmet ska ha felhantering. Det ska t.ex. inte vara möjligt att mata in text där det borde vara siffror, osv! Självklart ska programmet vara uppbyggt av funktioner.

Tänkte bara ge TS en hint på vägen om han ville använda det.

Permalänk
Medlem
Skrivet av krille0x7c2:

http://www.asciitable.com där hittar du dina villkor för din if-sats.

Har testat att skapa en if-sats med ascii men det verkar inte heller gå att kontrollera hela arrayen, vet inte om jag gjort rätt dock.
Såhär gjorde jag:

if ((&Item[i].itemName > 65 && &Item[i].itemName < 90 ) && (&Item[i].itemName > 97 && &Item[i].itemName < 122)) { printf("Input is correct!"); } else printf("Invalid input!");

Antar att jag lär loopa igenom hela arrayen för att kontrollera varje position men även med bara en bokstav angivet så fungerar det ej..

Permalänk
Medlem
Skrivet av Kallgard:

Har testat att skapa en if-sats med ascii men det verkar inte heller gå att kontrollera hela arrayen, vet inte om jag gjort rätt dock.
Såhär gjorde jag:

if ((&Item[i].itemName > 65 && &Item[i].itemName < 90 ) && (&Item[i].itemName > 97 && &Item[i].itemName < 122)) { printf("Input is correct!"); } else printf("Invalid input!");

Antar att jag lär loopa igenom hela arrayen för att kontrollera varje position men även med bara en bokstav angivet så fungerar det ej..

Nu testar du om hela strängen itemName är mellan 65 och 90 OCH SAMTIDIGT mellan 97 och 122. (kan aldrig vara sant)

Du vill testa en bokstav i taget från itemName.

Permalänk
Medlem
Skrivet av era909:

Mm, jag skulle inte använda isalpha() alls i det här fallet. Ex, försök skriva in "Omega 3 kosttillskott" och få det att fungera med isalpha().
Om de inte ändrat uppgiften från förra året så står det: Programmet ska ha felhantering. Det ska t.ex. inte vara möjligt att mata in text där det borde vara siffror, osv! Självklart ska programmet vara uppbyggt av funktioner.

Tänkte bara ge TS en hint på vägen om han ville använda det.

Du har iof rätt, man borde kunna mata in siffror i namnet också.. Felhanteringen när det kommer till att bra mata in siffror har jag koll på! Då behöver jag nog inte kontrollera om namnet är enbart av siffror!

Tack för all hjälp!