2012-12-20 148 views
0

傢伙您好我有這個文件的結構:閱讀TXT文件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 
+3

嘗試使用'fscanf' ... –

+0

我已經做了,但問題是,它遇到碰撞時,:(字符..我只想數字和字母,我想把每個值1結構 – devish

+4

請顯示您的代碼請。 – Nocturno

回答

1

我看到的第一個問題是你覆蓋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項...可能它會更好地做到這一點動態(讀取行,然後分配正確的大小來存儲您的令牌英寸)

+0

謝謝你..是啊,這是正確的b我不知道每條線的大小...我需要多少個參數...我可以有1行0:1(ab)5(b)或0:1(ab )5(b)9(ba)...在例子4中:5(ab)給我錯誤,因爲它只有3個參數而不是5個其他參數 – devish

+0

@devish - 所以沒有跡象?該行可以只是它想要的那麼多的num(char)集合? – Mike

+0

是/ sry,我真的很喜歡你的答案..只是在第一線(0)我知道它的唯一號碼 – devish

0

如果你真的不知道該行將包含多少數字和字母,爲什麼你閱讀固定數量的數字和字母?

你可以閱讀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改變字符串,做它的一個副本,如果你仍然需要它。

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

+0

謝謝,如何設置分隔符? – devish

+0

@devish對不起,把它丟在複製/粘貼中,補充說。這就是你們之間的關係。 – effeffe

+0

所以我對這個例子我const char * const DELIMITERS =「:,(,)」; ..但似乎不工作 – devish