c - Ignoring numbers with letters around them
问题描述
#include <stdio.h>
#include <ctype.h>
int main(void)
{
const char *str = NULL;
size_t len = 0;
getline(&str,&len,stdin);
int i = 0;
unsigned int count = 0, tmp = 0;
printf("%s\n", str);
while (sscanf(&str[count], "%d %n", &i, &tmp) != EOF) {
count += tmp;
printf("number %d\n", i);
}
return 0;
}
What I'm trying to do here is ask the user for a line of integers (positive or negative) and I only care about integers that are valid that have a space between them, if there was a non numeric char entered then it should ignore what comes after it. Up top is what I have so far but I have some bugs with it, what I have right now is also ignoring white space which is what I want. Look at EXP for more clarification.
EXP:
input: 1 2 3 4a desired output-> 1 2 3 my ouput-> 1 2 3 4 4
input: 1 2 3 a4 desired output-> 1 2 3 my ouput-> 1 2 3 3
input: 1 2 3 a b c 4 5 6 7 desired output-> 1 2 3 my output-> 1 2 3 3 3 3 4 5 6 7
Valid input EXP:
input: 12 367 98 -3 -67 desired output-> 12 367 98 -3 -67
解决方案
每当您需要通过缓冲区挑选数值时,您都想考虑strtoX()
(在哪里X
可以是l
, ul
, f
, d
, forstrtol()
等)。原因有两个。(1) 这些函数旨在允许您通过提供指向字符串本身的指针的endptr
参数以及在最后一个数字成功转换后更新为指向下一个字符的参数来做到这一点;(2) 这些功能为转换的各个方面提供了完整的错误检测。
由于endptr
参数被更新为最后一个转换的数字,您只需遍历缓冲区,尝试转换,成功转换后,您只需更新初始指针endptr
并重复直到用完字符。见man 3 strtol
由于endptr
更新为指向转换的最后一个数字之后的位置,因此您可以简单地检查指向的字符是否是字符串endptr
的nul 终止字符,或者!isspace(*endptr)
确定该组数字中是否包含非数字。
您的案例的一个简单实现是:
#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>
#include <errno.h>
#define MAXC 1024
int main (int argc, char **argv) {
char buf[MAXC]; /* buffer to hold each line */
/* use filename provided as 1st argument (stdin by default) */
FILE *fp = argc > 1 ? fopen (argv[1], "r") : stdin;
if (!fp) { /* validate file open for reading */
perror ("file open failed");
return 1;
}
while (fgets (buf, MAXC, fp)) { /* read each line into buf */
char *p = buf, *ep = p; /* pointers to use with strtol() */
for (;;) { /* loop continually */
errno = 0; /* reset errno */
long val = strtol (p, &ep, 0); /* attempt conversion to long */
if (p == ep) /* check if no characters converted */
break;
else if (errno) /* check for under/overflow */
break;
else if (*ep && !isspace(*ep)) /* check next char for non-space */
break;
else
printf (" %ld", val); /* good all-digit conversion */
p = ep; /* update pointer to endpointer */
}
putchar ('\n'); /* tidy up with newline */
}
if (fp != stdin) /* close file if not stdin */
fclose (fp);
}
示例输入文件
$ cat dat/numwalpha.txt
1 2 3 4a
1 2 3 a4
1 2 3 a b c 4 5 6 7
示例使用/输出
$ ./bin/strtol_numonly dat/numwalpha.txt
1 2 3
1 2 3
1 2 3
添加错误报告
endptr
失败时,您可以简单地输出以(ep
以上)开头的字符,以查看失败的原因。您可以包含一个预处理器指令,如果您愿意,可以使用定义来打开/关闭错误报告DEBUG
,例如
#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>
#include <errno.h>
#define MAXC 1024
int main (int argc, char **argv) {
char buf[MAXC]; /* buffer to hold each line */
/* use filename provided as 1st argument (stdin by default) */
FILE *fp = argc > 1 ? fopen (argv[1], "r") : stdin;
if (!fp) { /* validate file open for reading */
perror ("file open failed");
return 1;
}
while (fgets (buf, MAXC, fp)) { /* read each line into buf */
char *p = buf, *ep = p; /* pointers to use with strtol() */
for (;;) { /* loop continually */
errno = 0; /* reset errno */
long val = strtol (p, &ep, 0); /* attempt conversion to long */
if (p == ep) { /* check if no characters converted */
#ifdef DEBUG
fprintf (stderr, "error: no digits converted in '%s'.\n", p);
#endif
break;
}
else if (errno) { /* check for under/overflow */
#ifdef DEBUG
fprintf (stderr, "error: over/under-flow in conversion or '%s'.\n", p);
#endif
break;
}
else if (*ep && !isspace(*ep)) { /* check next char for non-space */
#ifdef DEBUG
fprintf (stderr, "error: mixed alphanumeric '%s'.\n", ep);
#endif
break;
}
else
printf (" %ld", val); /* good all-digit conversion */
p = ep; /* update pointer to endpointer */
}
putchar ('\n'); /* tidy up with newline */
}
if (fp != stdin) /* close file if not stdin */
fclose (fp);
}
然后编译-DDEBUG
以启用定义,您将拥有:
$ ./bin/strtol_numonly dat/numwalpha.txt
error: mixed alphanumeric 'a
'.
1 2 3
error: no digits converted in ' a4
'.
1 2 3
error: no digits converted in ' a b c 4 5 6 7
'.
1 2 3
这表明第一种情况由于'a'
最后的 a 而失败,第二种情况是由于"a4"
要转换的字符串,最后一种是因为"a b c 4 5 6 7"
是字符串中剩下的所有内容,并且'a'
是下一次转换。
推荐阅读
- c++ - 如何将 VideoWriter 代码合并到 ros 的 image_publisher 代码中?
- .net - 在容器上连接到 RabbitMQ 的问题
- amazon-web-services - 启动应用程序时出错?
- jupyter-notebook - 将 Jupyter Lab 中的笔记本导出为 PDF 时隐藏所有代码
- php - 我想在 php 中的特定区域坐标数组中找到我的纬度
- android - 无法在自定义视图中解析构造函数 ArrayAdapter
- sql - DB2(v10.5.0.5) 如何将自增列添加到已存在的表中
- javascript - 关闭浏览器选项卡时打开模式
- sql - 如果 SQL Server 中的主键匹配,则约束更新值
- java - 无法看到提供提示或重定向到错误路径的失败构建的 java 编译器行