[C/C++]Błąd podczas kompilacji


(Rdrfear) #1

Witam.

Mam taki mały problem.

Chcę stworzyć plik binarny o nazwie podanej z klawiatury.

Zadeklarowałem sobie char f[20], który ma przechowywać właśnie tą nazwę.

FILE* plik=fopen("f", "wb");

fwrite(&tab, sizeof(Osoba), i, "f");


fclose("f");

W tym kodzie wyskakuje mi błąd:

test.cxx:88:26: error: cannot convert 'std::string {aka std::basic_string}' to 'const char*' for argument '1' to 'FILE* fopen(const char*, const char*)'

test.cxx:89:36: error: cannot convert 'const char*' to 'FILE* {aka _iobuf*}' for argument '4' to 'size_t fwrite(const void*, size_t, size_t, FILE*)'

test.cxx:91:10: error: cannot convert 'std::string {aka std::basic_string}' to 'FILE* {aka _iobuf*}' for argument '1' to 'int fclose(FILE*)'

test.cxx:88:8: warning: unused variable 'plik' [-Wunused-variable]

Kompilacja nie powiodła się

Nie mam pojęcia co dalej z tym robić. Wydaje się, że coś źle wpisuję jako nazwę pliku. Tylko jak to poprawić?

Dzięki.


(Razi) #2

Skoro f jest char[], to czemu jako pierwszy argument podajesz "f"? W ten sposób przekazujesz ciąg znaków, czyli tekst (stały literał) "f" zamiast ciąg z tablicyf.

test.cxx:88:26: error: cannot convert 'std::string {aka std::basic_string}' to 'const char*' for argument '1' to 'FILE* fopen(const char*, const char*)'

std::string to nie (const) char*. Możesz wyciągnąć ciąg w postaci char* poprzez metodę (std::string).c_str()

test.cxx:89:36: error: cannot convert 'const char*' to 'FILE* {aka _iobuf*}' for argument '4' to 'size_t fwrite(const void*, size_t, size_t, FILE*)'

Za 4 argument podajesz wskaźnik (uchwyt) do pliku, a nie jego nazwę, znów podana nieprawidłowo, bo przez gotowy ciąg znaków zamiast wyciągnięcie go z tablicy. Wskaźnikiem na plik jest zmienna (wkaźnik) `plik u ciebie.

test.cxx:91:10: error: cannot convert 'std::string {aka std::basic_string}' to 'FILE* {aka _iobuf*}' for argument '1' to 'int fclose(FILE*)'

Znów w fclose używasz stałego literału. Przekazujesz tam wskaźnik do pliku, nie jego nazwę.

test.cxx:88:8: warning: unused variable 'plik' [-Wunused-variable]

Ostrzeżenie o nieużywanym pliku.


(Rdrfear) #3

Popatrzyłem, poczytałem, zrozumiałem. A oto poprawiony fragment. Kompilator już się nie drze.

FILE* plik=fopen(f, "wb");

fwrite(&tab, sizeof(Osoba), i, plik);


fclose(plik);

Dzięki za wytłumaczenie. Mam jeszcze jeden malutki problemik. Otóż mam: char klucz[9]; //na tej tablicy będzie nazwisko, wzrost lub wiek Chcę porównać to co znajduje się pod kluczem z wyrazami nazwisko, wiek i wzrost. Napisałem:

if(klucz == 'nazwisko')

I dostaję:

warning: character constant too long for its type [enabled by default]

To samo z wiekiem i wzrostem. Czy ja dobrze zapisuję to porównanie?

//Rozwiązałem ten problem za pomocą strcmp.


(Razi) #4

Nie. Apostrofy pojedyncze ' służą do pisania pojedynczych znaków ((typ char), a " do słów (typ const char*, lub char*). Operator == porównuje obiekty, jeśli chcesz porównać char* z innym char*, operator == sprawdzi jedynie czy te 2 łańcuchy leżą w tym samym miejscu w pamięci.

Do ich porównania musisz użyć funkcji strcmp(const char*, const char*), kolejność argumentów dowolna.

Funkcja zwraca 0 jeśli oba ciągi są identyczne, lub liczbę większą od zera, gdy są różne (liczba to indeks pierwszych różniących się znaków)


(Rdrfear) #5

Powstał jeszcze jeden problem.

Mam funkcję, która poszukuje elementów spełniających dane warunki, a potem wyświetla je na ekranie. Dostaje ona: nazwę pliku, z którego ma czytać elementy, dany warunek nazwisko, warunek wiek, warunek wzrost1 i wzrost2(rekordy mieszczące się między nimi są wypisywane). Jeżeli warunki nazwisko i/lub wiek dostaną wartość 0 to wyłączamy odpowiedni filtr.

Ona wczytuje do tablicy dane z pliku, po czym porównuje warunki(podane nazwisko lub/i podany wiek i podany wzrost) z elementami (elementami są struktury osoba: nazwisko, wiek, wzrost).

Niestety nie wiem co jest nie tak, ale funkcja nie wyświetla niczego, tak jakby się nie wykonała wcale, a menu programu wyświetla się ponownie.

Oto samo porównywanie:

if(nazwisko != 0 && wiek != 0)

	{

		for(int j=0;j
		{

			if(!strcmp(tab[j].nazwisko,nazwisko) && tab[j].wiek == wiek && tab[j].wzrost >= wzrost1 && tab[j].wzrost <= wzrost2)

			{

				printf("%s %d %f", tab[j].nazwisko, tab[j].wiek, tab[j].wzrost);

			}

		}

	} else if(nazwisko == 0 && wiek != 0) {

		for(int j=0;j
		{

			if(tab[j].wiek == wiek && tab[j].wzrost >= wzrost1 && tab[j].wzrost <= wzrost2)

			{

				printf("%s %d %f", tab[j].nazwisko, tab[j].wiek, tab[j].wzrost);

			}

		}

	} else if(nazwisko != 0 && wiek == 0) {

		for(int j=0;j
		{

			if(tab[j].nazwisko == nazwisko && tab[j].wzrost >= wzrost1 && tab[j].wzrost <= wzrost2)

			{

				printf("%s %d %f", tab[j].nazwisko, tab[j].wiek, tab[j].wzrost);

			}

		}

	} else if(nazwisko == 0 && wiek == 0) {

		for(int j=0;j
		{

			if(tab[j].wzrost >= wzrost1 && tab[j].wzrost <= wzrost2)

			{

				printf("%s %d %f", tab[j].nazwisko, tab[j].wiek, tab[j].wzrost);

			}

		}

	}

Żadnych błędów podczas kompilacji, czyli to sama koncepcja nie jest poprawna.

Dzięki.


(Razi) #6

Czy dane w ogóle się poprawnie wczytują?

Nie bój się używać printfów wszędzie gdzie się da by się tylko dowiedzieć czy dane fragment kodu jest wykonywany i jakie zmienne mają wartości.

Jeśli zmienna nazwisko jest char*, to porównując ją do 0 sprawdzasz, czy został podany NULL.


(Rdrfear) #7

Sprawdziłem przed chwilą i:

w if'ach gdzie mam nazwisko != 0, operacje wykonują się i działają poprawnie. Pozostały tylko 2 if'y gdzie nazwisko porównuje do zera i wiek jest niezerowy oraz wiek jest także zerem.

Sprawdziłem printf'ami jakie pobieram dane - są one poprawne.

Będę cały czas testował kod, jakby ktoś coś zauważył w kodzie nie tak to proszę o podpowiedź.

//Edit: Okazało się, że problem rozwiązać można za pomocą funkcji strcmp(). Dzięki.