Elektroda.pl
Elektroda.pl
X
Proszę, dodaj wyjątek www.elektroda.pl do Adblock.
Dzięki temu, że oglądasz reklamy, wspierasz portal i użytkowników.

Tablica char na float - czy funkcja poprawna?

marvin82 17 Lut 2010 14:02 2360 5
  • #1 17 Lut 2010 14:02
    marvin82
    Poziom 13  

    Code:

    float na_liczbe()
    {
      float wynik=0;
      float wynik_dzies=0;
      if (kropka<0)
      {
       for(int i=0;i<licznik_buf;i++)
          wynik=wynik*10+ ((int)bufor[i]+48);
      }
      else
      {
       lcd_puts("niepoprawny format");
      }
      return wynik;
    }


    Witam,
    napisałem taką funkcję która ma przerabiać tablicę charów na zwykły float, licznik_buf zwiększa się o 1 przy każdym wpisaniu znaku do bufora, który jest tablica znaków. Kropka jest mniejsza od zera jeśli w tablicy nie ma kropki. Znajomy podpowiedział mi że powinienem tam dopisać +48, problem w tym że funkcja nie działa jak powinna. Mógłby ktoś rzucić okiem? Ogólnie jest to program na Atmege ale wydaje mi się że w tym dziale lepiej pasuje.

    0 5
  • #2 17 Lut 2010 16:38
    pallid
    Poziom 20  

    Twoj algoryt nie jest poprawny. Zakladajac najprostszy przypadek, tj. liczba bez kropki dziesietnej, powinno byc cos takiego:

    Code:
    #include <math.h>
    

    long int wynik = 0;
    for(int i=0; i<licznik_buf; i++) {
        wynik += ((int)bufor[i] - 48) * pow(10, licznik_buf-i-1);
    }


    Kolejne zalozenie jest takie, ze [char] bufor zawiera tylko wartosci z przedzialu <48; 57> (czyli cyfry w tabicly ASCII) oraz, ew. wartosc 46 (kropka w tablic ASCII).

    Ogolnie, do konwersji ciagu znakow prosciej uzyc jest funkcji: double atof ( const char * str )

    0
  • #3 17 Lut 2010 21:02
    marvin82
    Poziom 13  

    Funkcja ładnie działa dopóki nie wpiszę więcej niż 2 cyfry, wtedy pomniejsza lub powiększa ostatnią cyfrę o 1, pomyślałem że to może coś z licznikiem bufora, to jego kod:

    Code:
    void dodaj_bufor(char znak)
    
    {
       //znak='a';
       if (licznik_buf<17)
          licznik_buf++;
       bufor[licznik_buf-1]=znak;
       bufor[licznik_buf]='\0';

    }

    0
  • #4 17 Lut 2010 22:45
    pallid
    Poziom 20  

    Twoja funkcja void dodaj_bufor(char znak) dziala w ten sposob: "Jesli licznik jest mniejszy od 17 to dodaj znak do bufora i zwieksz licznik. W przeciwnym razie podmien znak na przedostatniej, 17-tej, pozycji". Dodatkowo, na Twoj bufor (char bufor[]) powinno byc zarezerwowane 18 bajtow pamieci. Jesli takie jest zalozenie, to funkcja dodaj_bufor(char) jest srednio optymalna, ale poprawna.

    Natomiast problem z pomniejszaniem/powiekszaniem wartosci wynika z czegos innego. Sprawdz, czy przed wpisywaniem nowych znakow, licznik i bufor sa zerowane. Jesli masz mozliwosc, ustaw w swoim srodowisku stack trace (podglad zmiennych) i sprawdz krok po kroku jak zachowuje sie program.

    0
  • #5 18 Lut 2010 19:24
    marvin82
    Poziom 13  

    Ciężko tu zaobserwować zmiane tych wartości ponieważ jest to program na do mikrokontrolera ATMEGA, wrzucam cały kod, może będziecie wiedzieć co tu jest źle.

    Code:
    #define F_CPU 14.7456E6 //delay.h
    
    //na podstawie podanej czesotliwosci kwarcu obliczane beda opoznienia wystepujace w programie

    #include "pliki\io.h"
    #include "pliki\delay.h"
    #include "pliki\lcd.c"
    #include <stdio.h>
    #include <avr/io.h>
    #include <math.h>




    char bufor[17];  //bufor LCD
    char czyszczenie_linii[17]="                "; //16 spacji
    char* buffor;  //bufor LCD
    char bufor2[17];

    int licz_ob=0,licznik=0, przycisk=-1, kol=0, etap=0, licznik_buf=0, licznik_buf2=0, kropka=-1;
    int tmp;
    int miejsce_kropki=7; //precyzja wynikow
    long mnoznik=1;

    //########################################3      zamek szyfrowy    ############################
    int user_pin=0; // kod podany przez uzytkownika
    int pin=12;// prawidlowy kod
    int nowy_pin=0;


    void czysc_bufor()
    {
       licznik_buf=0;
       bufor[0]='\0';
    }

    void dodaj_bufor(char znak)
    {
       //znak='a';
       if (licznik_buf<17)
          licznik_buf++;
       bufor[licznik_buf-1]=znak;
       bufor[licznik_buf]='\0';

    }


    //######################################  zapis eeprom    3############################333333

    void EEPROM_write(unsigned int uiAddress, unsigned char ucData)
    {
    /* Wait for completion of previous write */
    while(EECR & (1<<EEWE))
    ;
    /* Set up address and data registers */
    EEARH = 0x00;
    EEARL = uiAddress;
    EEDR = ucData;
    /* Write logical one to EEMWE */
    EECR |= (1<<EEMWE);
    /* Start eeprom write by setting EEWE */
    EECR |= (1<<EEWE);
    }

    //#########################################    odczyt   EEPROM     #############################################

    unsigned char EEPROM_read(unsigned int uiAddress)
    {
    /* Wait for completion of previous write */
    while(EECR & (1<<EEWE))
    ;
    /* Set up address register */
    EEAR = uiAddress;
    /* Start eeprom read by writing EERE */
    EECR |= (1<<EERE);
    /* Return data from data register */
    return EEDR;
    }








    void inicjalizacja_systemu()
    {
       DDRB=0x0F;   // Port B - bity 0-3 jako wyjscia,bity 4-7 jako wejscia




       PORTB=0xFF;   // Port B wyjscia w stanie wysokim,wejscia z podciaganiem
       DDRA=0xFF; //linie LCD
       
       
       DDRE=0x0F;
       PORTE=0xFF;
       
       
       lcd_init(LCD_FUNCTION_4BIT_2LINES);   /*transmisja po 4 bity wyswietlacz 2 liniowy*/
       lcd_init(LCD_DISP_ON);//czyszczenie wyswietlacza
       for(int i=0;i<miejsce_kropki;i++)
          mnoznik=mnoznik*10;
    }

    char jaki_przycisk(char button)
    {
       switch(button){
          case 0x77:
             return 'x';
             break;
          case 0x7B:
             return '3';
             break;
          case 0x7D:
             return '2';
             break;
          case 0x7E:
             return '1';
             break;
          case 0xB7:
             return '+';
             break;
          case 0xBB:
             return '6';
             break;
          case 0xBD:
             return '5';
             break;
          case 0xBE:
             return '4';
             break;
          case 0xD7:
             return '-';
             break;
          case 0xDB:
             return '9';
             break;
          case 0xDD:
             return '8';
             break;
          case 0xDE:
             return '7';
             break;
          case 0xE7:
             return 'P';
             break;
          case 0xEB:
             return '.';
             break;
          case 0xED:
             return '0';
             break;
          case 0xEE:
             return 'C';
             break;
       default:
          return 'E';

       }
       return 'E';
    }


    int klawiatura()  // obsluga klawiatury
    {
       licz_ob++;               // Licznik obiegów pętli 
       if(licz_ob==10)       
        {
          kol++;            // Licznik kolumny
          licz_ob=0;
          if(kol==4)            // Przepełnienie licznika obiegów pętli
                kol=0;
          PORTB=0xFF;
          PORTB &= ~_BV(kol);
        }

       przycisk=PINB;
       if ((przycisk>>4)!=15)      // Wcisnięto klawisz
        {
          licznik=0;
          return przycisk;
        }
       return -1;
    }

    //###################################################  konwersja na liczbe   ###############################################
    float na_liczbe()    // konwersja znakow na liczbe
    {
      float wynik=0;

    for(int i=0; i<licznik_buf; i++)
    {
        wynik += ((int)bufor[i] - 48) * pow(10, licznik_buf-(i+1));
    }
    return wynik;
    }

    //   ##############################################   konwersja na znaki do wyswietlenia   #################################
    void na_znaki(float liczba)
    {
    long rzad=1;
    int licznik=1;


    while(liczba/rzad>=10)
       {
       rzad=rzad*10;
       licznik++;
       }


    for (int i=0; i<licznik;i++)
    {
       if (licznik-miejsce_kropki==0 && i==0)
          dodaj_bufor('0');
       if (i==(licznik-miejsce_kropki))
          dodaj_bufor('.');
       dodaj_bufor((char) ((int)(liczba/rzad)+48));
       liczba=liczba-rzad*(int)(liczba/rzad);
       rzad=rzad/10;
    }


    }

    //#########################################  główna funkcja   ###########################################
    int main(void)
    {
       inicjalizacja_systemu();
    lcd_gotoxy(0,0);
    lcd_puts("Podaj PIN");

       etap=1; //ustawienie etapu
       czysc_bufor();

       while(1)         // Nieskończona pętla
        {
          klawiatura();        // Obsługa klawiszy
          if (etap==1)
          {
             if (przycisk>1 && jaki_przycisk(przycisk)!='C'  && jaki_przycisk(przycisk)!='+' && jaki_przycisk(przycisk)!='-' && jaki_przycisk(przycisk)!='P' && jaki_przycisk(przycisk)!='.' && jaki_przycisk(przycisk)!='x' && jaki_przycisk(przycisk)!='E')
             {
                
                lcd_gotoxy(0,1);//linia dolna znak pierwszy
                dodaj_bufor(jaki_przycisk(przycisk));
                lcd_puts(bufor);
                _delay_ms(500);
                przycisk=-1;
             }
             if (przycisk>1 && jaki_przycisk(przycisk)=='C')
             {   
                lcd_init(LCD_DISP_ON);//czyszczenie
                lcd_gotoxy(0,1);//linia dolna znak pierwszy
                czysc_bufor();
                lcd_puts(czyszczenie_linii);
                _delay_ms(500);
                przycisk=-1;
                kropka=-1;
             }

             if (przycisk>1 && jaki_przycisk(przycisk)=='.' && kropka <0)
             {
                lcd_init(LCD_DISP_ON);//czyszczenie
                lcd_gotoxy(0,1);//linia dolna znak pierwszy
                kropka=licznik_buf;
                dodaj_bufor(jaki_przycisk(przycisk));
                lcd_puts(bufor);
                _delay_ms(500);
                przycisk=-1;
             }


             if (przycisk>1 && jaki_przycisk(przycisk)=='P')
             {
                lcd_init(LCD_DISP_ON);//czyszczenie
                user_pin=na_liczbe();
                czysc_bufor();
                _delay_ms(500);
                przycisk=-1;
                etap=2;
             }
             
             if (przycisk>1 && jaki_przycisk(przycisk)=='+')
             {
                lcd_init(LCD_DISP_ON);//czyszczenie
                user_pin=na_liczbe();
                czysc_bufor();
                _delay_ms(500);
                przycisk=-1;
                etap=3;
             }
          }


          if(etap==2)    // sprawdzenie czy PIN poprawny 
          {


          if (user_pin==pin)
             {
             lcd_init(LCD_DISP_ON);//czyszczenie
             lcd_puts("Otwarte");
             PORTE=0xFF;
             PORTE &=~_BV(1);
       
             
             _delay_ms(1000);
             PORTE=0xFF;
             lcd_init(LCD_DISP_ON);//czyszczenie
             lcd_puts("Podaj PIN");
             etap=1;
             }
       
          else
             {
             lcd_init(LCD_DISP_ON);//czyszczenie
             lcd_puts("Niepoprawny PIN");
             lcd_init(LCD_DISP_ON);//czyszczenie
             na_znaki(user_pin);
             lcd_puts(bufor);
             _delay_ms(1000);
             
             PORTE=0xFF;
             PORTE &=~_BV(0);
             _delay_ms(1000);
             PORTE=0xFF;
             
          
             lcd_init(LCD_DISP_ON);//czyszczenie
             lcd_puts("Podaj PIN");
             czysc_bufor();
             etap=1;
             }

          }
          
          
          if(etap==3)   // zmiana PIN
          {   
             if (user_pin==pin)
                {
                   lcd_init(LCD_DISP_ON);//czyszczenie
                   lcd_gotoxy(0,0);
                   lcd_puts("Zmiana PIN");
                   _delay_ms(1000);
                   lcd_init(LCD_DISP_ON);//czyszczenie
                   lcd_puts("Podaj nowy PIN");
                   _delay_ms(1000);
                   etap=31;
             
             
          
                }
             else
             
                {
                lcd_init(LCD_DISP_ON);//czyszczenie
                lcd_puts("PIN niepoprawny");
                _delay_ms(1000);
                lcd_init(LCD_DISP_ON);//czyszczenie
                lcd_puts("Podaj PIN");
                _delay_ms(1000);
                etap=1;
                
                }
          }
          
          
          if (etap==32)  // zmiana pinu, sprawdzenie czy dobry wpisany
          {
          pin=user_pin;
          lcd_init(LCD_DISP_ON);//czyszczenie
          lcd_puts("PIN zmieniony");
          _delay_ms(1000);
          
          lcd_init(LCD_DISP_ON);//czyszczenie
          lcd_puts("Nowy PIN to");
          lcd_gotoxy(0,1);
          na_znaki(user_pin);
          lcd_puts(bufor);
          czysc_bufor();
          _delay_ms(1000);
          lcd_init(LCD_DISP_ON);//czyszczenie
          lcd_puts("Podaj PIN");
          etap=1;
          }
          
          
          
          
          if (etap==31)    //  odczytywanie eprzyciskow dla zmianu PINU
          {
             if (przycisk>1 && jaki_przycisk(przycisk)!='C'  && jaki_przycisk(przycisk)!='+' && jaki_przycisk(przycisk)!='-' && jaki_przycisk(przycisk)!='P' && jaki_przycisk(przycisk)!='.' && jaki_przycisk(przycisk)!='x' && jaki_przycisk(przycisk)!='E')
             {
                
                lcd_gotoxy(0,1);//linia dolna znak pierwszy
                dodaj_bufor(jaki_przycisk(przycisk));
                //EEPROM_write(licznik_buf-1,jaki_przycisk(przycisk));
                lcd_puts(bufor);
                _delay_ms(500);
                przycisk=-1;
             }
             if (przycisk>1 && jaki_przycisk(przycisk)=='C')
             {   
                lcd_init(LCD_DISP_ON);//czyszczenie
                lcd_gotoxy(0,1);//linia dolna znak pierwszy
                czysc_bufor();
                lcd_puts(czyszczenie_linii);
                _delay_ms(500);
                przycisk=-1;
                kropka=-1;
             }

             if (przycisk>1 && jaki_przycisk(przycisk)=='.' && kropka <0)
             {
                lcd_init(LCD_DISP_ON);//czyszczenie
                lcd_gotoxy(0,1);//linia dolna znak pierwszy
                kropka=licznik_buf;
                dodaj_bufor(jaki_przycisk(przycisk));
                lcd_puts(bufor);
                _delay_ms(500);
                przycisk=-1;
             }


             if (przycisk>1 && jaki_przycisk(przycisk)=='P')
             {
                lcd_init(LCD_DISP_ON);//czyszczenie
                user_pin=na_liczbe();
                czysc_bufor();
                _delay_ms(500);
                przycisk=-1;
                etap=32;
             }
             
             if (przycisk>1 && jaki_przycisk(przycisk)=='+')
             {
                lcd_init(LCD_DISP_ON);//czyszczenie
                user_pin=na_liczbe();
                czysc_bufor();
                _delay_ms(500);
                przycisk=-1;
                etap=3;
             }
          }               
                      
                      
                      
                      
                      
                      
                      
                      
                      
                      


       
          

       }
    }

    0
  • #6 21 Lut 2010 00:34
    pallid
    Poziom 20  

    Przede wszystkim masz blad przepelnienia bufora w funkcji void dodaj_bufor(char). Poprawniej byloby zrobic to w taki sposob:

    Code:

    #define MAX_BUFFER_SIZE 17
    //...
    char bufor[MAX_BUFFER_SIZE] = {0};
    //...
    bool dodaj_bufor(char znak) {
       if (licznik_buf>= MAX_BUFFER_SIZE-1) {
          return false;
       }
       bufor[licznik_buf++]=znak;
       bufor[licznik_buf]='\0';
       return true;
    }


    Sprobuj tez posprzatac kod z nieuzywanych zmiennych. Mozesz napisac, na jakim etapie pojawia sie ten blad, o ktorym wspomniales? W trakcie odczytywania cyfr z klawiatury (etap == 1), czy w pozniejszym przetwarzaniu (etap > 1)? Ew. jakie wartosc podajesz i jakie rezultaty wtedy otrzymujesz.

    0