编写一个程序,将一个字符串转换为整数,而不使用标准的C库函数。

huangapple go评论63阅读模式
英文:

Write a program that converts a string to an integer without using standard C library functions

问题

#include <assert.h>
#include <stddef.h>
#include <string.h>

int StringToInteger(const char *str) {
    int num = 0;
    int sign = 1;
    assert(str != NULL); // 确保str不为NULL
    if (*str == '+' || *str == '-') {
        sign = (*str == '-') ? -1 : 1;
        str++;
        return sign; // 如果以字符开头
    }
    
    while (*str != '
#include <assert.h>
#include <stddef.h>
#include <string.h>

int StringToInteger(const char *str) {
    int num = 0;
    int sign = 1;
    assert(str != NULL); // 确保str不为NULL
    if (*str == '+' || *str == '-') {
        sign = (*str == '-') ? -1 : 1;
        str++;
        return sign; // 如果以字符开头
    }
    
    while (*str != '\0') { 
        if (*str >= '0' && *str <= '9') {
            num = num * 10 + (*str - '0');
        } else {
            return 0;
        }
        str++;
    }
    return 0;
}
'
) {
if (*str >= '0' && *str <= '9') { num = num * 10 + (*str - '0'); } else { return 0; } str++; } return 0; }

这是给定的代码的中文翻译,代码部分未翻译。

英文:
#include &lt;assert.h&gt;
#include &lt;stddef.h&gt;
#include &lt;string.h&gt;

int StringToInteger(const char *str) {
    int num = 0;
    int sign = 1;
    assert(str != NULL); //assert that str different from NULL
    if (*str == &#39;+&#39; || *str == &#39;-&#39;) {
        sign = (*str == &#39;-&#39;) ? -1 : 1;
        str++;
        return sign; // if sign start with character
    }
    
    while (*str != &#39;
#include &lt;assert.h&gt;
#include &lt;stddef.h&gt;
#include &lt;string.h&gt;
int StringToInteger(const char *str) {
int num = 0;
int sign = 1;
assert(str != NULL); //assert that str different from NULL
if (*str == &#39;+&#39; || *str == &#39;-&#39;) {
sign = (*str == &#39;-&#39;) ? -1 : 1;
str++;
return sign; // if sign start with character
}
while (*str != &#39;\0&#39;) { 
if (*str &gt;= &#39;0&#39; &amp;&amp; *str &lt;= &#39;9&#39;) {
num = num * 10 + (*str - &#39;0&#39;);
} else {
return 0;
}
str++;
}
return 0;
}
&#39;) { if (*str &gt;= &#39;0&#39; &amp;&amp; *str &lt;= &#39;9&#39;) { num = num * 10 + (*str - &#39;0&#39;); } else { return 0; } str++; } return 0; }

I tried to write a different version of the code without using the regular conversion functions but with no success.

答案1

得分: 2

以下是翻译的内容:

问题:

不要总是返回0 @tkausl

找到 sign 后没有返回的理由 @Barmar

删除那一行,然后在代码后面根据 sign 调整 num
提示:也要运行拼写检查器。

      // return sign; // 如果符号以字符开始

    // 代码结束
    return num * sign; // 包括这一行
    // return 0;

高级:避免 int 溢出

  • 处理 INT_MIN 文本,如 StringToInteger(&quot;-2147483648&quot;)

  • 在发生溢出之前检测潜在的溢出。这可以防止“未定义行为”(UB)。

#include &lt;assert.h&gt;
#include &lt;errno.h&gt;
#include &lt;limits.h&gt;
#include &lt;stddef.h&gt;

int StringToInteger(const char* str) {
  assert(str != NULL);

  // 如果需要,可以编写代码来忽略前导空格。

  int sign = *str;
  if (*str == &#39;+&#39; || *str == &#39;-&#39;) {
    str++;
  }

  const char *first = s;
  int num = 0;
  while (*str &gt;= &#39;0&#39; &amp;&amp; *str &lt;= &#39;9&#39;) { 
    int digit = *str - &#39;0&#39;
    if (num &lt;= INT_MIN/10 &amp;&amp; (num &lt; INT_MIN/10 || digit &gt; -(INT_MIN%10))) {
      errno = ERANGE;
      num = INT_MIN;
    } else {
      // 作为负值相加,因为负范围大于正范围。
      num = num * 10 - digit;
    }
    str++;
  }
  if (*str) {
    ; // 可能想要设置 errno。
    return 0; // 非空字符停止循环。
  }
  if (s == first) {
    ; // 可能想要设置 errno。
    return 0; // 没有数字。
  }

  if (sign != &#39;-&#39;) {
    if (num &lt; -INT_MAX) {
      num = INT_MAX;
      errno = ERANGE;
    } else {
      num = -num;
    }
  }

  return num;
}

希望这对你有帮助!

英文:

Problems:

Do not always return 0 @tkausl

No reason to return after finding a sign @Barmar

Delete that line and later in code adjust num per sign.
Tip: also run spell checker.

      // return sign; // if sign start with charcter
// End of code
return num * sign; // Include this line
// return 0;

Advanced: avoid int overflow

  • Handle the INT_MIN text like StringToInteger(&quot;-2147483648&quot;)

  • Detect potential overflow before it happens. This prevents undefined behavior (UB).

#include &lt;assert.h&gt;
#include &lt;errno.h&gt;
#include &lt;limits.h&gt;
#include &lt;stddef.h&gt;
int StringToInteger(const char* str) {
assert(str != NULL);
// TBD code if desired to ignore leading white-spaces. 
int sign = *str;
if (*str == &#39;+&#39; || *str == &#39;-&#39;) {
str++;
}
const char *first = s;
int num = 0;
while (*str &gt;= &#39;0&#39; &amp;&amp; *str &lt;= &#39;9&#39;) { 
int digit = *str - &#39;0&#39;;
if (num &lt;= INT_MIN/10 &amp;&amp; (num &lt; INT_MIN/10 || digit &gt; -(INT_MIN%10))) {
errno = ERANGE;
num = INT_MIN;
} else {
// Sum as a negative value as the - range is more than + range.
num = num * 10 - digit;
}
str++;
}
if (*str) {
; // May want to set errno.
return 0; // Non-null character stopped loop.
}
if (s == first) {
; // May want to set errno.
return 0; // No digits.
}
if (sign != &#39;-&#39;) {
if (num &lt; -INT_MAX) {
num = INT_MAX;
errno = ERANGE;
} else {
num = -num;
}
}
return num;
}

答案2

得分: 1

函数中有很多不合理的返回语句,例如:

return sign; // 如果sign以字符开头

而且你的函数要么返回sign,要么返回0。事实上,它没有考虑字符串中存储值的符号。

还要考虑到字符串可以包含前导或尾随的空白字符。

你可以实现该函数与标准C函数strtol相同的方式。一个简化的函数可以忽略存储的数字太大以适应类型int对象的情况。

以下是演示程序,展示了如何实现该函数:

#include <ctype.h>
#include <stdio.h>

int StringToInteger(const char *str)
{
    const int Base = 10;

    int sign = 0;

    while (isspace((unsigned char)*str))
        ++str;

    if (*str == '-' || *str == '+')
    {
        if (*str == '-') sign = 1;
        ++str;
    }

    int value = 0;

    for (unsigned char c = *str; isdigit(c); c = *++str)
    {
        int digit = c - '0';
        value = Base * value + (sign ? -digit : digit);
    }

    while (isspace((unsigned char)*str))
        ++str;

    return *str == '\0' ? value : 0;
}

int main(void)
{
    const char *str = " -12345\t";

    printf("\"%s\" = %d\n", str, StringToInteger(str));

    str = " 12345\t";

    printf("\"%s\" = %d\n", str, StringToInteger(str));

    str = " 12345\tA";

    printf("\"%s\" = %d\n", str, StringToInteger(str));

    str = " @12345\t";

    printf("\"%s\" = %d\n", str, StringToInteger(str));

    str = " 123@45\t";

    printf("\"%s\" = %d\n", str, StringToInteger(str));
}

程序输出如下:

"-12345        " = -12345
" 12345 " = 12345
" 12345 A" = 0
" @12345        " = 0
" 123@45        " = 0
英文:

The function has many return statements that do not make sense as for example

return sign; // if sign start with charcter

And your function returns either sign or 0. In fact it does not take into account the sign of the stored value in the string.

Also take into account that the string can contain leading or trailing white space characters.

You could implement the function the same way.as standard C function strtol. A simplified function can ignore the case when the stored number is too big to fit in an object of the type int.

Here is a demonstration program that shows how the function can be implemented.

#include &lt;ctype.h&gt;
#include &lt;stdio.h&gt;
int StringToInteger( const char *str )
{
const int Base = 10;
int sign = 0;
while (isspace( ( unsigned char )*str )) ++str;
if (*str == &#39;-&#39; || *str == &#39;+&#39;)
{
if (*str == &#39;-&#39;) sign = 1;
++str;
}
int value = 0;
for (unsigned char c = *str;  isdigit( c ); c = *++str )
{
int digit = c - &#39;0&#39;;
value = Base * value + ( sign ? -digit : digit );
}
while (isspace( ( unsigned char )*str )) ++str;
return *str == &#39;\0&#39; ? value : 0;
}
int main( void )
{
const char *str = &quot; -12345\t&quot;;
printf( &quot;\&quot;%s\&quot; = %d\n&quot;, str, StringToInteger( str ) );
str = &quot; 12345\t&quot;;
printf( &quot;\&quot;%s\&quot; = %d\n&quot;, str, StringToInteger( str ) );
str = &quot; 12345\tA&quot;;
printf( &quot;\&quot;%s\&quot; = %d\n&quot;, str, StringToInteger( str ) );
str = &quot; @12345\t&quot;;
printf( &quot;\&quot;%s\&quot; = %d\n&quot;, str, StringToInteger( str ) );
str = &quot; 123@45\t&quot;;
printf( &quot;\&quot;%s\&quot; = %d\n&quot;, str, StringToInteger( str ) );
}

The program output is

&quot; -12345        &quot; = -12345
&quot; 12345 &quot; = 12345
&quot; 12345 A&quot; = 0
&quot; @12345        &quot; = 0
&quot; 123@45        &quot; = 0

答案3

得分: 0

以下是您要翻译的代码部分:

// 将字符串转换为整数(任何进制,如果有足够的数字/字母/符号来表示该进制中的数字)。

int myisspace(int c)
{
    switch(c)
    {
        case ' ':
        case '\t':
        case '\r':
        case '\n':
        return 1;
    }
    return 0;
}

char *mystrchr(const char *str, const char ch)
{
    while(*str)
    {
        if(*str == ch) return str;
        str++;
    }
    return NULL;
}

int long long cnv(const char *str, unsigned base)
{
    const char digits[] = "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ";
    int sign = 1;
    int long long result = 0;

    if(str && (base >= 2 && base < sizeof(digits)))
    {
        while(myisspace(*str)) str++;
        if(*str == '-' || *str == '+') { sign = *str == '-' ? -1 : 1; str++;}
    }
    while(*str)
    {
        //you may check for overflow as well
        //TODO integer overflow code if needed
        char *rch = mystrchr(digits, *str);
        if(!rch || (rch - digits) >= base)
        {
            if(!myisspace(*str))
            {
                result = 0;
                break;
            }
            else
            {
                *str++;
                continue;
            }
        }
        result *= base;
        result += rch - digits;
        str++;
    }
    return result * sign;
}

int main(void)
{
    printf("%lld\n", cnv("934", 10));
    printf("%lld\n", cnv("934", 12));
    printf("%lld\n", cnv("ffff", 16));
    printf("%lld\n", cnv("01100110011", 2));
    printf("%lld\n", cnv("      -01100110011", 2));
    printf("%lld\n", cnv("      -42313442323", 5));
    printf("%lld\n", cnv("      -42313442323      ", 12));
}

希望这对您有所帮助。如果您有任何其他问题,请随时提出。

英文:

Function converting string to integer (any base if you have enough digits/letters/symbols) to represent digits in this base.

int myisspace(int c)
{
switch(c)
{
case &#39; &#39;:
case &#39;\t&#39;:
case &#39;\r&#39;:
case &#39;\n&#39;:
return 1;
}
return 0;
}
char *mystrchr(const char *str, const char ch)
{
while(*str)
{
if(*str == ch) return str;
str++;
}
return NULL;
}
int long long cnv(const char *str, unsigned base)
{
const char digits[] = &quot;0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ&quot;;
int sign = 1;
int long long result = 0;
if(str &amp;&amp; (base &gt;=2 &amp;&amp; base &lt; sizeof(digits)))
{
while(myisspace(*str)) str++;
if(*str == &#39;-&#39; || *str == &#39;+&#39;) { sign = *str == &#39;-&#39; ? -1 : 1; str++;}
}
while(*str)
{
//you may check for overflow as well
//TODO integer overflow code if needed
char *rch = mystrchr(digits, *str);
if(!rch || (rch - digits) &gt;= base)
{
if(!myisspace(*str))
{
result = 0;
break;
}
else
{
*str++;
continue;
}
}
result *= base;
result += rch - digits;
str++;
}
return result * sign;
}
int main(void)
{
printf(&quot;%lld\n&quot;, cnv(&quot;934&quot;, 10));
printf(&quot;%lld\n&quot;, cnv(&quot;934&quot;, 12));
printf(&quot;%lld\n&quot;, cnv(&quot;ffff&quot;, 16));
printf(&quot;%lld\n&quot;, cnv(&quot;01100110011&quot;, 2));
printf(&quot;%lld\n&quot;, cnv(&quot;      -01100110011&quot;, 2));
printf(&quot;%lld\n&quot;, cnv(&quot;      -42313442323&quot;, 5));
printf(&quot;%lld\n&quot;, cnv(&quot;      -42313442323      &quot;, 12));
}

huangapple
  • 本文由 发表于 2023年2月14日 00:53:06
  • 转载请务必保留本文链接:https://go.coder-hub.com/75438918.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定