#c
#c
Вопрос:
Мой код завершается с ошибкой и возвращает действительно большое число:
#include <stdio.h>
int main()
{
char *s = "hello123";
printf("%dn",*(int *)s);
return 0;
}
с atoi он возвращает 0, есть идеи?
Чего я пытаюсь добиться: например, я отправляю «hello123» серверному программному обеспечению, серверное программное обеспечение должно получить числовое значение «123» в строке, делая это следующим методом:
uint16_t get_uint16(NetworkMessage *message)
{
uint16_t ret = 0;
if (!message || !message->buffer)
return 0;
ret = *(uint16_t *)(message->buffer message->position);
message->position = sizeof(uint16_t);
return ret;
}
Комментарии:
1. чего вы на самом деле пытаетесь достичь?
2. зачем использовать
*(int *)s
? Объясните это.3. @Mark: пытаюсь получить «123» по позиции в моем сетевом сообщении (в другой программе)
4. Каким был бы ожидаемый результат, если бы строка была «h8llo123»?
5. Я добавил больше информации, пожалуйста, ознакомьтесь с ней (подробнее объясняется)
Ответ №1:
Предполагается, что ваша строка состоит из двух частей: первые индексы содержат символы (например hello
), а последние индексы содержат число (например 123
). Насколько я понимаю из ваших комментариев, это то, что вы хотели сделать.
#include <stdio.h>
#include <stdlib.h>
int main()
{
char* s = "hello123";
char* num_ptr = s;
while(*num_ptr < '0' || *num_ptr > '9')
num_ptr;
int number = atoi(num_ptr);
printf("%dn", number);
return 0;
}
После редактирования: попробуйте это? Я предполагаю, message_buffer
содержит ваше сообщение и имеет тип char*
int get_number(char* message_buffer)
{
char* num_ptr = message_buffer strlen(message_buffer) - 1;
while(isdigit(num_ptr) amp;amp; num_ptr > message_buffer)
--num_ptr;
int number = atoi(num_ptr);
if(number > UINT16_RANGE)
//Handle error here
return number;
}
uint16_t get_uint16(NetworkMessage *message)
{
uint16_t ret = 0;
if (!message || !message->buffer)
return 0;
ret = get_number(message->buffer);
//message->position = sizeof(uint16_t);
return ret;
}
Комментарии:
1. @Fallen, каково точное содержимое
message->buffer
?2. @Muggen: исправлено, спасибо, я проголосовал за вас и принял ваш ответ!
3. @Fallen, упс, у меня была ошибка в коде. добавьте
-1
вstrlen()
строку, пожалуйста.4. @Fallen,
itoa()
возвращаетint
, но вы используетеuint16_t
значение, которое может быть меньше, если ваш int32bit
убедитесь, что вы позаботились обо всех условиях ошибки в//Handle error here
, которые я добавил.5. Даже после исправлений (isdigit(*num_ptr) и однократная ошибка в цикле while), get_number(«hello123a4») вернул бы 4, в то время как мой atoi_skip(«hello123a4») вернул бы 123.
Ответ №2:
Ваш код делает не то, что вы думаете. Вы не можете преобразовать текст в число и ожидать, что оно определит, какие числа вы хотите.
Строка — это массив символов, каждый из которых имеет значение ASCII. При приведении к (int*)
он принимает значение ASCII первых 4 символов (4 байта для int) и создает из него одно огромное число.
В вашем примере значения ASCII первых 4 символов являются { 0x68, 0x65, 0x6c, 0x6c }
. Теперь вы меняете порядок для систем с малым порядковым номером на { 0x6c, 0x6c, 0x65, 0x68 }
. Вы объединяете их в 0x6c6c6568
. Преобразование этого значения в десятичное является 1,819,043,176
. Какое число вы получите на выходе.
Если вам нужно только 123, вам нужно использовать умный синтаксический анализ строки, чтобы выделить hello
, а затем использовать atoi()
для остальных.
Комментарии:
1. Я добавил больше информации в основной пост, ознакомьтесь с ней
Ответ №3:
Вам нужно использовать atoi(s)
.
В вашем коде вы преобразуете указатель на строку в указатель на целое число, считывая первые четыре байта строки как некоторое большое целое число. int atoi(char*)
произведет надлежащий синтаксический анализ, возвращая целочисленное значение.
Синтаксический анализ «hello123» остановится на первом нечисловом символе и вернет 0. Вы можете пропустить нечисловые символы, тестируя с int isdigit(char)
:
int atoi_skip(char *s) {
while(*s != '' amp;amp; !isdigit(*s)) s ; /* skip non digits */
return atoi(s);
}
Ответ №4:
Все остальные абсолютно правы. Вы не можете преобразовать массив символов в целое число с помощью приведения. Это так не работает. В C символы представлены целыми числами. Когда вы пишете:
char *s = "hello123";
То, что вы получаете, — это массив с кучей символов в нем. Вы могли бы эквивалентно написать:
char *s = {'h', 'e', 'l', 'l', 'o', '1', '2', '3', ''};
Таким образом, когда вы вызываете printf("%dn",*(int *)s);
, то, что вы делаете, преобразует адрес памяти вашего символьного массива в указатель на целое число. Затем вы берете содержимое этого целого числа и печатаете его. Я почти уверен, что результат, который вы получите, будет зависеть от используемой вами системы, но это определенно не то, что вы хотите.
Что вы, вероятно, хотите сделать, так это:
printf("%dn", atoi(amp;(s[5]));