2012-12-20 149 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