我已经为此苦苦挣扎了一段时间,并认为我最好还是寻求帮助,而不是将自己的头撞到墙上。
因此,假设您有字符串"10 10 10 4 4 4 9 9 9 2"
然后您要遍历,将数字一一取出,然后将其添加到要使用的整数数组中。
我已经制作了很多原型,并继续为自己做更多不必要的工作。起初我使用的是strtok()
,但后来人们说那已经过时了,使用strsep()
我该怎么做?
任何帮助将不胜感激!
我的函数似乎总是返回一个充满零的int数组。为什么会这样?
int *parse_line(char *line){
char sNumArray[MAX];
strcpy(sNumArray, line);
char *tokens = NULL;
int *numbers = malloc(sizeof(int) * MAX);
tokens = strtok(sNumArray, " ");
for(int i = 0; ; i++) {
numbers[i] = atoi(tokens);
printf("%d \n", atoi(tokens));
tokens = strtok(NULL, " ");
if (tokens == NULL)
break;
}
return numbers;
}
这些是我在main中定义的变量,并使用...调用我的函数。
int *skyline;
skyline = parse_line(line);
for (int j = 0; j < 100 ; ++j) {
printf("%d \n", skyline[j]);
}
答案 0 :(得分:3)
您有三个主要选择(1)按预期的方式使用strtol
,使用*endptr
参数将字符串中的当前读取位置前进到转换的最后一位数字之后,或者(2)使用sscanf
说明符传递给"%n"
,以报告在转换为int
(或任何类型)中使用的字符数,并使用该值来提高读取位置。同样的方式或(3)用strtok
标记字符串,然后使用strtol
(因为atoi
不能使用,因为它提供了绝对零错误检查)。确实没有必要同时使用strtok
和strtol
,因为strtol
已经提供了一种方法来超越转换后的数字。本质上,您是通过调用strtol
复制strtok
已经完成的工作,但这是一种有效的方法。
例如,使用strtol
,您可以执行以下操作:
#include <stdio.h>
#include <stdlib.h> /* for strtol */
#include <string.h> /* for strncpy */
#include <errno.h> /* for errno */
#define MAXC 1024 /* constant - max chars in line */
int main (void) {
char str[MAXC] = ""; /* str to hold line, initialized all zero */
while (fgets (str, MAXC, stdin)) { /* read each line of input */
char *p = str, /* pointer for strtol */
*endptr = NULL; /* end pointer for strtol */
while (*p) { /* work down str parsing integer or hex values */
long val = strtol (p, &endptr, 0); /* convert from p */
/* validate conversion */
if (p != endptr) { /* were digits converted? */
if (!errno) { /* if errno 0, successful conversion */
char ascii[MAXC] = ""; /* for string converted */
strncpy (ascii, p, endptr - p); /* copy to ascii */
ascii[endptr-p] = 0; /* nul-terminate ascii */
/* test whether string begins "0x" or "0X", output */
if (*p == '0' && (*(p + 1) == 'x' || *(p + 1) == 'X'))
printf ("hex conversion: %-10s %10lu 0x%lx\n",
ascii, val, val);
else
printf ("int conversion: %-10s % ld\n",
ascii, val);
}
p = endptr; /* advance p to 1-past end of converted string */
}
/* find start of next valid number in str, including (+/-) */
for (; *p; p++) {
if ('0' <= *p && *p <= '9') /* positive value */
break; /* explicitly signed value */
if ((*p == '+' || *p == '-') && '0' <= *(p+1) && *(p+1) <= '9')
break;
}
}
}
return 0;
}
使用/输出示例
$ echo "10 10 10 4 4 4 9 9 9 2" | ./bin/fgets_strtol_any
int conversion: 10 10
int conversion: 10 10
int conversion: 10 10
int conversion: 4 4
int conversion: 4 4
int conversion: 4 4
int conversion: 9 9
int conversion: 9 9
int conversion: 9 9
int conversion: 2 2
或转换杂乱文件中的所有整数,例如
示例输入文件
$ cat dat/10intmess.txt
8572,;a -2213,;--a 6434,;
a- 16330,;a
- The Quick
Brown%3034 Fox
12346Jumps Over
A
4855,;*;Lazy 16985/,;a
Dog.
11250
1495
使用/输出示例
$ ./bin/fgets_strtol_any <dat/10intmess.txt
int conversion: 8572 8572
int conversion: -2213 -2213
int conversion: 6434 6434
int conversion: 16330 16330
int conversion: 3034 3034
int conversion: 12346 12346
int conversion: 4855 4855
int conversion: 16985 16985
int conversion: 11250 11250
int conversion: 1495 1495
使用sscanf
类似地,您可以使用sscanf
,但请注意,它不提供错误处理的级别或程度-意味着您只能知道它成功转换了文本还是失败了。两者之间无,不报告通过errno
的上溢或下溢。但是,它与strtok
一起是从一行文本中解析整数的其他有效方法,例如
#include <stdio.h>
#include <stdlib.h>
#define MAXC 1024
int main (int argc, char **argv) {
char buf[MAXC] = ""; /* buffer to hold MAXC chars at a time */
int nval = 0; /* total number of integers found */
FILE *fp = argc > 1 ? fopen (argv[1], "r") : stdin;
if (!fp) { /* validate file open for reading */
fprintf (stderr, "error: file open failed '%s'.\n", argv[1]);
return 1;
}
while (fgets (buf, MAXC, fp)) {
char *p = buf; /* pointer to line */
int val, /* int val parsed */
nchars = 0; /* number of chars read */
/* while chars remain in buf and a valid conversion to int takes place
* output the integer found and update p to point to the start of the
* next digit.
*/
while (*p) {
if (sscanf (p, "%d%n", &val, &nchars) == 1) {
printf (" %d", val);
if (++nval % 10 == 0) /* output 10 int per line */
putchar ('\n');
}
p += nchars; /* move p nchars forward in buf */
/* find next number in buf */
for (; *p; p++) {
if (*p >= '0' && *p <= '9') /* positive value */
break;
if (*p == '-' && *(p+1) >= '0' && *(p+1) <= '9') /* negative */
break;
}
}
}
printf ("\n %d integers found.\n", nval);
if (fp != stdin) fclose (fp); /* close file if not stdin */
return 0;
}
使用/输出示例
$ echo "10 10 10 4 4 4 9 9 9 2" | ./bin/fgets_sscanf_int_any_ex
10 10 10 4 4 4 9 9 9 2
10 integers found.
或输入混乱
$ echo "1, 2 buckle my shoe, 3, 4..." | ./bin/fgets_sscanf_int_any_ex
1 2 3 4
4 integers found.
使用strtok
只是第一个示例中显示的strtol
转换的“前端”(它提供了自己的标记数字值的方法)。您只需使用strtok
(空格换行符)的分隔符循环调用" \n"
的缓冲区,然后使用strtol
转换指向的字符串。 (在这里,您只是使用endptr
来验证数字是否已转换,而忽略了它的使用来超越转换后的数字。本质上,strtok
复制了strtok
已经完成的操作,但是如果它更容易理解,您可以忍受重复的通话,这很好。您可以执行以下操作。
while (fgets (buf, MAXC, fp)) {
char *p = buf; /* pointer to buf to use with strtok */
/* 1st call using buffer, all remaining calls using NULL */
for (p = strtok (p, " \n"); p; p = strtok (NULL, " \n")) {
errno = 0; /* reset errno */
char *endptr; /* end pointer */
long tmp = strtol (p, &endptr, 0); /* convert using long */
if (p != endptr) { /* validate digits converted */
/* now validate value within range of int */
if (!errno && INT_MIN <= tmp && tmp <= INT_MAX)
/* you have an integer! */
}
else if (tmp == 0)
/* no digits were converted */
}
}
仔细检查一下,如果还有其他问题,请告诉我。
答案 1 :(得分:0)
我认为这将满足您的要求。
#include "stdafx.h"
#include <stdio.h>
#include <iostream>
#include <math.h>
#include <stdlib.h>
using namespace std;
#define MAX 100
int *parse_line(char *line, int *numInts) {
char sNumArray[MAX];
strcpy(sNumArray, line);
int *numbers = (int *) malloc(sizeof(int) * MAX);
char *tokens = strtok(sNumArray, " ");
for (int i = 0; ; i++) {
numbers[i] = atoi(tokens);
tokens = strtok(NULL, " ");
if (tokens == NULL) {
*numInts = i+1;
break;
}
}
return numbers;
}
int main() {
char *line = "10 10 10 4 4 4 9 9 9 2";
int numIntsExtracted = 0;
int *skyline = parse_line(line, &numIntsExtracted);
for (int j = 0; j < numIntsExtracted; ++j) {
printf("%d \n", skyline[j]);
}
return 0;
}
运行后得到的输出。
10
10
10
4
4
4
9
9
9
2
答案 2 :(得分:0)
我喜欢为此使用功能strtol()
,因为如果将指针传递给它,它将返回下一个点以继续解析。也有未签名的版本,例如:strtoul()
。自C99以来,它们是标准配置。此外,strtol()
可以解析十六进制,并且比atoi()
之类的旧函数(错误返回0)更好地处理错误。
以下代码的重要部分是strtol()
的结果。通话后next_number
不变时,没有更多输入(或发生错误)。变量ptr
用于跟踪字符串中解析的位置。它被赋予strtol()
,它会改变next_number
指向下一个元素,因此ptr
会向前跳转-分配给next_number
(粘贴刚刚解析的元素),然后过程重复。
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main(void)
{
char *number_str = "10 10 10 4 4 4 9 9 9 2";
char *ptr;
char *next_number;
int numbers[1000];
int number_count = 0;
long num;
next_number = number_str;
do
{
ptr = next_number;
num = strtol(ptr, &next_number, 10);
if (ptr != next_number) // found one
{
numbers[number_count] = (int)num;
printf("Stored %3d into numbers[%d]\n", numbers[number_count], number_count);
number_count += 1;
}
} while(ptr != next_number);
return 0;
}
答案 3 :(得分:-5)
只需使用scanf()在for或while循环中一个一个地获取每个数字即可。
for i = 0 to n
scanf(“%d”, &num);
请通过许多示例向Google或bing在线查询google或bing搜索。