VISUAL C++ - problem z funkcją fgets()

0

W swojej klasie umieściłem następującą metodę:

 bool data_generator_2::Core::load_names(void)
{
   char *temp;
    char *line;
   int i;
   this->l_imion_m = 0;
   this->l_imion_m = 0;
   int k = 0;
   temp = (char*)malloc(this->s_word1 * sizeof(char));
   line = (char*)malloc(this->s_word3 * sizeof(char));
   FILE *plik;
   fopen_s(&plik,"source/imiona.csv","r");

   while(feof(plik)==0)
   {
      if(fgets(line,99,plik)!=0)return false;   <-########################################## tu zawsze zwraca FALSE

      i = 0;
      while(line[i+2]!='\n')
      {
         temp[i] = line[i+2];
         i++;
      }//while
        temp[i] = 0;

      switch(line[0])
      {
      case 77:
         {
            strcpy_s(imiona_m[this->l_imion_m],strlen(imiona_m[this->l_imion_m]),temp);
            this->l_imion_m++;
            break;
         }//M
      case 75:
         {
            strcpy_s(imiona_k[this->l_imion_k],strlen(imiona_m[this->l_imion_m]),temp);
            this->l_imion_k++;
            break;
         }//K
      }//switch
   }//while
   fclose(plik);
   free(temp);
   free(line);
   return true;
}//load_names

Jest to metoda klasy zarządzanej (ref)
Za każdym razem wywolanie tej metody kończy się na FGETS - za każdym razem zwraca błąd
Dlaczego?????

0

s_word3 - co to za zmienna?

0
 public: int s_word3;
 this->s_word3 = 100;
0

Przyjrzałem się temu bliżej i...

if(fgets(line,99,plik)!=0) return false;
documentation napisał(a)

On success, the function returns the same str parameter.
If the End-of-File is encountered and no characters have been read, the contents of str remain unchanged and a null pointer is returned.
If an error occurs, a null pointer is returned.
Use either ferror or feof to check whether an error happened or the End-of-File was reached.

Inaczej mówiąc, sprawdzasz czy nie było błędu if (zwracana wartość != BŁĄD) return false - chyba nie o to Ci chodzi?

0

Innymi słowy sprawdzasz dokładnie na odwrót...

// najkrócej
if (!fgets(line,99,plik)) { /* błąd */ }

// od drugiej strony
if (line != fgets(line,99,plik)) { /* błąd */ }

Ale nie o tym chciałem... MSM:

C:\...\main.cpp||In function 'int main(int, char**)':|
C:\...\main.cpp|128|warning: statement has no effect|
||=== Build finished: 0 errors, 1 warnings (0 minutes, 0 seconds) ===|

Domyślasz się, do czego ten wycinek kodu ? ;] Nie łapię - pierwszy lepszy kompilator wykrywa takie literówki, które nota bene są możliwe w każdym języku C podobnym, a więc C, C++, C#, JavaScript, PHP ... nawet w Javie nie powie nic więcej niż ten nieszczęsny gcc - coś w stylu "not a statement" wypluje. Różnica taka, że w Javie taki komunikat to już błąd. To nie żadne reguły - to tylko twoje olewanie komunikatów. 200 warningów ale skompilowało się? To leeeecimy ;)

0

dzięki za wszystkie sugestie, sorki że dopiero teraz piszę, ale w weekend nie mogłem ;)
pokombinowałem troszkę z tym ustrojstwem i wyszło mi coś takiego:

 bool data_generator_2::Core::load_names(void)
{
	char *temp;
           char *line;
	int i,j;
	char c;
	this->l_imion_m = 0;
	this->l_imion_m = 0;
	int k = 0;
	temp = (char*)malloc(30 * sizeof(char));
	line = (char*)malloc(100 * sizeof(char));
	char imiona_mm[1000][30];
	char imiona_kk[1000][30];
	//char line[100];
	FILE *plik;
	fopen_s(&plik,"source/imiona.csv","r");
	while(feof(plik)==0)
	{
	  // if(fgets(line,99,plik)!=0)return false;

	   fread(&c,sizeof(char),1,plik);
	   j=0;
	   while(c!='\n' && c!=0)
	   {
			line[j] = c;
			fread(&c,sizeof(char),1,plik);
			j++;
	   }
	   line[j] = 0;
	
		i = 0;
		while(line[i+2]!=0)
		{
			temp[i] = line[i+2];
			i++;
		}//while
        temp[i] = 0;

		switch(line[0])
		{
		case 77:
			{
				//strcpy_s(imiona_m[this->l_imion_m],strlen(imiona_m[this->l_imion_m]),temp);
				strcpy(imiona_mm[this->l_imion_m],temp);
				this->l_imion_m++;
				break;
			}//M
		case 75:
			{
				//strcpy_s(imiona_k[this->l_imion_k],strlen(imiona_m[this->l_imion_k]),temp);
				strcpy(imiona_kk[this->l_imion_k],temp);
				this->l_imion_k++;
				break;
			}//K
		}//switch
	}//while
	fclose(plik);
	free(temp);
	free(line);
	return true;
}//load_names

Zmieniłem tablicę alokowaną w innej metodzie przy pomocy malloc() i dealokowaną free()

 imiona_k i imiona_m

na tablicę wywołaną na sztywno:

 char imiona_mm[1000][30];
	char imiona_kk[1000][30];

i powyższy kod się wykonuje.

I rodzi się kolejne pytanie: jak powinno się alokować tablice znaków w VS C++ ?? bo chyba jednak nie malloc;/

0

To, że piszesz w C++, to tylko w jednym miejscu się da definitywnie stwierdzić. Może Inaczej, tego że używasz kompilatora C++, bo większość kodu napisałeś po prostu w C. :P
W manualu, książce czy co tam masz pod ręką poszukaj sobie o new i delete (malloc i free też zadziałają, tylko po co?) Już o stringach, vectorach i innych takich nikomu niepotrzebnych rzeczach nie wspominam. ;)

0

line ma zdaje się rozmiar 100 u Ciebie? Po kolei - wywal wszystkie magiczne 100, 30, i inne ... to aż się prosi, żeby się walnąć... zamień na

const size_t line_size = 100;
const size_t temp_size = 30;
// itd ...

po drugie, używaj tych stałych konsekwentnie, wszędzie jak leci. sprawdzaj zakresy, patrz co piszesz, skąd czytasz i czy niczego nie przekraczasz. Takie kawałki aż się proszą o SIGSEGV...

fread(&c,sizeof(char),1,plik);
j=0;
while(c!='\n' && c!=0)
{
   line[j] = c;
   // ....

facet - jeden problem z treścią pliku, albo jedna pomyłka w pisaniu, i wszystko się wypieprza, a Ty nie masz pojęcia co. sprawdzaj, wszystkie możliwe błędy, bo przy takim kodzie jaki masz, to grasz w rosyjską ruletkę.

size_t ffc = fread(&c,sizeof(char),1,plik) ) {
assert(1==ffc);
j=0;
while(c!='\n' && c!=0)
{
   assert(j<line_size);
   line[j] = c;
   // ....

malloc możesz używać, dokładnie tak. po prostu wyjeżdżasz za tablicę gdzieś pewnie. zamiana na "sztywne tablice" spowodowała pewnie, że wyjeżdżasz na coś "mniej ważnego" i program na razie się nie wywala... ale się wywali, jak pełnia księżyca przypadnie. include<cassert> i assert'uj wszystko co się da, jeśli chcesz na suchej pamięci posuwać. Albo, jeśli chcesz, żeby "działało", to zgodnie z zaleceniem z posta wyżej: std::string, std::getline, std::iostream, a całą funkcję rozbij na 15 funkcji trywialnych, z których każda ma 5 linijek, i nie ma prawa nic zrobić "nie tak".

1 użytkowników online, w tym zalogowanych: 0, gości: 1