11 svar
107 visningar
Schwartz 42
Postad: 21 feb 22:18

Filhantering med structar och funktioner

Hej! Har mer problem nu. Håller på med en uppgift där man ska använda en struct och sedan göra olika saker med hjälp av olika funktioner. Jag fick programmet att fungera klockrent om jag har allting i main cppn, men main filen blir så stor så jag ville prova o dela upp det, med funktionerna för sig. Men jag får inte till det, trots flera dagars intensivt googlande. Hjälp! Har felkoder i både Funktioner.h och i main.cpp. Ändrat o flyttat grejer fram och tillbaka, men felkoderna ändras eller byts ut, de försvinner aldrig. Vet inte ens om jag ska ha min struct i h filen, eller ska den ligga någon annanstans? Framförallt är felkoderna att mina parametrar i funktionerna är odefinerade, eller att funktionerna i main har för många parametrar. Hur kan det bli såhär när det funkar när allt ligger i samma fil? :(

//Koden i Funktioner.cpp
#include <locale>
#include <iostream>
#include <ctype.h>
#include "Funktioner.h"
using namespace std;

//Här under är mina funktionsdefinitioner.

/*I denna funktion står all info om husdjuren som läggs in i
structen Husdjur. Jag väljer att spara en tom plats för att
man ska kunna lägga in sin egen info om man vill.*/

void Husdjuren()
{
	Djur[0].namn = "WillGott";
	Djur[0].alder = 19;
	Djur[0].typavdjur = "Häst";
	Djur[0].avliden = 'J';

	Djur[1].namn = "Bosse";
	Djur[1].alder = 4;
	Djur[1].typavdjur = "Katt";
	Djur[1].avliden = 'J';

	Djur[2].namn = "Winston";
	Djur[2].alder = 8;
	Djur[2].typavdjur = "Häst";
	Djur[2].avliden = 'J';

	Djur[3].namn = "Totte";
	Djur[3].alder = 2;
	Djur[3].typavdjur = "Katt";
	Djur[3].avliden = 'N';

	Djur[4].namn = "Knotte";
	Djur[4].alder = 2;
	Djur[4].typavdjur = "Katt";
	Djur[4].avliden = 'N';

	Djur[5].namn;
	Djur[5].alder;
	Djur[5].typavdjur;
	Djur[5].avliden;
}

/*Den här funktionen skriver ut all info som man lagt till i
funktionen Husdjuren. Den använder en for loop för att ta
sig igenom hela arrayen och skriva ut all info om alla
objekt.*/

void Husdjursinfo()
{
	Husdjuren();
	for (int i = 0; i < 6; i++)
	{
		cout << "Namn: " << Djur[i].namn << endl;
		cout << "Ålder: " << Djur[i].alder << endl;
		cout << "Typ av djur: " << Djur[i].typavdjur
			<< endl;
		cout << "Är djuret avlidet (J = Ja, N = Nej)? "
			<< Djur[i].avliden
			<< endl;
	}
}

/*Den här funktionen utför en linjär sökning för att hitta
ett husdjur med hjälp av namnet. Man får ett indexnr
tillbaka om djuret finns eller -1 om djuret inte finns i
arrayen.*/

int Sok2(Husdjur Djur[], int n, int index)
{
	for (int i = 0; i < n; i++)
	{
		if (i == index)
			return i;
	}
	return -1;
}

/*Den här funktionen utför en linjär sökning för att hitta
djuret på det index man anger. Funktionen returnerar
indexet djuret ligger på om djuret hittas eller annars
returnerar värdet -1 om djuret inte hittas.*/

int Linjesok(Husdjur Djur[], int n, string sökdjur)
{
	for (int i = 0; i < n; i++)
	{
		if (Djur[i].namn == sökdjur)
			return i;
	}
	return -1;
}

//Koden i Funktion.h
#include <string>
//Det här är min struct för husdjuren jag lagt till i programmet.
struct Husdjur
{
	std::string namn;
	int alder;
	std::string typavdjur;
	char avliden;
};
//Här ger jag structen 6 djurobjekt i en array.
Husdjur Djur[6];
void Husdjuren();
void Husdjursinfo();
int Linjesok(Djur, 6, sökdjur);
int Linjesok2(Djur, 6, index);

//Koden i main.cpp

#include <locale>
#include <iostream>
#include <ctype.h>
#include "Funktioner.h"
using namespace std;


//Här börjar Mainfunktionen som programmet körs i.
int main()
{
	setlocale(LC_ALL, "sv-SE");
	while (true)
	{
		cout << "Välkommen till min Husdjursbok!\n";
		cout << "Gör ett val i menyn under:\n";
		cout << "[V]isa lista över Husdjur\n";
		cout << "[S]ök efter Husdjur\n";
		cout << "[R]edigera Husdjur\n";
		cout << "[A]vsluta Program\n";
		char menyVal;
		cin >> menyVal;

		/*Använder toupper för att det inte ska spela
		någon roll om användaren matar in stora eller
		små bokstäver.*/
		menyVal = toupper(menyVal);

		switch (menyVal)
		{
		case 'V':

			Husdjursinfo();
			break;

		case 'S':

			/*Det här alternativet används med funktionen Linjesok.
			Man använder den för att kunna söka reda på ett husdjur
			med hjälp av namnet på husdjuret. Hittar sökningen djuret
			får man upp info om det, annars får man ett meddelande att
			djuret inte finns i listan. Använder en {} runt denna del
			av switchsatsen för att jag deklarerar en variabel jag
			sedan använder på ett annat sätt i en annan del av satsen
			längre ned.*/

		{
			cout << "Vad heter husdjuret vill du söka"
				<< " efter? ";
			string sökdjur;
			cin >> sökdjur;
			Husdjuren();

			int i = Linjesok(Djur, 6, sökdjur);
			if (i == 0 || i == 1 || i == 2 || i == 3 ||
				i == 4 || i == 5)
			{
				cout << "Djuret du söker finns på index "
					<< i << " med infon: " << endl;;
				cout << "Namn: " << Djur[i].namn << endl;
				cout << "Ålder: " << Djur[i].alder
					<< endl;
				cout << "Typ av djur: "
					<< Djur[i].typavdjur << endl;
				cout << "Är djuret avlidet (J = Ja, N"
					<< "= Nej): "
					<< Djur[i].avliden << endl;
			}
			else
			{
				cout << "Djuret du sökte på finns inte"
					<< " på listan. \n";
			}

			break;
		}
		case 'R':

			/*Man använder i detta alternativ funktionen Linjesok2 och
			kan då söka reda på djuret man vill redigera med hjälp av
			numret på djurets index. Man får sedan redigera djuret om
			det finns med på listan annars får man upp ett meddelande
			om att djuret inte finns på listan. Är kodat för att tåla
			felinmatningar på ålder. Använder {} runt denna del av
			switchsatsen för att jag använder en variabel som jag sedan
			återanvänder högre upp beroende på vad användaren matar in
			för val. */

		{
			cout << "Ange indexnr på djuret du vill "
				<< "redigera: ";
			int index;
			cin >> index;

			if (cin.fail())
			{
				cin.clear();
				cin.ignore();
				cout << "Ange en siffra!\n";
			}
			else
			{
				Husdjuren();
				int i = Linjesok2(Djur, 6, index);
				if (i == 0 || i == 1 || i == 2 || i == 3
					|| i == 4 || i == 5)
				{
					cout << "Djuret heter "
						<< Djur[i].namn
						<< ". Vad vill du ändra"
						<< " namnet till? ";
					cin >> Djur[i].namn;
					cout << "Ange "
						<< Djur[i].namn
						<< "s ålder: ";
					cin >> Djur[i].alder;
					if (cin.fail())
					{
						cin.clear();
						cin.ignore();
						cout << "Ange en siffra!\n";
						cout << "Ange "
							<< Djur[i].namn
							<< "s ålder: ";
						cin >> Djur[i].alder;

						if (cin.fail())
						{
							cin.clear();
							cin.ignore();
							cout << "Ange en SIFFRA"
								<< " i nästa"
								<< " försök,"
								<< " nu får du"
								<< " börja om!"
								<< endl;
						}
					}
					else
					{
						cout << "Ange vilken typ av"
							<< "djur "
							<< Djur[i].namn
							<< " är: ";
						cin >> Djur[i].typavdjur;
						cout << "Ange om "
							<< Djur[i].namn
							<< " är avliden (J ="
							<< "Ja och N = Nej):";
						cin >> Djur[i].avliden;
					}
				}
				else
				{
					cout << "Indexet du angav finns "
						<< "inte på listan\n";
				}
			}
			break;
		}

		case 'A':
			//Vad som händer vid val A. Programmet avslutas.
			return 0;
			//Vad som händer om inget av valen ovanför stämmer in.
		default:
			cout << "Ogiltigt val, försök igen.\n";
		}
	}
}
Laguna Online 30471
Postad: 21 feb 23:12

Fungerar det verkligen om du har med raden

 int Linjesok2(Djur, 6, index);

när du har allt i en enda fil?

Schwartz 42
Postad: 21 feb 23:20

Såhär ser koden ut i filen som jag har allting samlat i. Ja, jag tror det står precis likadant, kollat på det så länge nu så snart vet jag inte vad som är vad.

#include <locale>
#include <iostream>
#include <ctype.h>

using namespace std;


//Det här är min struct för husdjuren jag lagt till i programmet.
struct Husdjur
{
	string namn;
	int alder;
	string typavdjur;
	char avliden;
};

//Här ger jag structen 6 djurobjekt i en array.
Husdjur Djur[6];

//Här under är mina funktionsdefinitioner.

/*I denna funktion står all info om husdjuren som läggs in i
structen Husdjur. Jag väljer att spara en tom plats för att 
man ska kunna lägga in sin egen info om man vill.*/
void Husdjuren()
{
	Djur[0].namn = "WillGott";
	Djur[0].alder = 19;
	Djur[0].typavdjur = "Häst";
	Djur[0].avliden = 'J';

	Djur[1].namn = "Bosse";
	Djur[1].alder = 4;
	Djur[1].typavdjur = "Katt";
	Djur[1].avliden = 'J';

	Djur[2].namn = "Winston";
	Djur[2].alder = 8;
	Djur[2].typavdjur = "Häst";
	Djur[2].avliden = 'J';

	Djur[3].namn = "Totte";
	Djur[3].alder = 2;
	Djur[3].typavdjur = "Katt";
	Djur[3].avliden = 'N';

	Djur[4].namn = "Knotte";
	Djur[4].alder = 2;
	Djur[4].typavdjur = "Katt";
	Djur[4].avliden = 'N';

	Djur[5].namn;
	Djur[5].alder;
	Djur[5].typavdjur;
	Djur[5].avliden;
}
/*Den här funktionen skriver ut all info som man lagt till i
funktionen Husdjuren. Den använder en for loop för att ta 
sig igenom hela arrayen och skriva ut all info om alla 
objekt.*/
void Husdjursinfo()
{
	Husdjuren();
	for (int i = 0; i < 6; i++)
	{
		cout << "Namn: " << Djur[i].namn << endl;
		cout << "Ålder: " << Djur[i].alder << endl;
		cout << "Typ av djur: " << Djur[i].typavdjur 
			 << endl;
		cout << "Är djuret avlidet (J = Ja, N = Nej)? " 
			 << Djur[i].avliden 
			 << endl;
	}
}

/*Den här funktionen utför en linjär sökning för att hitta
ett husdjur med hjälp av namnet. Man får ett indexnr 
tillbaka om djuret finns eller -1 om djuret inte finns i
arrayen.*/
int Linjesok(Husdjur Djur[], int n, string sökdjur)
{
	for (int i = 0; i < n; i++)
	{
		if (Djur[i].namn == sökdjur)
			return i;
	}
	return -1;
}




/*Den här funktionen utför en linjär sökning för att hitta 
djuret på det index man anger. Funktionen returnerar 
indexet djuret ligger på om djuret hittas eller annars 
returnerar värdet -1 om djuret inte hittas.*/
int Linjesok2(Husdjur Djur[], int n, int index)
{
	for (int i = 0; i < n; i++)
	{
		if (i == index)
			return i;
	}
	return -1;
}

//Här börjar Mainfunktionen som programmet körs i.
int main()
{
	setlocale(LC_ALL, "sv-SE");
	while (true)
	{
		cout << "Välkommen till min Husdjursbok!\n";
		cout << "Gör ett val i menyn under:\n";
		cout << "[V]isa lista över Husdjur\n";
		cout << "[S]ök efter Husdjur\n";
		cout << "[R]edigera Husdjur\n";
		cout << "[A]vsluta Program\n";
		char menyVal;
		cin >> menyVal;

		/*Använder toupper för att det inte ska spela 
		någon roll om användaren matar in stora eller 
		små bokstäver.*/
		menyVal = toupper(menyVal);
		
		switch (menyVal)
		{
		case 'V':

			Husdjursinfo();
			break;

		case 'S':

/*Det här alternativet används med funktionen Linjesok. 
Man använder den för att kunna söka reda på ett husdjur
med hjälp av namnet på husdjuret. Hittar sökningen djuret
får man upp info om det, annars får man ett meddelande att
djuret inte finns i listan. Använder en {} runt denna del
av switchsatsen för att jag deklarerar en variabel jag 
sedan använder på ett annat sätt i en annan del av satsen
längre ned.*/

		{
			cout << "Vad heter husdjuret vill du söka" 
				 <<" efter? ";
			string sökdjur;
			cin >> sökdjur;
			Husdjuren();

			int i = Linjesok(Djur, 6, sökdjur);
			if (i == 0 || i == 1 || i == 2 || i == 3 ||
				i == 4 || i == 5)
			{
				cout << "Djuret du söker finns på index " 
					 << i << " med infon: " << endl;;
				cout << "Namn: " << Djur[i].namn << endl;
				cout << "Ålder: " << Djur[i].alder 
					 << endl;
				cout << "Typ av djur: " 
					 << Djur[i].typavdjur << endl;
				cout << "Är djuret avlidet (J = Ja, N"
					 <<"= Nej): " 
					<< Djur[i].avliden << endl;
			}
			else
			{
				cout << "Djuret du sökte på finns inte"
					 <<" på listan. \n";
			}

			break;
		}
		case 'R':

/*Man använder i detta alternativ funktionen Linjesok2 och
kan då söka reda på djuret man vill redigera med hjälp av
numret på djurets index. Man får sedan redigera djuret om
det finns med på listan annars får man upp ett meddelande
om att djuret inte finns på listan. Är kodat för att tåla
felinmatningar på ålder. Använder {} runt denna del av 
switchsatsen för att jag använder en variabel som jag sedan
återanvänder högre upp beroende på vad användaren matar in
för val. */

		{
			cout << "Ange indexnr på djuret du vill "
				 <<"redigera: ";
			int index;
			cin >> index;

			if (cin.fail())
			{
				cin.clear();
				cin.ignore();
				cout << "Ange en siffra!\n";
			}
			else
			{
				Husdjuren();
				int i = Linjesok2(Djur, 6, index);
				if (i == 0 || i == 1 || i == 2 || i == 3 
					||i == 4 || i == 5)
				{
					cout << "Djuret heter " 
						 << Djur[i].namn 
						 << ". Vad vill du ändra" 
						 <<" namnet till? ";
					cin >> Djur[i].namn;
					cout << "Ange " 
						 << Djur[i].namn 
						 << "s ålder: ";
					cin >> Djur[i].alder;
					if (cin.fail())
					{
						cin.clear();
						cin.ignore();
						cout << "Ange en siffra!\n";
						cout << "Ange " 
							 << Djur[i].namn 
							 << "s ålder: ";
						cin >> Djur[i].alder;

						if (cin.fail())
						{
							cin.clear();
							cin.ignore();
							cout << "Ange en SIFFRA"
								<<" i nästa" 
								<<" försök," 
								<<" nu får du" 
								<<" börja om!"
								<<endl;
						}
					}
					else
					{
						cout << "Ange vilken typ av"
							 <<"djur " 
							 << Djur[i].namn 
							 << " är: ";
						cin >> Djur[i].typavdjur;
						cout << "Ange om " 
							 << Djur[i].namn 
							 << " är avliden (J ="
							 <<"Ja och N = Nej):";
						cin >> Djur[i].avliden;
					}
				}
				else
				{
					cout << "Indexet du angav finns "
						<<"inte på listan\n";
				}
			}
			break;
		}

		case 'A':
//Vad som händer vid val A. Programmet avslutas.
			return 0;
//Vad som händer om inget av valen ovanför stämmer in.
		default:
			cout << "Ogiltigt val, försök igen.\n";
		}
	}
}
Schwartz 42
Postad: 22 feb 12:59

Insåg att filen jag lagt upp överst hade en del fel som till och med jag såg som är återgärdade nu, bl a att sökfunktionerna hade olika namn och fel kommentarer över, blev så när jag ändrade om men nu har jag ändrat dem igen men det hjälper inte, har fortfarande typ 40 felkoder. Nån som vill hjälpa till? :(

Laguna Online 30471
Postad: 22 feb 13:05

En sak är att alla funktioner som du anropar i main.cpp men inte är definierade där måste deklareras i main.cpp eller någon fil som den inkluderar, förslagsvis Funktioner.h. T.ex. en rad

int Sok2(Husdjur Djur[], int n, int index);

Det är möjligt att namespace måste anges i alla filer, jag kan inte den delen av C++.

Schwartz 42
Postad: 22 feb 13:18

Gör jag så får jag hur många som helst av felkoden subscript requieres array or pointer type i main filen. Vad beror det på?

Laguna Online 30471
Postad: 22 feb 13:21

Vet inte. Jag ser att du inte ens använder den funktionen.

Strunta i den, och ta hand om Linjesok2, t.ex.

Schwartz 42
Postad: 22 feb 13:25

Det har jag gjort, o nu får jag bara denna: Severity Code Description Project File Line Suppression State Details
Error LNK2005 "struct Husdjur * Djur" (?Djur@@3PAUHusdjur@@A) already defined in ConsoleApplication21.obj ConsoleApplication21 C:\Users\loove\Documents\Visual Studio 2022\Templates\ProjectTemplates\Visual C++\ConsoleApplication21\Funktioner.obj 1

Laguna Online 30471
Postad: 22 feb 13:30

Du ska inte ha

Husdjur Djur[6];

i Funktion.h. Det är en definition och krockar med den du har i main.cpp. Det du vill göra är att deklarera Djur så att funktionen Husdjuren ser den, och det gör man antingen så här

Husdjur Djur[];

eller så här

extern Husdjur Djur[];

I C gör man på det senare sättet, i C++ vet jag inte.

Schwartz 42
Postad: 22 feb 13:31

Okej, vart ska jag ha Husdjur Djur[6] någonstans då? i main? :)

Schwartz 42
Postad: 22 feb 13:33

Ja det skulle man! Om jag använde Husdjur Djur[]; i h filen o den andra i main funkade det! Tack för hjälpen! :))))

anders_k 237
Postad: 23 feb 17:47

Normalt är det bra innan man börja koda att man tänker efter vilka moduler man vill dela upp programmet i. 

Ett annat tip är att avstå från globala variabler, istället skapa din struct array inne i main,  sen skicka den till de funktioner som behöver den. T.ex. en funktion ShowMenu() behöver inte veta om arrayen. På så vis blir beroenden tydligare och det gör att programmet blir lättare att läsa.

Normalt så använder man aldrig i modern C++ native arrays utan det är std::vector och std::array som gäller (och för all del std::span).

Svara
Close