繁体   English   中英

Atoi() 和 strtol() 在 C 中无法正常工作

[英]Atoi() and strtol() not working correctly in C

基本上我想检查我写的时间是否有效我输入了这个字符串:20:40: 20:40:30 ,结果是: No

当我调试问题时,发现atoi无法正常工作。

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

int main() {
    char Input[20] = { '\0' };
    scanf("%s", &Input);

    char sub1[2] = { '\0' };
    char sub2[2] = { '\0' };
    char sub3[2] = { '\0' };

    strncpy(sub1, Input, 2);
    strncpy(sub2, Input + 3, 2);
    strncpy(sub3, Input + 6, 2);

    int H = atoi(sub1);
    int M = atoi(sub2);
    int S = atoi(sub3);

    int count = 0;
    if (H >= 0 && H < 24) count++;
    if (M >= 0 && M < 60) count++;
    if (S >= 0 && S < 60) count++;

    if (count == 3)
        printf("Yes);
    else
        printf("No");

    return 0;
}

我也尝试了strtol ,但仍然是同样的问题。

您的代码中有多个问题:

  • 您将字符串片段复制到其中的 arrays 不够长,无法容纳 2 个字符和一个 null 终止符。
  • 如果源字符串的字符数至少与 size 参数指定的一样多,则strncpy()不会在目标中设置 nul 终止符。 使目标 arrays 更长并将其初始化为0就足以解决这里的问题,但语义strncpy()令人困惑且容易出错,因此最好避免使用 function。
  • 您无需验证字符串的实际内容: "1x+ 2=3b""abcdefgh"一样被认为是正确的,因为您只检查从偏移量 0、3 和 6 开始的数字是否在适当的范围内。

这是一个更有效的验证:

#include <stdio.h>
#include <stdlib.h>

int main() {
    char Input[20], sub1[3], sub2[3], sub3[3];
    int pos;
    char c;

    /* read a string of at most 19 characters */
    if (scanf("%19s", Input) != 1) {
        printf("No: input error\n");
        return 1;
    }
    /* extract 3 fields of at most 2 digits separated by ':'
     * verify that all characters have been consumed
     * verify that 8 characters have been consumed 
     */
    if (sscanf(Input, "%2[0-9]:%2[0-9]:%2[0-9]%n%c", sub1, sub2, sub3, &pos, &c) != 3 || pos != 8) {
        printf("No: format error\n");
        return 1;
    }
    int H = atoi(sub1);
    int M = atoi(sub2);
    int S = atoi(sub3);

    /* no need to test for negative values since we already verified
     *  that the fields have 2 digits
     */
    if (H < 24 && M < 60 && S < 60)
        printf("Yes\n");
    else
        printf("No: values out of range\n");

    return 0;
}

当达到最大字符数时, strncpy()不会放置最后'\0'
您必须手动放置它,并确保有足够的存储空间
(当然,如果结果缓冲区已经用零填充,则不必显式放置它,但在一般情况下,您必须确保)

在您的尝试中, atoi()会在您复制的两个字符之后找到任何内容 这是一个缓冲区溢出,这个字符序列可能看起来不像 integer。

/**
  gcc -std=c99 -o prog_c prog_c.c \
      -pedantic -Wall -Wextra -Wconversion \
      -Wc++-compat -Wwrite-strings -Wold-style-definition -Wvla \
      -g -O0 -UNDEBUG -fsanitize=address,undefined
**/

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

int main(void)
{
     char Input[20]={'\0'};
     scanf("%s",Input);


     char sub1[3]={'\0'}; // 2 --> 3 for the final '\0'
     char sub2[3]={'\0'}; // note that since these arrays are partially
     char sub3[3]={'\0'}; // initialised, they contain some zeros in the
                          // remaining locations.


     strncpy(sub1,Input,2);
     sub1[2]='\0'; // useless here since sub1 is filled with zeros
     strncpy(sub2,Input+3,2);
     sub2[2]='\0'; // useless here since sub2 is filled with zeros
     strncpy(sub3,Input+6,2);
     sub3[2]='\0'; // useless here since sub3 is filled with zeros


     int H=atoi(sub1);
     int M=atoi(sub2);
     int S=atoi(sub3);

     int count=0;
     if (H>=0 && H<24)count++;
     if (M>=0 && M<60)count++;
     if (S>=0 && S<60)count++;

    if (count==3)printf("Yes\n");
    else printf("No\n");


return 0;
}

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM