আমি সিটিতে স্ট্রিংকে পূর্ণসংখ্যায় রূপান্তর করার বিকল্প উপায় আছে কিনা তা অনুসন্ধান করার চেষ্টা করছি
আমি নিয়মিতভাবে আমার কোডটিতে নীচে প্যাটার্ন করি।
char s[] = "45";
int num = atoi(s);
তাহলে, এর চেয়ে ভাল উপায় বা অন্য কোনও উপায় আছে?
আমি সিটিতে স্ট্রিংকে পূর্ণসংখ্যায় রূপান্তর করার বিকল্প উপায় আছে কিনা তা অনুসন্ধান করার চেষ্টা করছি
আমি নিয়মিতভাবে আমার কোডটিতে নীচে প্যাটার্ন করি।
char s[] = "45";
int num = atoi(s);
তাহলে, এর চেয়ে ভাল উপায় বা অন্য কোনও উপায় আছে?
উত্তর:
এখানে strtol
আরও ভাল আইএমও রয়েছে। এছাড়াও আমি পছন্দ করে নিয়েছি strtonum
, সুতরাং আপনার যদি এটি থাকে তবে এটি ব্যবহার করুন (তবে মনে রাখবেন এটি পোর্টেবল নয়):
long long
strtonum(const char *nptr, long long minval, long long maxval,
const char **errstr);
আপনার আগ্রহীও হতে পারে strtoumax
এবংstrtoimax
যা C99 এর মানক ফাংশনগুলি। উদাহরণস্বরূপ আপনি বলতে পারেন:
uintmax_t num = strtoumax(s, NULL, 10);
if (num == UINTMAX_MAX && errno == ERANGE)
/* Could not convert. */
যাইহোক, এ থেকে দূরে থাকুন atoi
:
কল atoi (স্ট্র) এর সমান হবে:
(int) strtol(str, (char **)NULL, 10)
ত্রুটিগুলি পরিচালনা করা পৃথক হতে পারে except মানটি উপস্থাপন করা না গেলে, আচরণটি সংজ্ঞায়িত ।
strtonum
? আমি একটি অন্তর্নিহিত ঘোষণার সতর্কতা পেয়ে
#<stdlib.h>
। তবে আপনি স্ট্যান্ডার্ড strtoumax
বিকল্পটি ব্যবহার করতে পারেন ।
দৃ Rob় সি 89 strtol
ভিত্তিক সমাধান
সঙ্গে:
atoi
পরিবারের সাথে যেমন করা যেতে পারে )strtol
(যেমন কোন নেতৃস্থানীয় হোয়াইটস্পেস কিংবা trailing ট্র্যাশ অক্ষর)#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;
}
str2int()
। পেডেন্টিক: ব্যবহার isspace((unsigned char) s[0])
।
(unsigned char)
কাস্ট একটি পার্থক্য করতে পারে?
l > INT_MAX
এবং l < INT_MIN
অর্থহীন পূর্ণসংখ্যার তুলনা হয় যেহেতু উভয় ফলাফল সর্বদা মিথ্যা। আমি যদি তাদের এ পরিবর্তন করি l >= INT_MAX
এবং l <= INT_MIN
সতর্কতাগুলি সাফ করি তবে কী হবে ? এআরএম সি তারিখে, দীর্ঘ এবং int- এ 32-বিট সাইন করে এআরএম সি এবং C ++ বেসিক ধরনের তথ্য
l >= INT_MAX
কার্যকারিতাটি ভুল কার্যকারিতাকে অন্তর্ভুক্ত করে: STR2INT_OVERFLOW
ইনপুট "32767"
এবং 16-বিট দিয়ে ফিরে আসা উদাহরণ int
। শর্তসাপেক্ষিত সংকলন ব্যবহার করুন। উদাহরণ ।
if (l > INT_MAX || (errno == ERANGE && l == LONG_MAX)) return STR2INT_OVERFLOW;
ভাল হবে যেমন if (l > INT_MAX || (errno == ERANGE && l == LONG_MAX)) { errno = ERANGE; return STR2INT_OVERFLOW;}
ব্যবহার করতে কোড কলিং করার অনুমতি errno
উপর int
আউট-অফ-পরিসীমা। একই জন্য if (l < INT_MIN...
।
ato...
গ্রুপ থেকে ফাংশন ব্যবহার করবেন না । এগুলি ভাঙ্গা এবং কার্যত অকেজো। একটি পরিমিতরূপে আরও ভাল সমাধান ব্যবহার করা হবে sscanf
, যদিও এটি নিখুঁত নয়।
স্ট্রিংটিকে পূর্ণসংখ্যায় রূপান্তর করতে, strto...
গ্রুপ থেকে ফাংশন ব্যবহার করা উচিত। আপনার নির্দিষ্ট ক্ষেত্রে এটি strtol
ফাংশন হবে।
sscanf
প্রকৃতপক্ষে অপরিবর্তিত আচরণ থাকলে যদি এটি কোনও সংখ্যাকে এর ধরণের সীমার বাইরে রূপান্তরিত করার চেষ্টা করে (উদাহরণস্বরূপ sscanf("999999999999999999999", "%d", &n)
)।
atoi
কোনও অর্থবহ সাফল্য / ব্যর্থতার প্রতিক্রিয়া সরবরাহ করে না এবং এটি ওভারফ্লোতে অপরিজ্ঞাত আচরণ করে। sscanf
বিভিন্ন ধরণের সাফল্য / ব্যর্থতার প্রতিক্রিয়া সরবরাহ করে (প্রত্যাবর্তনের মান, যা এটি "মাঝারিভাবে আরও ভাল" করে তোলে) তবে ওভারফ্লোতে এখনও অপরিবর্তিত আচরণ রয়েছে। কেবল strtol
একটি কার্যকর সমাধান।
sscanf
। (যদিও আমি স্বীকার করি যে আমি মাঝে মাঝে ব্যবহার করি atoi
, সাধারণত এমন প্রোগ্রামগুলির জন্য যা আমি উত্সটি মোছার আগে 10 মিনিটের বেশি বেঁচে থাকার আশা করি না))
আপনি মজা করার জন্য একটু আটই কোড করতে পারেন:
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);
}
আপনি এটিকে পুনরাবৃত্ত করতে পারেন যা 3 লাইনে পুরানো হতে পারে =)
code
((* code
"----1"
কোডটির অনুমতি দেয় 2) int
ফলাফলটি কখন হওয়া উচিত ওভারফ্লোর সাথে অপরিবর্তিত আচরণ INT_MIN
। বিবেচনা করুনmy_getnbr("-2147483648")
স্বাক্ষরযুক্ত দীর্ঘ সময়ের পাশাপাশি একটি সমাধান ভাগ করে নিতে চেয়েছিলেন।
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;
}
const char *
।
48
মানে কী? আপনি কি ধরে নিচ্ছেন যে '0'
কোডটি কোথায় চলবে তার মান ? দয়া করে বিশ্বকে এমন বিস্তৃত অনুমান দান করবেন না!
'0'
আপনার মতো ব্যবহার করুন ।
int atoi(const char* str){
int num = 0;
int i = 0;
bool isNegetive = false;
if(str[i] == '-'){
isNegetive = true;
i++;
}
while (str[i] && (str[i] >= '0' && str[i] <= '9')){
num = num * 10 + (str[i] - '0');
i++;
}
if(isNegetive) num = -1 * num;
return num;
}
আপনি সর্বদা নিজের রোল করতে পারেন!
#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;
}
এটি বিশৃঙ্খলা ছাড়াই যা করতে চান তা করবে।
strto...
ফাংশনগুলির পরিবারটি ব্যবহার না করার কোনও কারণ নেই । তারা বহনযোগ্য এবং উল্লেখযোগ্যভাবে ভাল।
0x2d, 0x30
পরিবর্তে ব্যবহার করার অদ্ভুত '-', '0'
। '+'
সাইন অনুমতি দেয় না । (int)
Castোকা কেন (int)strlen(snum)
? ইনপুট হলে ইউবি""
। ইউবি যখন ফলাফলINT_MIN
int
accum += (snum[strIdx] - 0x30) * pow(10, idx);
এই ফাংশন আপনাকে সাহায্য করবে
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);
}
রেফ: http://amscata.blogspot.com/2013/09/strnumstr-version-2.html
atoi
এবং বন্ধুদের সাথে সবচেয়ে বড় সমস্যা হ'ল যদি ওভারফ্লো হয় তবে এটি অনির্ধারিত আচরণ। আপনার ফাংশন এটি পরীক্ষা করে না। strtol
এবং বন্ধুরা করতে।
ঠিক আছে, আমারও একই সমস্যা ছিল I আমি এই সমাধানটি নিয়ে এসেছি t এটি আমার পক্ষে সবচেয়ে ভাল কাজ করেছে at
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;
}
nInt = (nInt *= 10) + ((int) snum[index] - 48);
বনামের nInt = nInt*10 + snum[index] - '0';
if(!nInt)
প্রয়োজন নেই।
সি ++ এ আপনি এই জাতীয় ফাংশন ব্যবহার করতে পারেন:
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;
}
এটি আপনাকে যে কোনও স্ট্রিংকে যে কোনও ধরণের যেমন ফ্লোট, ইনট, ডাবল ... তে রূপান্তর করতে সহায়তা করতে পারে
হ্যাঁ, আপনি সরাসরি পূর্ণসংখ্যা সঞ্চয় করতে পারেন:
int num = 45;
যদি আপনাকে অবশ্যই একটি স্ট্রিং বিশ্লেষণ করতে পারে, atoi
বা strol
"সংক্ষিপ্ত পরিমাণের কোড" প্রতিযোগিতা জিততে চলেছে।
strtol()
আসলে একটি মোটামুটি কোড দরকার। এটা তোলে আসতে পারেন LONG_MIN
বা LONG_MAX
পারেন যে যদি প্রকৃত রূপান্তরিত মান অথবা একটি underflow বা ওভারফ্লো, এবং এটা হয় 0 আসতে পারেন যে যদি প্রকৃত মূল্য বা যদি রূপান্তর করতে কোন সংখ্যা ছিল পারেন। আপনাকে errno = 0
কল করার আগে সেট করতে হবে এবং চেক করতে হবে endptr
।