konwersje typów błąd access violation

0

Witam
Piszę program w borland c++ builder, który przelicza liczbę z określonego systemu pozycyjnego na system dziesiętny.
deklaruję tablicę na wprowadzaną liczbę w komponenice TEdit. kod przedstawia się następująco:

char *PodanaLiczba;
.
.
.
.
DlugoscLiczby = Edit1->Text.Length();

do zadeklarowanej tablicy PodanaLiczba chcę wczytać liczbę z komponentu TEdit1

sprintf(PodanaLiczba,"%s",Edit1->Text.c_str()); //i w tej linijce wywala mi błąd

nie wiem co jest grane bo raz kompiluje się i działa bez problemu a teraz program nie chce się skompilować i dostaję błąd AccessViolation

0

A zaalokowałeś miejsce w zmiennej PodanaLiczba? :P
PS to nie jest tablica w rozumieniu ścisłym, a sam wskaźnik.

0

Mógłbyś podać instrukcję jak to zrobić. Czy czeka mnie wywołanie funkcji malloc? Może lepiej byłoby zadeklarować jawnie tablicę np 30 elementów?

0

Może lepiej byłoby zadeklarować jawnie tablicę np 30 elementów?

Pomyśl chwilę.
Przecież znasz dokładnie długość tego ciągu, po kiego miałbyś na sztywno inicjować tę tablicę?

Inna sprawa, że co tak właściwie próbujesz zrobić i dlaczego korzystasz z tzw.C-with-classes (char*), a nie C++ (std::string)?

0

Chodzi o to że ten ciąg to liczba w systemie liczbowym o podstawie od 2 do 16 i nie jest znana jej określona długość. Jest wprowadzana przez użytkownika może składać się z 5 lub 10 albo 15 cyfr.

0

Jest wprowadzana przez użytkownika może składać się z 5 lub 10 albo 15 cyfr.

I co, chcesz mi powiedzieć, że Edit1->Text.length() czy tam strlen(Edit1->Text.c_str()) nie zwróci tej długości, co?

0

ups
ale czy to znaczy że muszę dynamicznie alokować pamięć? Już zmieniłem wskaźnik na tablicę i program produkuje poprawne wyniki.

0

Może tak, może nie, pokaż więcej kodu.

0

Ale po co tak na około. Skoro to jest C++ Builder to czemu nie wykorzystać tego czym posługuje się VCL czyli AnsiString/UnicodeString/String?

0

Witam
Trochę na okrągło bo piszę w C używając Borlanda. Wrzucam też kawałek kodu.

if(ComboBox1->ItemIndex == 1)
        {
                DlugoscLiczby = Edit1->Text.Length();
                PodanaLiczba = (char*)malloc(DlugoscLiczby);

                sprintf(PodanaLiczba,"%s",Edit1->Text.c_str());

                for(int i=0;i<DlugoscLiczby;i++)
                {
                        if(PodanaLiczba[i]=='0'||PodanaLiczba[i]=='1'||PodanaLiczba[i]=='2')
                                continue;
                        else
                        {
                                BladZapisu = true;
                                Edit2->Text = "BLAD ZAPISU";
                        }
                }

                LiczbaDziesietna = 0;
                if(!BladZapisu)
                {
                        int Licznik = DlugoscLiczby - 1;
                        int i = 0;
                        int cyfra;

                        while(Licznik>=0)
                        {
                                cyfra = PodanaLiczba[Licznik] - '0';
                                LiczbaDziesietna += cyfra * pow(3,i);
                                i++;
                                Licznik--;
                        }
                        Edit2->Text = IntToStr(LiczbaDziesietna);
                }
                free(PodanaLiczba);
        }

Mam jeszcze pytanie czy prawidłowo przydzielam pamięć, czy prawidłowo odwołuję się do zarezerwowanej pamięci i czy prawidłowo zwalniam pamięć

0

Cóż skoro chcesz pisać to w C, za pomocą Buildera to faktycznie musisz użyć char*. Jednak taki kod jak pokazałeś jest trochę zły. Niby caly algorytm jest napisany w "C", ale korzystasz z metod VCL, więc bardziej to taka sztuka dla sztuki. Jeśli już chcesz coś zrobić pisząc w czystym C i korzystać z graficznego GUI jaki daje Builder to zamiast pakować całość w if'a wydziel to do odrębnej funkcji. Będzie łatwiej, czytelniej i bardziej poprawnie. Zatem napisz funkcję taką:

int Zamiana(char *PodanaLiczba, int *LiczbaDziesietna)
{
  int DlugoscLiczby = strlen(PodanaLiczba);

  for (int i = 0; i < DlugoscLiczby; i++)
  {
    if(PodanaLiczba[i]=='0'||PodanaLiczba[i]=='1'||PodanaLiczba[i]=='2')
      continue;
    else
    {
      return 0;
    }
  }

  *LiczbaDziesietna = 0;
  int Licznik = strlen(PodanaLiczba) - 1;
  int i = 0;
  int cyfra;

  while(Licznik>=0)
  {
    cyfra = PodanaLiczba[Licznik] - '0';
    *LiczbaDziesietna += cyfra * pow(3,i);
    i++;
    Licznik--;
  }
  return 1;
}



if (ComboBox1->ItemIndex == 1)
{  
    char *PodanaLiczba = (char*)malloc(Edit1->Text.Length());
    int LiczbaDziesietna;

    sprintf(PodanaLiczba,"%s",Edit1->Text.c_str());

    if (Zamiana(PodanaLiczba,&LiczbaDziesietna))
      Edit2->Text = IntToStr(LiczbaDziesietna);
    else
      Edit2->Text = "BLAD ZAPISU";

     free(PodanaLiczba);
}

Pisane z palca, ale powinno dobrze działać, chociaż nie testowałem. Od razu widać co jest co, a sama funkcja zmieniająca na liczbę dziesiętną jest napisana w samym C. Co do zarządzania pamięcią, to jest ok. Ogólnie to można by się przyczepić do wywołania malloc, ale generalnie jest ok.

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