我有一个读取格式化文件的函数。它看起来像这样:
1;Name_of_the_author;The date when the quote was published;The author of the quote;The quote
2;Name_of_the_author_2;The date when the second quote was published;The author of the second quote;The second quote
所以,分隔符是; 。我要做的是检查每个序列/令牌并检查它是否正确。然而问题是它没有获得所有令牌,只是前三个,它刚刚破坏的日期,它没有通过...这是附加的代码功能。忽略评论,这是一个学校项目,评论是罗马尼亚语。
int svnCheckDb()
{
FILE *file;
int k, p, i=2, m, j=0;
char mystring[1000000], *var, *var2, *string;
file = fopen("db.txt", "r"); //deschidem fisierul
if(file == NULL) {
return 0;
}
else {
//il putem accesa.
while(fgets(mystring, 1000000, file) ) {
if(j != 0)
{
//nu luam si prima linie cu descrierea repo-ului, prelucram doar citatele, j-ul numara randul pe care suntem
//separam cu strtok linia citita si verificam fiecare informatie in parte pentru a fi corecta
var = strtok(mystring, ";");
k=1;
/*
k numara string-urile citite din descrierea citatelor tocmai citita. Primul e numarul de ordine, al doilea e utilizatorul
care a adaugat citatul, al treilea reprezinta data adaugarii citatului, dupa care urmeaza citatul.
*/
while(var != NULL) {
printf("k is %d and var is %s \n", k, var);
switch(k)
{
case 1:
//numarul de ordine. Daca e 0, inseamna ca nu e numar, returnam false
i = atoi(var);
if(i == 0)
return 0;
break;
case 2:
//utilizatorul care a adaugat citatul. Daca e gol sau nu e format doar din caractere a-z A-Z, returnam false
for( m = 0; m < strlen(var); m++ )
if(!isalpha(var[m]))
return 0;
break;
case 3:
//data la care a fost adaugat citatul. Intrucat folosim formatul DD MM YY cu spatii intre ele, vom verifica daca e ok in fisier
string = var;
var2 = strtok(string, " ");
p=1; //folosim p sa vedem daca am ajuns la zi, luna sau an
while(var2 != NULL)
{
switch(p)
{
case 1:
//ziua
i = atoi(var2);
if(i == 0)
return 0;
else if(i > 31 || i < 1)
return 0;
break;
case 2:
//luna, care e formata din primele 3 caractere ale lunii si trebuie sa respecte formatul acesta
if( strlen(var2) == 3)
{
for( m = 0; m < strlen(var2); m++ )
if(!isalpha(var2[m]))
return 0;
}
else return 0;
break;
case 3:
//anul.
i = atoi(var2);
if(i == 0)
return 0;
break;
}
var2 = strtok(NULL, " ");
p++;
}
break;
case 4:
//cine a adaugat citatul, vom folosi functia searchAuthor dupa ce va fi gata.
for( m = 0; m < strlen(var); m++ )
if(!isalpha(var[m]))
return 0;
break;
case 5:
//citatul
if(strlen(var) == 0)
return 0;
printf("%d x \n", strlen(var));
}
var = strtok(NULL, ";"); //trecem la urmatorul sir de car separat de ;
k++;
}
}
j++; //trecem la urmatoarea linie
}
}
return 1;
}
k只得到3,所以它只得到数字,作者和日期。没有引用也没有作者。所以我无法检查它们,看看它是否真的
答案 0 :(得分:3)
下面:
string = var;
var2 = strtok(string, " ");
你遇到了麻烦。 strtok
忘记它曾经有一个更长的字符串标记,现在所有它记住的是它先前返回的部分。您可以使用strtok_r
同时标记不同的字符串。阅读手册页了解更多详情。
如果strtok_r
不可用,在您的情况下,这将是case 3
中内部循环中不使用strtok
进行解析的最简单方法。由于预期格式是严格的,因此按顺序检查三个字段并不复杂。如果你敢,你也可以存储strtok
插入缓冲区的'\ 0'字节的位置,并在内循环之后,根据需要用''或';'替换它们,并输入重新修改的缓冲区再次转移到strtok
。但这很容易出错,我强烈反对尝试这一点。
答案 1 :(得分:1)
你可以从你的第一个循环和其他变量开始。 第一个strtok必须在循环之外,这将帮助您划分每个标记,这必须完成以便存储您想要在strtok函数中处理的缓冲区。 在确定不再需要划分主数据之前,不能重复使用strtok函数,因为如果在主要处理结束之前重复使用strtok,则重置strtok函数使用的数据。 例如:
char str[] = "hello world how are you?\n";
char *res;
// here i tell strtok the string str is the one i want to separate
res = strtok(str, " \n");
int i = 0;
// here i separate str, using the caracters space and endline as separators
while (res != null)
{
res = strtok(NULL, " \n"); // each time i pass in this part of the loop i get my new word in res
++i; // here the variable i represents the number of times i enter the loop
}
// here i can use again strtok with another string
如果您的作业中允许使用sscanf功能,并且您似乎知道文件的确切格式,则可能需要使用它。 此外,getline函数允许您逐行获取文件,并且您可以一次处理每个句子。
答案 2 :(得分:0)
示例strtok代码,创建一个指向每个元素的指针数组strtok从大字符串中删除。
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#define MAX_SPLIT 10
void split(char **result, char *working, const char *delim)
{
int i;
char *p=strtok(working, delim);
for(i=0; p!=NULL && i<MAX_SPLIT; p=strtok(NULL, delim), i++ )
{
result[i]=p;
result[i+1]=NULL;
}
}
int foo(const char *splitme, const char *delim)
{
int retval=0;
char *result[MAX_SPLIT]={NULL};
char *working=strdup(splitme);
int i=0;
if(working!=NULL)
{
split(result, working, delim);
retval=1;
while(result[i]!=NULL)
printf("%s\n", result[i++]);
free(working);
}
return retval;
}