我正在尝试读取一个文件,该文件包含逗号分隔的数字,并将它们存储在不包含逗号的数组中。
例如:processs.txt包含
0,1,3
1,0,5
2,9,8
3,10,6
一个叫做数字的数组应该看起来像:
0 1 3 1 0 5 2 9 8 3 10 6
到目前为止,我的代码是:
FILE *fp1;
char c; //declaration of characters
fp1=fopen(argv[1],"r"); //opening the file
int list[300];
c=fgetc(fp1); //taking character from fp1 pointer or file
int i=0,number,num=0;
while(c!=EOF){ //iterate until end of file
if (isdigit(c)){ //if it is digit
sscanf(&c,"%d",&number); //changing character to number (c)
num=(num*10)+number;
}
else if (c==',' || c=='\n') { //if it is new line or ,then it will store the number in list
list[i]=num;
num=0;
i++;
}
c=fgetc(fp1);
}
但是如果它是两位数,就出现了问题。有谁有更好的解决方案?谢谢!
答案 0 :(得分:2)
对于逗号前没有空格显示的数据,您可以简单地使用:
while (fscanf(fp1, "%d,", &num) == 1 && i < 300)
list[i++] = num;
如果有一个数字,它将在数字后读取逗号,而在没有数字的情况下会默默地忽略。如果数据中逗号前可能有空格,请在格式字符串中的逗号前添加一个空格。在i
上进行的测试可防止您在list
数组的边界之外进行编写。 ++
运算符在这里使用。
答案 1 :(得分:0)
首先,fgetc
返回一个int
,因此c
必须是一个int
。
除此之外,我将使用稍微不同的方法。我承认这有点复杂。但是,如果您有几种需要不同操作的不同类型的字段(例如解析器),则可以使用这种方法。对于您的特定问题,我建议Johathan Leffler给出答案。
int c=fgetc(f);
while(c!=EOF && i<300) {
if(isdigit(c)) {
fseek(f, -1, SEEK_CUR);
if(fscanf(f, "%d", &list[i++]) != 1) {
// Handle error
}
}
c=fgetc(f);
}
在这里,我不在乎逗号和换行符。除了数字以外,我将其他任何内容都用作分隔符。我要做的基本上是这样:
read next byte
if byte is digit:
back one byte in the file
read number, irregardless of length
else continue
添加的条件i<300
是出于安全原因。如果您真的想检查逗号和换行符(我没有发现您觉得它很重要),那么可以轻松地添加一个else if (c == ...
来处理错误。
请注意,您应始终检查sscanf
,fscanf
,scanf
等函数的返回值。实际上,您也应该对fseek
执行此操作。在这种情况下,它并不重要,因为由于该原因该代码不太可能失败,因此出于可读性考虑,我将其省略。但是在生产代码中,您应该检查它。
答案 2 :(得分:0)
我的解决方案是先读取整行,然后用逗号分隔的strtok_r进行解析。如果您想要可移植的代码,则应改用strtok
。
天真地实现readline是这样的:
static char *readline(FILE *file)
{
char *line = malloc(sizeof(char));
int index = 0;
int c = fgetc(file);
if (c == EOF) {
free(line);
return NULL;
}
while (c != EOF && c != '\n') {
line[index++] = c;
char *l = realloc(line, (index + 1) * sizeof(char));
if (l == NULL) {
free(line);
return NULL;
}
line = l;
c = fgetc(file);
}
line[index] = '\0';
return line;
}
然后,您只需要用strtok_r
来分析整行,那么您将以如下形式结束:
int main(int argc, char **argv)
{
FILE *file = fopen(argv[1], "re");
int list[300];
if (file == NULL) {
return 1;
}
char *line;
int numc = 0;
while((line = readline(file)) != NULL) {
char *saveptr;
// Get the first token
char *tok = strtok_r(line, ",", &saveptr);
// Now start parsing the whole line
while (tok != NULL) {
// Convert the token to a long if possible
long num = strtol(tok, NULL, 0);
if (errno != 0) {
// Handle no value conversion
// ...
// ...
}
list[numc++] = (int) num;
// Get next token
tok = strtok_r(NULL, ",", &saveptr);
}
free(line);
}
fclose(file);
return 0;
}
要打印整个列表,只需使用for循环:
for (int i = 0; i < numc; i++) {
printf("%d ", list[i]);
}
printf("\n");