![](/img/trans.png)
[英]Reading a file with numbers separated by commas and storing each line into a struct pointer
[英]C Reading a file of digits separated by commas
我正在嘗試讀取一個文件,該文件包含逗號分隔的數字,並將它們存儲在沒有逗號存在的數組中。
例如:processes.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);
}
但這是兩位數的問題。 有誰有更好的解決方案? 謝謝!
對於逗號前沒有空格顯示的數據,您可以簡單地使用:
while (fscanf(fp1, "%d,", &num) == 1 && i < 300)
list[i++] = num;
如果有數字,它將在數字后讀取逗號,而在沒有數字的情況下,它會靜默忽略。 如果數據中逗號前可能有空格,請在格式字符串中的逗號前添加一個空格。 在i
上進行的測試可防止您在list
數組的邊界之外書寫。 ++
運算符在這里使用。
首先, 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
這樣做。 在這種情況下,它並不重要,因為由於該原因該代碼不太可能失敗,因此出於可讀性考慮,我將其省略。 但是在生產代碼中,您應該檢查它。
我的解決方案是先讀取整行,然后使用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");
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.