我用 C 撰寫了一個決議器來決議一個描述圖形的檔案,帶有頂點和邊,圖形檔案如下所示:
c FILE: graph_test
c
c SOURCE: generator
c
p edge 10 12
e 1 2
e 2 3
e 6 2
“c”行對應注釋(必須忽略),“p”行描述節點數和邊數,nbEdges “e”后面的行描述兩個節點之間的邊。
我使用 strtok() 拆分字串以僅獲取我感興趣的值,但是當我嘗試將值存盤到陣列int edges[nb_adges][2]中時,陣列中填充了錯誤的值
這是整個代碼(“aretes” = 邊,和“sommets”:節點)
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#define TAILLE_MAX 1000
int main(int argc, char * argv[]) {
if(argc != 2) {
printf("\n[UTILISATION] : ./parseur chemin_fichier\n");
exit(1);
}
char* nom_fichier = argv[1];
FILE* fichier;
//Ouverture en lecture
fichier = fopen(nom_fichier,"r");
if(fichier == NULL) {
printf("\nImpossible d'ouvrir le fichier '%s'\n", nom_fichier);
exit(2);
}
char ligne[TAILLE_MAX];
int nb_sommets = 0;
int nb_aretes = 0;
int aretes[nb_aretes][2];
//On lit chaque ligne du fichier
int i;
while(fgets(ligne, TAILLE_MAX, fichier) != NULL) {
//Si la ligne commence par "c" c'est un commentaire on l'ignore
if(ligne[0] == 'c') {
continue;
}
//Si la ligne commence par "p" c'est la ligne qui contient le nombre de sommets et de aretes
if(ligne[0] == 'p') {
i = 0;
char* tmp = strtok(ligne, " ");
while(tmp != NULL) {
if(i == 2) {
nb_sommets = atoi(tmp);
}
if(i == 3) {
nb_aretes = atoi(tmp);
}
tmp = strtok(NULL, " ");
i ;
}
i = 0;
continue;
}
//Si la ligne commence par "e" on récupère les aretes
if(ligne[0] == 'e') {
char* tmp = strtok(ligne, " ");
int j = 0;
while(tmp != NULL) {
if(j == 1) {
aretes[i][0] = atoi(tmp);
}
if(j == 2) {
aretes[i][1] = atoi(tmp);
}
printf("tmp : %s\n",tmp);
tmp = strtok(NULL, " ");
j ;
}
i ;
continue;
}
}
printf("\nNombre de sommets : %d\n", nb_sommets);
printf("Nombre d'aretes : %d\n", nb_aretes);
printf("Liste des aretes :\n");
//On affiche toutes les aretes
for(int i = 0; i < nb_aretes; i ) {
printf("%d -> %d\n", aretes[i][0], aretes[i][1]);
}
//On ferme le fichier
fclose(fichier);
return 0;
}
我試圖在“e”回圈中列印 tmp 的值,它顯示節點的正確值,但陣列int edges[nb_edges][2]中充滿了奇怪的值
> Execution
List of edges :
1 -> 2
2 -> 3
6 -> 2
8 -> 3
3473509 -> 52
8 -> 7
9 -> 4
5 -> 6
7 -> 9
10 -> 1
1 -> 7
5 -> 4
uj5u.com熱心網友回復:
除了我的熱門評論...
這個:
int nb_aretes = 0;
int aretes[nb_aretes][2];
這是[有效地]:
int aretes[0][2];
這是因為在宣告發生時大小是固定的。如果隨后增加,則不會增加。nb_aretes
我們需要一個固定大小的陣列(例如):
#define ARETES_MAX 10000
int aretes[ARETES_MAX][2];
資料檔案不匹配。這p條線說 15 條邊,但只有 3e條線。
雖然,我 [四年,40 年前] 學習了法語,但我通過谷歌翻譯運行了你的代碼。所以,其中一些可能來自那個。
我更改了代碼以忽略該p行nb_edges并僅計算e行數:
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#define MAX_LINE 1000 // max line size
#define EDGES_MAX 10000 // max number of edges/nodes
int
main(int argc, char *argv[])
{
if (argc != 2) {
printf("\n[USAGE]: ./parser file_path\n");
exit(1);
}
char *file_name = argv[1];
FILE *file;
// Open for reading
file = fopen(file_name, "r");
if (file == NULL) {
printf("\nCould not open file '%s'\n", file_name);
exit(2);
}
char line[MAX_LINE];
int nb_vertices = 0;
// NOTE/BUG: this produces [effectively]
int nb_edges = 0;
#if 0
int edges[nb_edges][2];
#else
int counted_edges = 0;
int edges[EDGES_MAX][2];
#endif
// We read each line of the file
int i;
while (fgets(line, MAX_LINE, file) != NULL) {
// If the line begins with "c" it is a comment, we ignore it
if (line[0] == 'c') {
continue;
}
// If the line begins with "p" this is the line that contains the
// number of vertices and edges
if (line[0] == 'p') {
i = 0;
char *tmp = strtok(line, " ");
while (tmp != NULL) {
if (i == 2) {
nb_vertices = atoi(tmp);
}
if (i == 3) {
// NOTE/BUG: in the data file, this does _not_ match the number of "e" lines
nb_edges = atoi(tmp);
// NOTE/BUG: this is flagged by the compiler with -Wall
// NOTE/BUG: using [2] is UB (undefined behavior) because the max index can be
// is 1
#if 0
edges[nb_edges][2];
#endif
}
tmp = strtok(NULL, " ");
i ;
}
i = 0;
continue;
}
// If the line begins with "e" we retrieve the edges
if (line[0] == 'e') {
char *tmp = strtok(line, " ");
int j = 0;
while (tmp != NULL) {
if (j == 1) {
#if 0
edges[i][0] = atoi(tmp);
#else
edges[counted_edges][0] = atoi(tmp);
#endif
}
if (j == 2) {
#if 0
edges[i][1] = atoi(tmp);
#else
edges[counted_edges][1] = atoi(tmp);
#endif
}
printf("tmp: %s\n", tmp);
tmp = strtok(NULL, " ");
j ;
}
#if 0
i ;
#else
counted_edges;
#endif
continue;
}
}
printf("\nNumber of vertices: %d\n", nb_vertices);
printf("Number of edges: %d (expected)\n", nb_edges);
printf("Number of edges: %d (calculated)\n", counted_edges);
printf("List of edges:\n");
// We display all the edges
#if 0
for (int i = 0; i < nb_edges; i ) {
#else
for (int i = 0; i < counted_edges; i ) {
#endif
printf("%d -> %d\n", edges[i][0], edges[i][1]);
}
// We close the file
fclose(file);
return 0;
}
在上面的代碼中,我使用cpp條件來表示舊代碼和新代碼:
#if 0
// old code
#else
// new code
#endif
#if 1
// new code
#endif
注意:這可以通過運行檔案來清理unifdef -k
我使用了您的示例輸入:
c FILE: graph_test
c
c SOURCE: generator
c
p edge 10 12
e 1 2
e 2 3
e 6 2
這是程式輸出:
tmp: e
tmp: 1
tmp: 2
tmp: e
tmp: 2
tmp: 3
tmp: e
tmp: 6
tmp: 2
Number of vertices: 10
Number of edges: 12 (expected)
Number of edges: 3 (calculated)
List of edges:
1 -> 2
2 -> 3
6 -> 2
我認為代碼可以簡化。每個陳述句strtok下的呼叫復制過多。if
在決定要處理的命令之前,最好有一個分割行的回圈。
而且,aswitch/case似乎比if陳述更好。
以下是我清理東西的方法:
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#define MAX_LINE 1000 // max line size
#define EDGES_MAX 10000 // max number of edges/nodes
#if 1
#define MAX_TOKENS 10 // max tokens per line
#endif
int
main(int argc, char *argv[])
{
if (argc != 2) {
printf("\n[USAGE]: ./parser file_path\n");
exit(1);
}
char *file_name = argv[1];
FILE *file;
// Open for reading
file = fopen(file_name, "r");
if (file == NULL) {
printf("\nCould not open file '%s'\n", file_name);
exit(2);
}
char line[MAX_LINE];
char saved_line[MAX_LINE];
int nb_vertices = 0;
int nb_edges = 0;
int counted_edges = 0;
int edges[EDGES_MAX][2];
// We read each line of the file
#if 1
int ntokens;
char *tokens[MAX_TOKENS 1];
#endif
while (fgets(line, MAX_LINE, file) != NULL) {
// If the line begins with "c" [or "#"] it is a comment, we ignore it
if (line[0] == 'c')
continue;
#if 1
if (line[0] == '#')
continue;
#endif
// split line into tokens
#if 1
// copy in case of error
strcpy(saved_line,line);
char *tok = strtok(line," \n");
for (ntokens = 0; ntokens < MAX_TOKENS; ntokens) {
if (tok == NULL)
break;
tokens[ntokens] = tok;
tok = strtok(NULL," \n");
}
tokens[ntokens] = NULL;
// ignore blank lines
if (ntokens == 0)
continue;
#endif
switch (line[0]) {
case 'p':
// If the line begins with "p" this is the line that contains the
// number of vertices and edges
if (ntokens != 4) {
printf("bad p line -- ntokens=%d %s",ntokens,saved_line);
exit(1);
}
nb_vertices = atoi(tokens[2]);
nb_edges = atoi(tokens[3]);
break;
case 'e':
// If the line begins with "e" we retrieve the edges
if (ntokens != 3) {
printf("bad e line -- ntokens=%d %s",ntokens,saved_line);
exit(1);
}
edges[counted_edges][0] = atoi(tokens[1]);
edges[counted_edges][1] = atoi(tokens[2]);
counted_edges;
break;
default:
printf("unknown command -- %s",saved_line);
exit(1);
break;
}
}
printf("\nNumber of vertices: %d\n", nb_vertices);
printf("Number of edges: %d (expected)\n", nb_edges);
printf("Number of edges: %d (calculated)\n", counted_edges);
printf("List of edges:\n");
// We display all the edges
for (int i = 0; i < counted_edges; i )
printf("%d -> %d\n", edges[i][0], edges[i][1]);
// We close the file
fclose(file);
return 0;
}
我沒有在上面的代碼中執行以下操作。
但是,如果意圖是檔案頂部只有一行,我們可以 使用:p
int aretes[nb_aretes][2];
但是,我們必須p在單獨的塊中決議該定義上方的行。然后,在我們看到定義之前nb_aretes會被正確地[動態地]設定。
轉載請註明出處,本文鏈接:https://www.uj5u.com/qiye/532396.html
標籤:数组C解析斯托克
上一篇:使用boost決議日志檔案
