我试图只读取字符串中的整数。每次迭代时,空格和非整数字符基本上是随机的。理想情况下,我的代码将遍历此代码并仅打印(或以其他方式存储)整数。所以对于这个测试用例,它将是6,1,0,16,2,3
等等。
char line [ 200 ] ="T06 1/ 0 16/ 2 3/15 41/40 17/36 0/11 0/11 0/11 1/14 1/ 7";
int num=0;
int count=0;
int i=0;
char *str = line;
while (sscanf(str, "%d%n", &num,&i)){
printf ("number: %d\n",num);
str+=i;
count++;
}
显然它不起作用,我想我需要一种方法让sscanf跳过任何不是0-9的东西。有什么帮助吗?
由于
答案 0 :(得分:2)
更改为
while (sscanf(str, "%*[^0-9]%d%n", &num, &i)==1){
printf ("number: %d\n",num);
str+=i;
count++;
}
答案 1 :(得分:1)
#include <stdio.h>
#include <string.h>
#include <errno.h>
#include <limits.h>
#include <stdlib.h>
enum oflow { OFL_GOOD, OFL_OVER, OFL_UNDER };
int getnums(const char *str, int nums[], enum oflow oflow[], int n)
{
int i;
for (i = 0; *str; ) {
char *junk;
long val;
str += strcspn(str, "0123456789+-");
if (!*str)
break;
errno = 0;
val = strtol(str, &junk, 10);
if (junk > str) {
if (i < n) {
if (((val == LONG_MIN) && errno == ERANGE) || (val < INT_MIN)) {
nums[i] = 0;
oflow[i++] = OFL_UNDER;
} else if (((val == LONG_MAX) && errno == ERANGE) || (val > INT_MAX)) {
nums[i] = 0;
oflow[i++] = OFL_OVER;
} else {
oflow[i] = OFL_GOOD;
nums[i++] = val;
}
} else {
i++;
}
str = junk;
} else {
str++; /* no number was pulled out: skip one char and try again */
}
}
return i;
}
int main(int argc, char **argv)
{
int nums[256];
enum oflow oflow[256];
if (argc > 1) {
int n = getnums(argv[1], nums, oflow, 256);
int i;
if (n > 256) {
printf("array is too small: we need %d elements\n", n);
n = 256;
}
for (i = 0; i < n; i++) {
if (oflow[i])
printf("nums[%d] = %sflow\n", i, oflow[i] == OFL_OVER ? "over" : "under");
else
printf("nums[%d] = %d\n", i, nums[i]);
}
}
return 0;
}
测试:
$ ./nums "" $ ./nums "0" nums[0] = 0 $ ./nums "-" $ ./nums "+" $ ./nums "+1" nums[0] = 1 $ ./nums "-1" nums[0] = -1 $ ./nums "abc" $ ./nums "asd+asdf+1 -0+1-3234abc-10zzz-" nums[0] = 1 nums[1] = 0 nums[2] = 1 nums[3] = -3234 nums[4] = -10 $ ./nums "+++-1+++" nums[0] = -1 $ ./nums "++" $ ./nums "1+11111111111111111111111-111111111111111111111" nums[0] = 1 nums[1] = overflow nums[2] = underflow $ ./nums "$(seq 1 300)" | head -5 array is too small: we need 300 elements nums[0] = 1 nums[1] = 2 nums[2] = 3 nums[3] = 4 $ ./nums "$(seq 1 300)" | tail -5 nums[251] = 252 nums[252] = 253 nums[253] = 254 nums[254] = 255 nums[255] = 256
家庭作业练习:在junk == str
之后strtol
的情况是什么,以便str++
案例执行?为什么我们需要这种逻辑?
答案 2 :(得分:1)
用空格替换所有非数字字符,然后只用scanf
替换它们。您需要对负片进行调整,但我对此进行了测试,并为给定的输入提供了所需的输出。
char line [ 200 ] ="T06 1/ 0 16/ 2 3/15 41/40 17/36 0/11 0/11 0/11 1/14 1/ 7";
int num=0;
int count=0;
int i=0;
char *str = line;
for (int i = 0; i < strlen(line); i++)
if (!isdigit(line[i]))
line[i] = ' ';
while (sscanf(str, "%d%n", &num,&i) == 1){
printf ("number: %d\n",num);
str+=i;
count++;
}
答案 3 :(得分:0)
sscanf
真的很难用,如果你的输入每次都不一样,那就更糟了。您可以尝试正则表达式,或者您可以尝试手动解析整数:
int i;
int num = 0;
int num_valid = 0;
int count = 0;
for(i = 0; line[i]; i++) { // loop through every character
if(line[i] >= '0' && line[i] <= '9') { // check to see if it's a digit
num *= 10; // scale up num
num += lin[i] - '0'; // convert ASCII to INT
num_valid = 1; // indicate that num contains a real number
} else if(num_valid) { // if the number is done
printf ("number: %d\n",num);
count++;
num = 0;
num_valid = 0;
}
}
答案 4 :(得分:0)
为字符串结尾和返回值表单sscanf()
char line [200]="T06 1/ 0 16/ 2 3/15 41/40 17/36 0/11 0/11 0/11 1/14 1/ 7";
int num;
int count=0;
int i;
char *str = line;
while (*str) {
if (1 == sscanf(str, "%d%n", &num, &i)){
printf ("number: %d\n", num);
str += i;
count++;
}
else str++;
}
答案 5 :(得分:0)
要过滤除数字以外的所有内容,请在循环中使用 strcspn()
和 sscanf()
:
int i;
while (sscanf(str += strcspn(str, "0123456789"), "%d%n", &num, &i) == 1) {
printf("number: %d\n", num);
count++;
str += i;
}