读取Txt文件语言C.

时间:2012-12-20 13:17:38

标签: c file text

大家好我有这个文件结构:

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

2 个答案:

答案 0 :(得分: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个条目...可能最好动态地这样做(读取行然后分配正确的大小来存储你的令牌。)

答案 1 :(得分: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会更改字符串,如果您仍需要,请复制该字符串。

很可能代码是针对任意长行的,读取前两行是微不足道的。