在 C 中标记 phone 数字
Tokenizing a phone number in C
我正在尝试标记一个 phone 数字并将其拆分为两个数组。它以“(515) 555-5555”形式的字符串开始。我希望标记区号、前 3 位数字和后 4 位数字。我将存储在一个数组中的区号,将其他 7 位数字存储在另一个数组中。两个数组都只保存数字本身。
我的代码似乎工作...有点。问题是当我打印两个存储阵列时,我发现了一些怪癖;
我的数组 aCode;
它按照我的要求存储了前 3 位数字,但随后它也打印了一些末尾缺口的垃圾值。我在调试器中遍历了它,数组只存储了我要求它存储的内容——515。那么它为什么会打印这些垃圾值呢?给出了什么?
我的数组aNum
;我可以将我需要的标记附加到它的末尾,唯一的问题是我最终在前面有一个额外的 space (这是有道理的;我正在添加到一个空数组,即添加到空 space)。我将代码修改为仅包含 7 个变量只是为了乱七八糟,我进入调试器,它告诉我数组包含并为空 space 和我需要的 6 个数字 - 最后一个没有空间.然而,当我打印它时, space 和所有 7 位数字都被打印出来了。这是怎么发生的?
我如何设置我的 strtok
函数,以便它首先复制“-”之前的 3 位数字,然后附加到我需要的最后 4 位数字?我见过的所有标记化示例都使用 while 循环,这意味着我必须选择 strcat
或 strcpy
来完成我的任务。我可以设置一个 "if" 语句来每次检查当前令牌的大小,但这对我来说太粗糙了,我觉得有一个更简单的方法。谢谢大家!
int main() {
char phoneNum[]= "(515) 555-5555";
char aCode[3];
char aNum[7];
char *numPtr;
numPtr = strtok(phoneNum, " ");
strncpy(aCode, &numPtr[1], 3);
printf("%s\n", aCode);
numPtr = strtok(&phoneNum[6], "-");
while (numPtr != NULL) {
strcat(aNum, numPtr);
numPtr = strtok(NULL, "-");
}
printf("%s", aNum);
}
我主要看到两个错误,
作为 3
char
的数组,aCode
在这里不是空终止的。将它用作 printf()
中 %s
格式说明符的参数会调用 undefined behaviour。 aNum
也有不同的方式。
strcat()
期望两个参数都有一个以 null 结尾的数组。 aNum
不是空终止的,第一次使用时,也会导致 UB。总是初始化你的局部变量。
此外,请参阅其他答案以获得完整的无错误代码。
您的代码有多个问题
您为aCode
分配了错误的大小,您应该为nul
终止符字节加1并将整个数组初始化为'\0'以确保行结束.
char aCode[4] = {'[=10=]'};
你不检查是否 strtok()
returns NULL
.
numPtr = strtok(phoneNum, " ");
strncpy(aCode, &numPtr[1], 3);
点 1,适用于 strcat(aNum, numPtr)
中的 aNum
这也会失败,因为 aNum
在第一次调用时尚未初始化。
对 strtok()
的后续调用必须将 NULL
作为第一个参数,因此
numPtr = strtok(&phoneNum[6], "-");
错了,应该是
numPtr = strtok(NULL, "-");
您的代码中最大的问题是未定义的行为:由于您正在将一个三字符常量读入一个三字符数组,因此您没有为空终止符留下 space。
由于您以固定长度的非常特定的格式对值进行标记,因此您可以使用 sscanf
:
的非常简洁的实现
char *phoneNum = "(515) 555-5555";
char aCode[3+1];
char aNum[7+1];
sscanf(phoneNum, "(%3[0-9]) %3[0-9]-%4[0-9]", aCode, aNum, &aNum[3]);
printf("%s %s", aCode, aNum);
此解决方案将格式 (###) ###-####
直接传递给 sscanf
,并告诉函数每个值需要放置的位置。上面使用的唯一 "trick" 是为最后一个参数传递 &aNum[3]
,指示 sscanf
将第三段的数据放入与第二段相同的存储中,但从位置 3 开始。
其他答案已经提到了主要问题,即aCode
和aNum
中space对于终止NUL字符的不足。 sscanf
的答案也是解决问题的最干净的方法,但考虑到使用 strtok
的限制,这里有一种可能的解决方案可供考虑:
char phone_number[]= "(515) 555-1234";
char area[3+1] = "";
char digits[7+1] = "";
const char *separators = " (-)";
char *p = strtok(phone_number, separators);
if (p) {
int len = 0;
(void) snprintf(area, sizeof(area), "%s", p);
while (len < sizeof(digits) && (p = strtok(NULL, separators))) {
len += snprintf(digits + len, sizeof(digits) - len, "%s", p);
}
}
(void) printf("(%s) %s\n", area, digits);
我正在尝试标记一个 phone 数字并将其拆分为两个数组。它以“(515) 555-5555”形式的字符串开始。我希望标记区号、前 3 位数字和后 4 位数字。我将存储在一个数组中的区号,将其他 7 位数字存储在另一个数组中。两个数组都只保存数字本身。
我的代码似乎工作...有点。问题是当我打印两个存储阵列时,我发现了一些怪癖;
我的数组
aCode;
它按照我的要求存储了前 3 位数字,但随后它也打印了一些末尾缺口的垃圾值。我在调试器中遍历了它,数组只存储了我要求它存储的内容——515。那么它为什么会打印这些垃圾值呢?给出了什么?我的数组
aNum
;我可以将我需要的标记附加到它的末尾,唯一的问题是我最终在前面有一个额外的 space (这是有道理的;我正在添加到一个空数组,即添加到空 space)。我将代码修改为仅包含 7 个变量只是为了乱七八糟,我进入调试器,它告诉我数组包含并为空 space 和我需要的 6 个数字 - 最后一个没有空间.然而,当我打印它时, space 和所有 7 位数字都被打印出来了。这是怎么发生的?
我如何设置我的 strtok
函数,以便它首先复制“-”之前的 3 位数字,然后附加到我需要的最后 4 位数字?我见过的所有标记化示例都使用 while 循环,这意味着我必须选择 strcat
或 strcpy
来完成我的任务。我可以设置一个 "if" 语句来每次检查当前令牌的大小,但这对我来说太粗糙了,我觉得有一个更简单的方法。谢谢大家!
int main() {
char phoneNum[]= "(515) 555-5555";
char aCode[3];
char aNum[7];
char *numPtr;
numPtr = strtok(phoneNum, " ");
strncpy(aCode, &numPtr[1], 3);
printf("%s\n", aCode);
numPtr = strtok(&phoneNum[6], "-");
while (numPtr != NULL) {
strcat(aNum, numPtr);
numPtr = strtok(NULL, "-");
}
printf("%s", aNum);
}
我主要看到两个错误,
作为
3
char
的数组,aCode
在这里不是空终止的。将它用作printf()
中%s
格式说明符的参数会调用 undefined behaviour。aNum
也有不同的方式。strcat()
期望两个参数都有一个以 null 结尾的数组。aNum
不是空终止的,第一次使用时,也会导致 UB。总是初始化你的局部变量。
此外,请参阅其他答案以获得完整的无错误代码。
您的代码有多个问题
您为
aCode
分配了错误的大小,您应该为nul
终止符字节加1并将整个数组初始化为'\0'以确保行结束.char aCode[4] = {'[=10=]'};
你不检查是否
strtok()
returnsNULL
.numPtr = strtok(phoneNum, " "); strncpy(aCode, &numPtr[1], 3);
点 1,适用于
strcat(aNum, numPtr)
中的aNum
这也会失败,因为aNum
在第一次调用时尚未初始化。对
strtok()
的后续调用必须将NULL
作为第一个参数,因此numPtr = strtok(&phoneNum[6], "-");
错了,应该是
numPtr = strtok(NULL, "-");
您的代码中最大的问题是未定义的行为:由于您正在将一个三字符常量读入一个三字符数组,因此您没有为空终止符留下 space。
由于您以固定长度的非常特定的格式对值进行标记,因此您可以使用 sscanf
:
char *phoneNum = "(515) 555-5555";
char aCode[3+1];
char aNum[7+1];
sscanf(phoneNum, "(%3[0-9]) %3[0-9]-%4[0-9]", aCode, aNum, &aNum[3]);
printf("%s %s", aCode, aNum);
此解决方案将格式 (###) ###-####
直接传递给 sscanf
,并告诉函数每个值需要放置的位置。上面使用的唯一 "trick" 是为最后一个参数传递 &aNum[3]
,指示 sscanf
将第三段的数据放入与第二段相同的存储中,但从位置 3 开始。
其他答案已经提到了主要问题,即aCode
和aNum
中space对于终止NUL字符的不足。 sscanf
的答案也是解决问题的最干净的方法,但考虑到使用 strtok
的限制,这里有一种可能的解决方案可供考虑:
char phone_number[]= "(515) 555-1234";
char area[3+1] = "";
char digits[7+1] = "";
const char *separators = " (-)";
char *p = strtok(phone_number, separators);
if (p) {
int len = 0;
(void) snprintf(area, sizeof(area), "%s", p);
while (len < sizeof(digits) && (p = strtok(NULL, separators))) {
len += snprintf(digits + len, sizeof(digits) - len, "%s", p);
}
}
(void) printf("(%s) %s\n", area, digits);