【发布时间】:2010-09-16 16:04:13
【问题描述】:
我有以下字符串:
"..1....10..20....30...40....50...80..."
我需要将其中的所有数字提取到数组中。
在 C 中最好的方法是什么?
【问题讨论】:
我有以下字符串:
"..1....10..20....30...40....50...80..."
我需要将其中的所有数字提取到数组中。
在 C 中最好的方法是什么?
【问题讨论】:
也许最简单的方法是使用strtok() 函数(或strtok_r(),如果需要考虑可重入性):
char str[] = "..1...10...20";
char *p = strtok(str, ".");
while (p != NULL) {
printf("%d\n", atoi(p));
p = strtok(NULL, ".");
}
一旦你得到了调用atoi()的结果,将这些整数保存到一个数组中应该是一件简单的事情。
【讨论】:
您可以使用带有抑制赋值 (%*[.]) 的 sscanf 代码来跳过点(或您想要的任何其他字符),并使用扫描的字符计数代码 %n 来推进字符串指针。
const char *s = "..1....10..20....30...40....50...80...";
int num, nc;
while (sscanf(s, "%*[.]%d%n", &num, &nc) == 1) {
printf("%d\n", num);
s += nc;
}
【讨论】:
我更喜欢在 for 循环中使用 strtok。让它感觉更自然,虽然语法看起来有点奇怪。
char str[] = "..1....10..20....30...40....50...80..."
for ( char* p = strtok( strtok, "." ); p != NULL; p = strtok( NULL, "." ) )
{
printf( "%d\n", atoi( p ) );
}
【讨论】:
这是正确的方法,它比最简单的方法长一点,但如果读取的值超出范围,它不会出现未定义的行为,如果第一个字符不是点,则可以正常工作,等等。您没有指定数字是否可以是负数,所以我使用了有符号类型,但只允许正值,您可以通过允许内部 while 循环顶部的负号轻松更改此设置。此版本允许任何非数字字符分隔整数,如果您只想允许点,您可以修改内部循环以仅跳过点,然后检查数字。
#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>
#include <errno.h>
#define ARRAY_SIZE 10
size_t store_numbers (const char *s, long *array, size_t elems)
{
/* Scan string s, returning the number of integers found, delimited by
* non-digit characters. If array is not null, store the first elems
* numbers into the provided array */
long value;
char *endptr;
size_t index = 0;
while (*s)
{
/* Skip any non-digits, add '-' to support negative numbers */
while (!isdigit(*s) && *s != '\0')
s++;
/* Try to read a number with strtol, set errno to 0 first as
* we need it to detect a range error. */
errno = 0;
value = strtol(s, &endptr, 10);
if (s == endptr) break; /* Conversion failed, end of input */
if (errno != 0) { /* Error handling for out of range values here */ }
/* Store value if array is not null and index is within array bounds */
if (array && index < elems) array[index] = value;
index++;
/* Update s to point to the first character not processed by strtol */
s = endptr;
}
/* Return the number of numbers found which may be more than were stored */
return index;
}
void print_numbers (const long *a, size_t elems)
{
size_t idx;
for (idx = 0; idx < elems; idx++) printf("%ld\n", a[idx]);
return;
}
int main (void)
{
size_t found, stored;
long numbers[ARRAY_SIZE];
found = store_numbers("..1....10..20....30...40....50...80...", numbers, ARRAY_SIZE);
if (found > ARRAY_SIZE)
stored = ARRAY_SIZE;
else
stored = found;
printf("Found %zu numbers, stored %zu numbers:\n", found, stored);
print_numbers(numbers, stored);
return 0;
}
【讨论】: