Saya mencoba untuk mencari tahu apakah ada alternatif cara untuk mengkonversi string ke integer dalam C.
Saya secara teratur pola berikut dalam kode saya.
char s[] = "45";
int num = atoi(s);
Jadi, apakah ada cara yang lebih baik atau cara lain?
Ada strtol
yang lebih baik IMO. Juga saya telah mengambil keinginan di strtonum
, jadi gunakan ini jika anda memiliki itu (tapi ingat itu's tidak portable):
long long
strtonum(const char *nptr, long long minval, long long maxval,
const char **errstr);
Anda juga mungkin tertarik dalam strtoumax
dan strtoimax
yang merupakan fungsi standar di C99. Misalnya anda bisa mengatakan:
uintmax_t num = strtoumax(s, NULL, 10);
if (num == UINTMAX_MAX && errno == ERANGE)
/* Could not convert. */
Pokoknya, tinggal jauh dari atoi
:
panggilan atoi(str) harus setara dengan:
(int) strtol(str, (char **)NULL, 10)
kecuali bahwa penanganan kesalahan yang mungkin berbeda. Jika nilai tidak dapat diwakili, perilaku yang tidak terdefinisi.
Don't menggunakan fungsi dari ato...
kelompok. Ini yang rusak dan hampir tidak berguna. Cukup solusi yang lebih baik akan menggunakan sscanf
, meskipun tidak sempurna.
Untuk mengkonversi string ke integer, fungsi dari strto...
kelompok harus digunakan. Dalam kasus tertentu anda akan strtol
fungsi.
Kuat C89 strtol
berbasis solusi
Dengan:
atoi
keluarga)strtol
(misalnya tidak ada ruang kosong atau trailing sampah karakter)#include <assert.h>
#include <ctype.h>
#include <errno.h>
#include <limits.h>
#include <stdio.h>
#include <stdlib.h>
typedef enum {
STR2INT_SUCCESS,
STR2INT_OVERFLOW,
STR2INT_UNDERFLOW,
STR2INT_INCONVERTIBLE
} str2int_errno;
/* Convert string s to int out.
*
* @param[out] out The converted int. Cannot be NULL.
*
* @param[in] s Input string to be converted.
*
* The format is the same as strtol,
* except that the following are inconvertible:
*
* - empty string
* - leading whitespace
* - any trailing characters that are not part of the number
*
* Cannot be NULL.
*
* @param[in] base Base to interpret string in. Same range as strtol (2 to 36).
*
* @return Indicates if the operation succeeded, or why it failed.
*/
str2int_errno str2int(int *out, char *s, int base) {
char *end;
if (s[0] == '\0' || isspace(s[0]))
return STR2INT_INCONVERTIBLE;
errno = 0;
long l = strtol(s, &end, base);
/* Both checks are needed because INT_MAX == LONG_MAX is possible. */
if (l > INT_MAX || (errno == ERANGE && l == LONG_MAX))
return STR2INT_OVERFLOW;
if (l < INT_MIN || (errno == ERANGE && l == LONG_MIN))
return STR2INT_UNDERFLOW;
if (*end != '\0')
return STR2INT_INCONVERTIBLE;
*out = l;
return STR2INT_SUCCESS;
}
int main(void) {
int i;
/* Lazy to calculate this size properly. */
char s[256];
/* Simple case. */
assert(str2int(&i, "11", 10) == STR2INT_SUCCESS);
assert(i == 11);
/* Negative number . */
assert(str2int(&i, "-11", 10) == STR2INT_SUCCESS);
assert(i == -11);
/* Different base. */
assert(str2int(&i, "11", 16) == STR2INT_SUCCESS);
assert(i == 17);
/* 0 */
assert(str2int(&i, "0", 10) == STR2INT_SUCCESS);
assert(i == 0);
/* INT_MAX. */
sprintf(s, "%d", INT_MAX);
assert(str2int(&i, s, 10) == STR2INT_SUCCESS);
assert(i == INT_MAX);
/* INT_MIN. */
sprintf(s, "%d", INT_MIN);
assert(str2int(&i, s, 10) == STR2INT_SUCCESS);
assert(i == INT_MIN);
/* Leading and trailing space. */
assert(str2int(&i, " 1", 10) == STR2INT_INCONVERTIBLE);
assert(str2int(&i, "1 ", 10) == STR2INT_INCONVERTIBLE);
/* Trash characters. */
assert(str2int(&i, "a10", 10) == STR2INT_INCONVERTIBLE);
assert(str2int(&i, "10a", 10) == STR2INT_INCONVERTIBLE);
/* int overflow.
*
* `if` needed to avoid undefined behaviour
* on `INT_MAX + 1` if INT_MAX == LONG_MAX.
*/
if (INT_MAX < LONG_MAX) {
sprintf(s, "%ld", (long int)INT_MAX + 1L);
assert(str2int(&i, s, 10) == STR2INT_OVERFLOW);
}
/* int underflow */
if (LONG_MIN < INT_MIN) {
sprintf(s, "%ld", (long int)INT_MIN - 1L);
assert(str2int(&i, s, 10) == STR2INT_UNDERFLOW);
}
/* long overflow */
sprintf(s, "%ld0", LONG_MAX);
assert(str2int(&i, s, 10) == STR2INT_OVERFLOW);
/* long underflow */
sprintf(s, "%ld0", LONG_MIN);
assert(str2int(&i, s, 10) == STR2INT_UNDERFLOW);
return EXIT_SUCCESS;
}
Berdasarkan pada: https://stackoverflow.com/a/6154614/895245
Anda dapat kode sedikit atoi() untuk memulai:
int my_getnbr(char *str)
{
int result;
int puiss;
result = 0;
puiss = 1;
while (('-' == (*str)) || ((*str) == '+'))
{
if (*str == '-')
puiss = puiss * -1;
str++;
}
while ((*str >= '0') && (*str <= '9'))
{
result = (result * 10) + ((*str) - '0');
str++;
}
return (result * puiss);
}
Anda juga dapat membuatnya rekursif yang bisa tua di 3 baris =)
Hanya ingin berbagi solusi untuk unsigned long juga.
unsigned long ToUInt(char* str)
{
unsigned long mult = 1;
unsigned long re = 0;
int len = strlen(str);
for(int i = len -1 ; i >= 0 ; i--)
{
re = re + ((int)str[i] -48)*mult;
mult = mult*10;
}
return re;
}
Anda selalu dapat memutar anda sendiri!
#include <stdio.h>
#include <string.h>
#include <math.h>
int my_atoi(const char* snum)
{
int idx, strIdx = 0, accum = 0, numIsNeg = 0;
const unsigned int NUMLEN = (int)strlen(snum);
/* Check if negative number and flag it. */
if(snum[0] == 0x2d)
numIsNeg = 1;
for(idx = NUMLEN - 1; idx >= 0; idx--)
{
/* Only process numbers from 0 through 9. */
if(snum[strIdx] >= 0x30 && snum[strIdx] <= 0x39)
accum += (snum[strIdx] - 0x30) * pow(10, idx);
strIdx++;
}
/* Check flag to see if originally passed -ve number and convert result if so. */
if(!numIsNeg)
return accum;
else
return accum * -1;
}
int main()
{
/* Tests... */
printf("Returned number is: %d\n", my_atoi("34574"));
printf("Returned number is: %d\n", my_atoi("-23"));
return 0;
}
Ini akan melakukan apa yang anda inginkan tanpa kekacauan.
Fungsi ini akan membantu anda
int strtoint_n(char* str, int n)
{
int sign = 1;
int place = 1;
int ret = 0;
int i;
for (i = n-1; i >= 0; i--, place *= 10)
{
int c = str[i];
switch (c)
{
case '-':
if (i == 0) sign = -1;
else return -1;
break;
default:
if (c >= '0' && c <= '9') ret += (c - '0') * place;
else return -1;
}
}
return sign * ret;
}
int strtoint(char* str)
{
char* temp = str;
int n = 0;
while (*temp != '\0')
{
n++;
temp++;
}
return strtoint_n(str, n);
}
Ref: http://amscata.blogspot.com/2013/09/strnumstr-version-2.html
Ok, saya punya masalah yang sama.Saya datang dengan solusi ini.Ini bekerja untuk saya yang terbaik.Aku mencoba atoi() tetapi tidak't bekerja dengan baik bagi saya.Jadi di sini adalah solusi saya:
void splitInput(int arr[], int sizeArr, char num[])
{
for(int i = 0; i < sizeArr; i++)
// We are subtracting 48 because the numbers in ASCII starts at 48.
arr[i] = (int)num[i] - 48;
}
//I think this way we could go :
int my_atoi(const char* snum)
{
int nInt(0);
int index(0);
while(snum[index])
{
if(!nInt)
nInt= ( (int) snum[index]) - 48;
else
{
nInt = (nInt *= 10) + ((int) snum[index] - 48);
}
index++;
}
return(nInt);
}
int main()
{
printf("Returned number is: %d\n", my_atoi("676987"));
return 0;
}
Dalam C++, anda dapat menggunakan fungsi seperti:
template <typename T>
T to(const std::string & s)
{
std::istringstream stm(s);
T result;
stm >> result;
if(stm.tellg() != s.size())
throw error;
return result;
}
Hal ini dapat membantu anda untuk mengkonversi string ke tipe seperti float, int, double...