2014-01-15 3 views
0

Я ищу способ взять строку и проверить 3 возможности.Перевести строку на номер

  • Digit и, таким образом, преобразует его в знаковом междунар (не долго)
  • ли символическое представление определены ранее во время выполнения, и преобразует его в знаковом ИНТ
  • Ни

«символическое представление» будет в основном как ассоциативный массив, который начинается с 0 элементов и расширяется по мере добавления большего количества символов. Например позволяет сказать, например, что C имел ассоциативные массивы (я хочу) с этим peusdocode:

symbol_array['q'] = 3; 
symbol_array['five'] = 5; 
symbol_array['negfive'] = -5; 
symbol_array['random294'] = 28; 

signed int i; 
string = get_from_input(); 
if(!(i = convert_to_int(string))) { 
    if(!(i = translate_from_symbol(string))) { 
     printf("Invalid symbol or integer\n"); 
     exit(1); 
    } 
} 

printf("Your number: %d\n, i); 

Идея в том, если они вошли в «5» было бы преобразовать его в 5 через convert_to_int, и если они вошли в «пять «он преобразует его в 5 через translate_from_symbol. Насколько мне кажется, может быть сложнее, если они войдут в «random294», это не будет конвертировать его в 294, а в 28. Если они войдут в «foo», тогда он выйдет (1).

Мои общие вопросы таковы: (Вместо того, чтобы сделать несколько сообщений)

При создании convert_to_int я знаю, что я не должен использовать atoi, потому что не будут обречены на провал. Некоторые люди говорят, что используют strtol, но кажется утомительным, чтобы преобразовать его в недолгий int. Упрощенным (читай: кратчайшим) способом я нашел это использование sscanf:

int i; 
if ((sscanf(string, "%d", &i)) == 1){ 
    return i; 
} 

Однако некоторые люди смотрят на это даже. Что такое лучший метод, если не sscanf или преобразование strtol?

Во-вторых, как я могу не только вернуть целое число, но и узнать, нашел ли он его. Например, если пользователь ввел «0», тогда он вернет 0, тем самым отключив мой FALSE в моей инструкции if. Я рассмотрел использование -1, если не найден, но поскольку я возвращаю подписанные int, тогда это также страдает от той же проблемы. В PHP я знаю, например, с strpos они используют === FALSE

Наконец, есть ли короткий код, который эмулирует ассоциированные массивы и/или позволяет мне нажимать элементы на массив во время выполнения?

ответ

1

Во-первых, вы можете пересмотреть свой синтаксис и установить ключевое слово отдельно от операнда, то есть "neg five" вместо "negfive". В противном случае ваш поиск символов для ключевых слов должен учитывать каждый префикс. ("random294" может быть хорошо, если ваши ключевые слова не могут иметь цифры в них.)

Конечно, sscanf говорит вам, нашли ли вы десятичную в возвращаемое значение и пишет, что десятичную в отдельную int, что приятно, но вам придется следить за завершающими символами, проверяя, что количество прочитанных символов равно длине вашей строки с форматом %n. В противном случае sscanf рассмотрит 5x как юридическое десятичное число. strtol также возвращает указатель на местоположение после разбора десятичного числа, но он слишком полагается на проверку err по моему вкусу.

Тот факт, что strtol использует длинные целые числа, не должен быть проблемой. Если вход не помещается в int, верните INT_MAX или INT_MIN или введите ошибку.

Вы также можете легко написать функцию обертки вокруг sscanf или strtol, которая лучше подходит для ваших нужд. (Я знаю, что мне нужна функция, которая возвращает true при успешном завершении и сохраняет целое число с помощью аргумента указателя sscanf, где успех означает: никаких конечных нецифровых символов.)

Наконец, об ассоциативных массивах: там не является коротким кодом, по крайней мере, не C. Вы должны будете реализовать свою собственную хэш-карту или использовать библиотеку. В качестве первого черновика я использовал бы линейный список строк и проверял их один за другим. Это очень наивный подход, но его легко реализовать. Я предполагаю, что вы не начинаете с большого количества символов, и вы не делаете много проверок, поэтому скорость не должна быть проблемой. (Вы можете отсортировать массив и использовать бинарный поиск, чтобы ускорить его, но вам придется повторно сортировать после каждой вставки.) Когда у вас есть логика вашей программы, вы можете начать думать о хэш-картах.

0

Что-то, как это должно делать свою работу:

#include <stdio.h> 
#include <string.h> 

struct StringToLongLookUp { 
    char *str; 
    char *num; 
}; 

struct StringToLongLookUp table[] = 
{ 
    { "q"  , "3" }, 
    { "five"  , "5" }, 
    { "negfive" , "-5" }, 
    { "random294", "28" } 
}; 


int translate_from_symbol(char **str) 
{ 
    int i; 
    for(i = 0; i < (sizeof(table)/sizeof(struct StringToLongLookUp)); i++) 
    { 
     if(strcmp(*str, table[i].str) == 0) 
     {     
      *str = table[i].num; 
      return 1; // TRUE 
     } 
    } 
    return 0; // FALSE 
} 

int main() 
{ 

    char buf[100]; 
    char *in = buf; 
    char *out; 
    int val; 

    scanf("%s", in); 

    translate_from_symbol(&in); 

    val = strtol(in, &out, 10); 

    if (in != out) 
    {    
     printf("\nValue = %d\n", val); 
    } 
    else 
    { 
     printf("\nValue Invalid\n"); 
    } 
} 

Конечно, вы получите длинный, но преобразования, что межд не должно быть проблемой, как упоминалось выше.

Смежные вопросы