我有一个更长的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 ......发生了什么事?
答案 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;
}