C将char数组转换成int表现得很奇怪

时间:2016-04-27 12:15:57

标签: c arrays string integer

我有一个更长的char数组,我正在变成整数,但我无法弄清楚为什么它在某些地方表现得很奇怪。

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

int main () 
{
    char x[60] = "08 02 22 97 38 15 00 40 00 75 04 05 07 78 52 12 50 77 91 08";
    printf("%lu\n\n", strlen(x));

    for ( int i = 0; i < strlen(x); i+=3 ) {
        char num[2];
        num[0] = (char)x[i];
        num[1] = (char)x[i+1];
        printf("%d, ", atoi(num));
    }

}

输出:

8, 2, 22, 97, 38, 15, 0, 40, 0, 75, 4, 5, 7, 78, 52, 12, 500, 773, 916, 89, 

一切都很棒,直到..... 500,773,916,89 ......发生了什么事?

5 个答案:

答案 0 :(得分:12)

正如您所看到的,atoi需要一个C-String:一个空终止的字符数组。

所以,这个

    char num[2];
    num[0] = (char)x[i];
    num[1] = (char)x[i+1];

必须

    char num[3] = {0};
    num[0] = (char)x[i];
    num[1] = (char)x[i+1];        
    num[2] = '\0'; // this could be avoided in your specific case

答案 1 :(得分:1)

许多人已经发布了对具有空字符的正确字符串的需求。

只是想添加另一种编码理念:复合文字。 (char[]) { x[i], x[i + 1], '\0' }实现这一目标。

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

int main(void) {
  char x[] = "08 02 22 97 38 15 00 40 00 75 04 05 07 78 52 12 50 77 91 08";
  size_t len = strlen(x);
  printf("%zu\n\n", len);

  for (size_t i = 0; i < len; i += 3) {
    printf("%d, ", atoi((char[] ) { x[i], x[i + 1], '\0' }));
  }
}

输出

59

8, 2, 22, 97, 38, 15, 0, 40, 0, 75, 4, 5, 7, 78, 52, 12, 50, 77, 91, 8, 

其他一些修正也是如此。

答案 2 :(得分:0)

 num[0] = (char)x[i];
 num[1] = (char)x[i+1];
 printf("%d, ", atoi(num)

这假定输入中的位数始终为2(其中num应声明为char num [3]。使用较小的输入集进行逻辑的干运行,例如:{{1 }}

"01 50"

尝试使用sscanf来解析输入而不是依赖于位数。这将更加清洁,不容易出错。

i=0
num[0] = *(num+0) = 0 
num[1] = *(num+1) = <space> 
num[2] = *(num + 2) = ????? Since this memory is not allocated for num
printf("%d, ", atoi("1<space>")) = 1 (atoi stops after looking at num[1] which is a non-digit character)

i = 3
num[0] = *(num+0) = 0 
num[1] = *(num + 1) =  0
num[2] = *(num + 2) = ?????
printf("%d ", atoi("00<garbage>...")) // this is UB since atoi will definitely read memory at  `(num + 2)` which is beyond the bounds of what the compiler allocated for it.

答案 3 :(得分:0)

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

int main () 
{
    char num[3]; // 3rd byte is the null character
    num[3]='\0';
    char x[60] = "08 02 22 97 38 15 00 40 00 75 04 05 07 78 52 12 50 77 91 08";
    printf("%lu\n\n", strlen(x));

    for ( int i = 0; i < strlen(x); i+=3 ) {
        strncpy ( num, x+i, 2 ); // Copies two characters starting from x+i
        // You get a null terminated string num here.
        printf("%d, ", atoi(num));
    }
printf("\n");

}

答案 4 :(得分:0)

已经提供了对您的问题的答案,即根据定义,C字符串是一个以NULL结尾的char数组。如果没有NULL终止符的空间,那么传递给字符串函数的字符串的结果最多是不可信任的。

我提供这个只是为了突出一些关于将char数组读入int数组的其他想法,其中NULL终止符几乎不成问题。

以下方法包括简单的字符串解析和动态内存使用,其中字符串内容直接读入int内存,绕过对中间字符串缓冲区的任何需要,从而能够读取任何 {来自字符串的{3}} ,并直接转换为int

请参阅内联评论以获取建议:

int main(void)
{
    //leave array index blank, the compiler will size it for you
    char x[] = "08 0223 22 97 382345 15 00 40 00 75 04 05 07 78 52 12 50 77 91 08 1000";
    //    ^
    int size = sizeof(x)/sizeof(x[0]);//use sizeof macro to get number of elements in array
    char *tok = NULL;
    int i = 0;
    int count=0;
    for(i=0;i<size;i++)
    {
        if(x[i]==' ')count++;//get count to size int array
    }
    int *array = malloc((count+1)*sizeof(int));
    if(array)
    {
        i=0;//reinitialize to 0 for use here
        tok = strtok(x, " \n");
        while(tok)//test after each parse before processing
        {
            if((i>0)&&(i%6==0))printf("\n");//newlines to format
            array[i++] = atoi(tok);
            printf("%6d, ", array[i]);
            //       ^ provide spacing in output
            tok = strtok(NULL, " \n");
        }
        free(array);
    }
    return 0;
}
相关问题