2009-05-05 12 views
6

Jaki jest najlepszy sposób konwersji niepodpisanej tablicy znaków na tablicę typu float w języku C++?Przesyłanie tablicy niepodpisanych znaków do tablicy zmiennych

że obecnie mają pętli następująco

for (i=0 ;i< len; i++) 
    float_buff[i]= (float) char_buff[i]; 

również trzeba odwrócić procedurę, tj konwersji z unsigned char float (float do przekształcenia 8-bitowego)

for (i=0 ;i< len; i++) 
    char_buff[i]= (unsigned char) float_buff[i]; 

Wszelkie porady być docenionym

Dzięki

+1

Co ty robisz to wymaga? –

Odpowiedz

2

Twoje rozwiązanie wydaje się ale w drodze powrotnej możesz utracić zmienne cyfry w rzucie.

+0

Dzięki Jestem zdezorientowany, który styl C++ używać (reinterpretować lub statyczne), więc użyłem starego stylu, Wszelkie pomysły. Co się dzieje, gdy konwersja z float na unsigned char ma wartość większą niż 255.0. (nie martwi się o cyfry po punkcie) Dzięki –

+0

W przypadku, gdy liczba zmiennoprzecinkowa jest większa niż 255, będzie miała wynik MOD po odlaniu (tak samo jak w przypadku każdego innego przelewu). Na przykład: float = 500 -> char = 254. float = 256 -> char = 0. BTW, oto kilka informacji na static_cast: http://stackoverflow.com/questions/103512/in-c-why-use-staticcastintx -instead-of-intx –

+0

Zachowanie, jeśli zmienna> = 256 jest niezdefiniowana - uzyskanie wartości modulo może być powszechne, ale nie jest gwarantowane. –

2

W jakim celu to robisz? Wrzucenie floata do chara nie ma sensu. Na większości platform liczba zmiennoprzecinkowa wynosi 4 bajty i reprezentuje liczbę zmiennoprzecinkową, gdzie jako znak będzie 1 bajtem i często reprezentuje pojedynczy znak. Stracisz 3 bajty danych, próbując wrzucić element pływający w znak, prawda?

+0

Dzięki Potrzebuję przekonwertować z float na 8bit –

+0

Odlew wykona konwersję - obcina ułamkową część pływaka. Może to być dokładnie to, czego chce ta osoba. Kluczową rzeczą, o której należy pamiętać, jest to, że jeśli integralna część pływaka nie może być przedstawiona w postaci bez znaku (zazwyczaj, jeśli nie znajduje się w zakresie 0-255), jest niezdefiniowana. –

+0

Dzięki Michael, nie mam nic przeciwko utracie części ułamkowej. Jeśli liczba zmiennopozycyjna jest mniejsza niż 255, czy rzutowanie będzie prawidłowe? Chciałem zacieśnić wynik do 255, jeśli pływak był większy od tego. Dzięki –

8

Twoje rozwiązanie jest całkiem dużo najlepszym rozwiązaniem, jednak chciałbym rozważyć przejście do:

char_buff[i]= static_cast<unsigned char>(float_buff[i]); 
0

Jeśli masz do czynienia z bardzo dużych tablic i wydajność jest niezbędna wówczas następujące mogą okazać się nieco bardziej wydajne:

float *dst = float_buff; 
    unsigned char *src = char_buff; 

    for (i=0; i<len; i++) *dst++ = (float)*src++; 
+0

Dzięki Dan, doceń końcówkę –

+0

Lub std :: copy (char_buff, char_buff + len, float_buff); –

+0

Użycie std :: copy ujawnia wadę w STL (tak samo jak C++). Kiedy tworzysz kopię czegoś, powinno być prawdą, że kopiuje == oryginał. Opierając się na niejawnym rzucaniu, nie jest to już prawdą, dlatego należy unikać ukrytego rzucania. –

2

Twoja pierwsza pętla nie wymaga rzutowania. Można niejawnie przekonwertować z jednego typu (np. unsigned char) na szerszy typ (np. float). Twoja druga pętla powinna wykorzystać static_cast:

for (i=0; i< len; i++) 
    char_buff[i]= static_cast<unsigned char>(float_buff[i]); 

Używamy static_cast wyraźnie poinformować kompilator zrobić konwersję do węższego typu. Jeśli nie użyjesz rzutowania, Twój kompilator może ostrzec Cię, że konwersja może spowodować utratę danych. Obecność operatora obsady oznacza, że ​​rozumiesz, że możesz stracić precyzję danych i nie masz nic przeciwko temu. To jest nie odpowiednie miejsce do korzystania z reinterpret_cast. W przypadku static_cast masz co najmniej pewne ograniczenia dotyczące konwersji (np. Prawdopodobnie nie pozwolisz Ci przekonwertować wartości Bird* na Nuclear_Submarine*). reinterpret_cast nie ma takich ograniczeń.

Ponadto, oto co ma na ten temat do powiedzenia Bjarne Stroustrup.

9

Myślę, że najlepszym sposobem jest użycie obiektu funkcję:

template <typename T> // T models Any 
struct static_cast_func 
{ 
    template <typename T1> // T1 models type statically convertible to T 
    T operator()(const T1& x) const { return static_cast<T>(x); } 
}; 

następnie:

std::transform(char_buff, char_buff + len, float_buff, static_cast_func<float>()); 
std::transform(float_buff, float_buff + len, char_buff, static_cast_func<unsigned char>()); 

Jest to najbardziej czytelny, ponieważ mówi to, co zostało zrobione w języku angielskim: przekształcenia sekwencję do innego typu za pomocą statycznego odlewania. A przyszłe rzuty można wykonać w jednej linii.

1

Obsada jest automatyczna, więc nie trzeba jej wyraźnie określać.
Ale można użyć standardowych algorytmów:

std::copy(char_buff,char_buff+len,float_buff); 

Nawrócenie float na char istnieje potencjalna utrata informacji. Musisz więc być bardziej konkretny.

std::transform(float_buff,float_buff+len,char_buff,MyTransform()); 

Tutaj używamy klasy MyTransform, która powinna mieć operator(), który pobiera float i zwraca znak. To powinno być trywialne.

0

Nikt o tym nie wspomniał, ale jeśli robisz arytmetykę z pływakami, możesz zaokrąglić zamiast obcinać ... jeśli masz znak 49 i zostanie on przekształcony w 4.9E1, po niektórych arytmetyczna, może zmienić się w 4.89999999E1, która zmieni się w 48, gdy zmienisz ją z powrotem w znak.

Jeśli nie robisz nic z pływakiem, nie powinno to stanowić problemu, ale dlaczego w pierwszej kolejności jest to potrzebne?

Powiązane problemy