簡體   English   中英

讀取Txt文件語言C

[英]Read Txt file Language C

嗨,我有這個文件結構:

0
2 4
0: 1(ab) 5(b)
1: 2(b) 6(a)
2: 0(a) 2(b)
3: 2(a) 6(b)
4: 5(ab)
5: 2(a) 6(b)
6: 4(b) 6(ab)

每行將使用其數據(數字+字母)來提供結構。
閱讀該行並獲取我想要的字符串的最佳方法是什么?

例:

0
2 4
0,1,ab,5,b
1,2,b,5,a
...

這些行的大小可能會有所不同,因為我們可以有1、2、3,....個數字。

我已經做到了:

//struct 
#define MAX_ 20

struct otherstats{ //struct otherStats
  int conectstat[MAX_];//conection with others stats
  int transitions[MAX_];//Symbols betwen conection ASCI
}tableStats[MAX_];

struct sAutomate{
 int stat_initial; //initial
 int stats_finals[MAX_]; //final orfinals
 struct otherstats tableStats[MAX_]; //otherStats 0 1 2 3 4 5 6
};

/* eXample that what i want ..using the example 
sAutomate.stat_initial=0
sAutomate.stats_finals[0]=2
sAutomate.stats_finals[1]=4

Others Stats table
//0
sAutomate.tableStats[0].conectstat[0]=1;
sAutomate.tableStats[0].conectstat[1]=5;
sAutomate.tableStats[0].transitions[0]=ab;
sAutomate.tableStats[0].transitions[1]=b; 
//1
sAutomate.tableStats[1].conectstat[0]=2;
sAutomate.tableStats[1].conectstat[1]=6;
sAutomate.tableStats[1].transitions[0]=b;
sAutomate.tableStats[1].transitions[1]=a;
///etc
 */



void scanfile(){ //function to read the file

struct sAutomate st; //initialize st struct

char filename[] = "txe.txt";
FILE *file = fopen ( filename, "r" );
char buf[81];       
char parts[5][11];  

fscanf(file,"%d", &st.stat_initial);//read first line
printf("initial state : %d \n", st.stat_initial);
fscanf(file,"%d",&st.stats_finals);
fscanf(file,"%d",&st.stats_finals);


while (fgets(buf, sizeof(buf), stdin) != NULL)
{
if (sscanf(buf, "%10[^:]: (%10[^(], %10[^)]), (%10[^(], %10[^)])",
           parts[0], parts[1], parts[2], parts[3], parts[4]) == 5)
{
  printf("parts: %s, %s, %s, %s, %s\n",
         parts[0], parts[1], parts[2], parts[3], parts[4]);
}
else
{
  printf("Invalid input: %s", buf);
}
}
//fclose

我看到的第一個問題是您正在覆蓋stats_finals

fscanf(file,"%d",&st.stats_finals);
fscanf(file,"%d",&st.stats_finals);

您想在這里做的是:

fscanf(file,"%d",&st.stats_finals[0]);
fscanf(file,"%d",&st.stats_finals[1]);

保存文本文件中的“ 2”和“ 4”。

第二個主要問題是您正在從stdin讀取內容:

while (fgets(buf, sizeof(buf), stdin) != NULL)

那不會讀取您的文本文件,而是從鍵盤讀取輸入內容...所以您希望這樣:

while (fgets(buf, sizeof(buf), file) != NULL)

第三個(次要)問題是fscanf()無法讀取換行符,而fgets()可以讀取。 這意味着,當您從讀取第二個stats_finals到while循環中的第一次讀取時,您的第一個輸入將剛好位於換行符的左側。 因為您檢查了“無效輸入”,所以這沒什么大不了的,但是值得注意。

最后,您的sscanf在我看來錯了:

sscanf(buf, "%10[^:]: (%10[^(], %10[^)]), (%10[^(], %10[^)])",
               ^                        ^
              That's a width of 10,     Why are you checking for commas? You didn't
              I don't think that's      have any in your text file
              what you wanted...

我認為這更是您想要的:

sscanf(buf, "%[0-9]: %[0-9](%[^)]) %[0-9](%[^)])",
                ^
             takes a digit (0 to 9)

編輯錯過了您的原始觀點。 如果您不知道要讀取的字符串有多長時間,則不能使用sscanf() 就這么簡單。 :)

scanf系列假定您知道要解析的對象數以及格式字符串中要包含的對象數。 但是,還有其他選擇。

在執行操作時,使用fgets讀取一行,但是可以對其進行標記化。 使用C函數strtok或用自己的for循環手。

但是請注意:

由於您不知道要多長時間,因此: char parts[5][11]; 不是您最好的選擇。 這將您限制為2個條目...動態地執行此操作可能會更好(讀取該行,然后分配正確的大小來存儲令牌)。

如果您真的不知道該行包含多少個數字和字母,那么為什么要讀取固定數量的數字和字母?

您可以使用fgets讀取整行,然后使用諸如strtok類的標記化工具對其進行解析,如下所示:

const char* const DELIMITERS = " ";

int i;  // index for tableStats
char* token;

token = strtok(line, DELIMITERS);

// first integer
if (token == NULL || sscanf(token, "%d:", &i) < 1)
  // error

/* it seems like you should have at least one element in your "list",
 * otherwise this is not necessary
 */

token = strtok(NULL, DELIMITERS);

if (token == NULL || sscanf(token, "%d(%[^)])",
    &(tableStats[i].connectstat[0]),
    &(tableStats[i].transitions[0])) < 2)
  // error

// read optional part
for (int j = 1; (token = strtok(NULL, DELIMITERS)) != NULL; ++j)      
  if (sscanf(token, "%d(%[^)])", &(tableStats[i].connectstat[j]),
      &(tableStats[i].transitions[j])) < 3)
    break;

請記住, strtok更改字符串,如果仍然需要,請對其進行復制。

顯然,代碼是針對任意長行的,閱讀前兩行是微不足道的。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM