Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/c/61.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
用C语言读取Txt文件_C_File_Text - Fatal编程技术网

用C语言读取Txt文件

用C语言读取Txt文件,c,file,text,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_

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

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

我看到的第一个问题是您正在覆盖统计数据:

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()
将读取换行符。这意味着,当您在while循环中从读取第二个
stats\u final
转到第一个读取时,您的第一个输入将只是剩下的换行符。这没什么大不了的,因为你检查了“无效输入”,但值得注意

最后,在我看来,你的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循环

但有一点值得注意:


因为你不知道它有多长,所以这个:
charparts[5][11]不是您的最佳选择。这将您限制为2个条目。。。可能最好是动态执行此操作(读取该行,然后分配正确的大小来存储令牌)。

如果您真的不知道该行将包含多少数字和字母,为什么要读取固定数量的数字和字母

您可以使用
fgets
读取整行代码,然后使用标记器对其进行解析,如下所示:

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;
const char*const DELIMITERS=“”;
int i;//表状态的索引
字符*令牌;
token=strtok(行、分隔符);
//第一个整数
如果(令牌==NULL | | sscanf(令牌,“%d:”,&i)<1)
//错误
/*看起来你的“列表”中至少应该有一个元素,
*否则这是不必要的
*/
token=strtok(空,分隔符);
如果(令牌==NULL | | sscanf(令牌,“%d”(%[^)])”,
&(tableStats[i].connectstat[0]),
&(表状态[i]。转换[0]))<2)
//错误
//阅读可选部分
for(int j=1;(token=strtok(NULL,分隔符))!=NULL;++j)
如果(sscanf(token,“%d(%[^)])”,&(tableStats[i].connectstat[j]),
&(表状态[i].转换[j])<3)
打破
请记住,
strtok
更改字符串,如果仍然需要,请复制它


显然,代码是针对任意长的行的,读取前两行很简单。

我已经这样做了,但问题是遇到以下情况时它会崩溃:,(字符..我只需要数字和字母,我想把每个值都放在1上struct@user1918863欢迎来到Stack Overflow。请;您的问题是用HTML格式的,而不是在这里如何完成的。如果您想填充结构,发布其定义可能会很有帮助。至少是重要的一部分。世界末日即将到来,人们仍在等待试图读取和解析纯C格式的文本文件…嗯。@maverik我理解你们,但这是我需要的谢谢你们…是的,这是正确的,但主要问题是我不知道每行的大小…我需要取多少个参数…我可以有一行0:1(ab)5(b)或0:1(ab)5(b)9(ba)…在示例4:5(ab)中因为它只有3个参数而不是5个lke,所以给我错误others@devish-所以没有指示?行可以是它想要的任意多组num(char)?是:/sry,我非常喜欢你的答案..只在第一行(0)我知道它只有1个数字,我可以做一个绑定的1-10个梨线…那部分东西只是为了测试,然后我就在结构上做谢谢你,如何设置分隔符?@devish抱歉,在复制/粘贴中丢失了它,补充道。这正是行中元素之间的关系。所以我在这个示例中使用了我的const char*const Delimiters=“:,(,)”但似乎不是work@devish不,
分隔符
应该是
。这是介于
1(ab)
5(b)
之间的字符。我只是想让代码更一般一些。