Come convertire string in unsigned long in C ++?

Ho bisogno di aiuto nella programmazione. Il programma deve accettare una stringa che alla fine verrà convertita in unsigned long. Ma ecco il trucco, ci deve essere un catcher di errori che quando si inserisce una combinazione di hex e simboli come a!!!!!! genererà un errore e la variabile lunga non firmata deve essere in grado di accettare e memorizzare l’input maggiore di 4294967295 che è FFFFFFFF . Ho provato questo segmento di codice:

 char buffer[256]; unsigned long holder; fgets(buffer,256,stdin); holder = strtoul (buffer,NULL,16); 

Il mio problema è che quando inserisco FFFFFFFFF (9 F’s) invece di FFFFFFFF (8 F’s), il titolare STILL accetterà comunque 4294967295 anche se è più del. Un’altra cosa è che quando combino sia hex che simboli come a!!!!! , i fgets considerano ancora l’esagono A.

Puoi per favore darmi un’idea su come fare questo? Se conosci altre idee oltre a questo codice, faccelo sapere. Grazie!

Se si utilizzano le “vecchie stringhe di tipo C”, è ansible aggiungere ulteriori controlli per verificare che “tutti i caratteri siano stati acquisiti” passando un char * alla chiamata strtoul .

In altre parole:

  char *end_ptr = NULL; .... errno = 0; holder = strtoul(buffer, &end_ptr, 16); 

end_ptr punterà al carattere uno oltre l’input accettato, quindi se inserisci “a !!!!!”, indicherà un ‘!’.

  if (end_ptr != '\0') // Should point at "end of string marker". { ... do something to indicate error. } 

Per rilevare l’overflow, dovrai fare affidamento su errno :

 if (errno != 0) { ... deal with errors here . } 

Ovviamente, puoi fare:

 if (errno != 0 || *end_ptr != '\0') { .... deal with errors. } 

L’uso della funzione std:stoul() C ++ std:stoul() un’eccezione, quindi qualcosa come:

prova {holder = std :: stoul (buffer); } catch (…) {… gestisce l’errore …}

sarebbe la soluzione in stile C ++.

Quindi se guardi questo documento per strtoul lo vedrai nella sezione Return Value :

Se il valore convertito non rientra nell’intervallo del tipo di ritorno corrispondente, si verifica un errore di intervallo e vengono restituiti ULONG_MAX o ULLONG_MAX.

Quindi per il controllo fuori intervallo è necessario un codice simile a questo:

 if ( ( holder == ULONG_MAX || holder == ULLONG_MAX ) && errno == ERANGE) 

Per l’ a!!!! caso guardando indietro allo stesso documento, vedrai:

Le funzioni impostano il puntatore puntato da str_end per puntare al carattere oltre l’ultimo carattere interpretato. Se str_end è NULL, viene ignorato.

stai passando attualmente in NULL ma se passi un argomento:

 char *p; holder = strtoul (buffer,&p,16); 

ora puoi verificare se *p è un terminatore NULL e se è così hai elaborato tutti i caratteri altrimenti sai che hai avuto un problema.

Hai anche la possibilità di usare stoul che lancia le seguenti eccezioni std::invalid_argument se non è ansible eseguire alcuna conversione e std::out_of_range se il valore convertito cade fuori dall’intervallo del tipo di risultato.

Ad esempio potresti fare come segue:

 std::string str1(n) ; size_t pos ; try { holder = std::stoul( str1, &pos, 16 ) ; } catch( std::invalid_argument e ) { std::cout << "Invalid argument" << std::endl ; } catch ( std::out_of_range e ) { std::cout << "Out of range" << std::endl ; } 

pos sarà l'indice dell'ultimo carattere elaborato, nel tuo caso se pos != str1.length() non potrebbe elaborare l'intera stringa e avrai un problema.

Come hanno detto altri poster, usa lo stoul se lo hai.

Se non lo fai, potresti essere in grado di fare qualcosa del tipo:

 std::istringstream strm( buffer ); unsigned long holder = 1; strm >> std::hex >> holder; if( strm.fail() ) // out-of-range if( ! strm.eof() ) // didn't read all available characters - catches "A!!!"