2013-05-07 10 views
9

Czy można przekonwertować int na "string" w C, używając tylko rzutowania? Bez żadnych funkcji, takich jak atoi() lub sprintf()?Prześlij int do tablicy znaków w C

Co chcę byłoby tak:

int main(int argc, char *argv[]) { 
    int i = 500; 
    char c[4]; 

    c = (char)i; 
    i = 0; 
    i = (int)c; 
} 

Powodem jest to, że muszę generować dwa losowe ints (0 do 500) i wysyłać zarówno jako jeden ciąg w kolejce komunikatów do innego procesu. Drugi proces odbiera komunikat i wykonuje LCM.

Wiem, jak to zrobić z atoi() i itoa(). Ale moi nauczyciele chcą tylko używać obsady.

Dlaczego poniższe kompilacje nie są możliwe?

typedef struct 
{ 
    int x; 
    int y; 
} int_t; 

typedef struct 
{ 
    char x[sizeof(int)]; 
    char y[sizeof(int)]; 
} char_t; 

int main(int argc, char *argv[]) 
{ 
    int_t rand_int; 
    char_t rand_char; 

    rand_int.x = (rand() % 501); 
    rand_int.y = (rand() % 501); 

    rand_char = (char_t)rand_int; 
} 
+9

kluczowy zwrot jest „moi nauczyciele want' co oznacza, że ​​wszystko jest po abyś zrozumiał, a nie żebyśmy ci pokazali. ~ smile ~ –

+0

Nie możesz wyobrazić sobie wysiłku, czasu i badań, które zmarnowałem próbując to zrobić. Wszystko działa dobrze, po prostu obsada nie działa. – Bodosko

+5

Chciałbym kontratakować, że straciłeś jedną sekundę ... zrobiłeś dokładnie to, co zamierzali nauczyciele ... spędziłeś dużo czasu, zastanawiając się, jak tego nie robić. I to jest niezwykle cenne jako programista. –

Odpowiedz

4

Trzeba przekonwertować 500 do "500".

"500" jest taka sama jak '5' następnie '0' następnie '0' następnie 0. Ostatni element 0 jest terminatorem zerowym łańcucha.

500 jest równa 5 * 100 + 0 * 10 + 0 * 1. Trzeba tu trochę matematyki. Zasadniczo musisz użyć operatora /.

Może to być również przydatne: '5' jest taki sam jak '0' + 5.

+1

Ale w ten sposób nie użyłbym odlewania. Mogę sobie wyobrazić wiele sposobów robienia tego, czego potrzebuję, ale każdy z nich wymaga obsady i nie mam pojęcia, nawet jeśli jest to możliwe. – Bodosko

+1

Wymóg używania odlewania nie jest praktyczny. To tak, jakby powiedzieć komuś, że musi rozwiązać problem z kalkulatorem, kiedy już to zrobili w swojej głowie. Po prostu rozwiązaj to bez odlewania. (W razie potrzeby przykleić sztuczny rzut, np. Wpisując 1 + 1 = do kalkulatora.) –

11

Oczywiście nie jest to możliwe, ponieważ tablica jest obiektem i potrzebuje przechowywania. Przesyła wynik w postaci wartości, a nie obiektów. Niektórzy powiedzieliby, że cały punkt/moc C jest taka, że ​​masz kontrolę nad przechowywaniem i czasem życia obiektów.

Właściwym sposobem, aby wygenerować ciąg zawierający reprezentację dziesiętną liczbą całkowitą jest stworzenie przechowywanie to sam i korzystać snprintf:

char buf[sizeof(int)*3+2]; 
snprintf(buf, sizeof buf, "%d", n); 
1

Bez obdarowywała dokładną zakodowaną odpowiedź, co zechcesz do to przechodzi przez każdą cyfrę liczby całkowitej (obliczając jej resztę modulo 10 za pośrednictwem operatora%), a następnie dodaje jej wartość do wartości ASCII równą "0", odrzucając wynik z powrotem do znaku i umieszczając ten wynik w postaci zakończony znakiem NUL ciąg.

Przykładem, który udaje, jak ukrytych odlewów nie istnieją może wyglądać następująco:

char c = (char) (((int) '0') + 5); // c should now be '5'. 

Można określić długość łańcucha wynikowego obliczając podstawę log10 liczby, lub po prostu przydzielenie dynamicznie, gdy używasz realloc().

2

Rzucanie jest okropnym sposobem na zrobienie tego z powodu endianizmu, ale tutaj jest to przykład w każdym razie - są pewne okazje, w których jest to przydatne (związki działają obecnie lepiej, ze względu na obsługę tych typów rzutów przez kompilator).

#include <stdio.h> //for printf 
#define INT(x) ((int*)(x)) //these are not endian-safe methods 
#define CHAR(x) ((char*)(x)) 
int main(void) 
{ 
    int *x=INT(&"HI !"); 
    printf("%X\n",*x); //look up the ascii and note the order 
    printf("%s\n",CHAR(x)); 
    return 0; 
} 

Dla int o wartości < 500, jeśli najbardziej znaczący bajt jest na pierwszym miejscu, a następnie dostać "string" (wskaźnik do tablicy char) z "" (lub {0}), ale jeśli endianness jest najpierw LSB (x86 jest małym endianem), wtedy dostaniesz użyteczny 3-bajtowy "ciąg" char * (niekoniecznie ludzkie czytelne znaki), ale nie ma gwarancji, że będzie zero bajtów w liczbie całkowitej i ponieważ wszystko, co masz, jest wskaźnikiem do adresu, w którym int było przechowywane, jeśli miałbyś uruchamiać na nim normalne funkcje łańcuchowe, przeszłyby one poza koniec pierwotnej int do no-mans-land (w małych programach testowych to będzie często są to zmienne środowiskowe) ... w każdym razie dla większej przenośności używać sieci kolejność bajtów (co za mały endian jest no-op):

#include <arpa/inet.h> 
uint32_t htonl(uint32_t hostlong); 
uint16_t htons(uint16_t hostshort); 
uint32_t ntohl(uint32_t netlong); 
uint16_t ntohs(uint16_t netshort); 

te funkcje tylko byteswap jako niezbędne do uzyskania sieciowej kolejności bajtów. Na twoim x86 zostaną zoptymalizowane, więc równie dobrze możesz je wykorzystać do przenoszenia.

0

Tylko dlatego, że nie jest jeszcze na liście: tu sposób przekonwertować int do char tablicę alokacji zmiennej wielkości stosując snprintf:

int value = 5 

// this will just output the length which is to expect 
int length = snprintf(NULL, 0, "%d", value); 

char* valueAsString = malloc(length + 1);// one more for 0-terminator 
snprintf(valueAsString, length + 1, "%d", value);