2015-04-10 1 views
1

J'ai été en train de tourner mes roues pendant un certain temps à essayer de comprendre cela, mais n'a pas pu. J'espère que vous pouvez aider!Parse fichier texte dans C - Passer les lignes - Calcul répété

Je travaille actuellement sur un programme qui permet de résoudre Sudoku. Le code actuel que je montre ci-dessous prend en entrée une grille d'entiers 9x9 (le puzzle du Sudoku) et génère ensuite une solution. Cela fonctionne bien.

#include <stdio.h> 

int isAvailable(int puzzle[][9], int row, int col, int num) 
{ 
    int rowStart = (row/3) * 3; 
    int colStart = (col/3) * 3; 
    int i, j; 

    for(i=0; i<9; ++i) 
    { 
     if (puzzle[row][i] == num) return 0; 
     if (puzzle[i][col] == num) return 0; 
     if (puzzle[rowStart + (i%3)][colStart + (i/3)] == num) return 0; 
    } 
    return 1; 
} 

int fillSudoku(int puzzle[][9], int row, int col) 
{ 
    int i; 
    if(row<9 && col<9) 
    { 
     if(puzzle[row][col] != 0) 
     { 
      if((col+1)<9) return fillSudoku(puzzle, row, col+1); 
      else if((row+1)<9) return fillSudoku(puzzle, row+1, 0); 
      else return 1; 
     } 
     else 
     { 
      for(i=0; i<9; ++i) 
      { 
       if(isAvailable(puzzle, row, col, i+1)) 
       { 
        puzzle[row][col] = i+1; 
        if((col+1)<9) 
        { 
         if(fillSudoku(puzzle, row, col +1)) return 1; 
         else puzzle[row][col] = 0; 
        } 
        else if((row+1)<9) 
        { 
         if(fillSudoku(puzzle, row+1, 0)) return 1; 
         else puzzle[row][col] = 0; 
        } 
        else return 1; 
       } 
      } 
     } 
     return 0; 
    } 
    else return 1; 
} 

int main() 
{ 
    int i, j; 
    int row,column; 
    int puzzle[9][9]; 
    //printf("Enter your input:\n"); 
    for (row=0; row <9; row++){ 
     for(column = 0; column <9; column ++){ 
     scanf("%d",&puzzle[row][column]); 
     } 
    } 

    //PRINT INPUT PUZZLE 
    printf("Original Puzzle:"); 
    printf("\n+-----+-----+-----+\n"); 
    for(i=1; i<10; ++i) 
    { 
     for(j=1; j<10; ++j) printf("|%d", puzzle[i-1][j-1]); 
     printf("|\n"); 
     if (i%3 == 0) printf("+-----+-----+-----+\n"); 
    } 
    printf("\n"); 


    //PRINT OUTPUT PUZZLE 
    printf("Solved Puzzle:"); 
    if(fillSudoku(puzzle, 0, 0)) 
    { 
     printf("\n+-----+-----+-----+\n"); 
     for(i=1; i<10; ++i) 
     { 
      for(j=1; j<10; ++j) printf("|%d", puzzle[i-1][j-1]); 
      printf("|\n"); 
      if (i%3 == 0) printf("+-----+-----+-----+\n"); 
     } 
     printf("\n"); 
    } 

    else printf("\n\nNO SOLUTION\n\n"); 

    return 0; 
} 

Je veux maintenant utiliser un fichier texte à partir du projet Euler (https://projecteuler.net/project/resources/p096_sudoku.txt) et que mon programme génère tous les 50 de ces solutions. Le fichier texte a le format suivant:

Grid 01 
003020600 
900305001 
001806400 
008102900 
700000008 
006708200 
002609500 
800203009 
005010300 
Grid 02 
200080300 
060070084 
030500209 
000105408 
000000000 
402706000 
301007040 
720040060 
004010003 
... 

et ainsi de suite pour 50 grilles totales.

Ma question est: Quelle est la meilleure façon d'analyser dans ce fichier

  1. Passer sur la « Grille ## » ligne
  2. Lire dans les 9 lignes suivantes pour l'entrée
  3. Continuer sur le fichier pour répéter le programme jusqu'à la fin du fichier

EDIT: Entre les étapes 2 & 3, c'est ce qui se passerait: Après avoir lu dans 9 lignes de nombres, je vais l'utiliser comme entrée pour le programme et exécuter le programme et générer une solution, puis revenir au fichier d'entrée et obtenir le prochain ensemble de nombres et exécuter une autre itération de le programme.

Merci pour toute entrée et les conseils que vous pouvez me fournir! -Colton

+0

Sudoku utilise généralement des * nombres * comme symboles, tandis que le séparateur semble commencer par un caractère. Je recommanderais 'isalpha()' et 'isdigit()'. – EOF

+0

@EOF: Mais si le fichier a un format fixe/régulier (comme cela semble), ce que OP propose sera bien. –

+0

@ScottHunter: L'approche pour résoudre ce problème me semble assez claire. Ce dont je ne suis pas sûr, c'est un moyen simple d'analyser ce fichier au format fixe pour obtenir les entrées dont j'ai besoin pour le programme à chaque itération. –

Répondre

1

Lorsque les données dans un fichier texte sont la ligne formatée, recommande fortement d'utiliser fgets().

considérer chaque groupe de 10 lignes comme un enregistrement. Ils appartiennent ensemble, si une partie est dans l'erreur, le groupe entier est invalide.

// return 0 on success, -1 on EOF and 1 on format failure 
int ReadPuzzle(FILE *inf, int puzzle[][9], int *Grid) { 
    char buffer[20]; // About 2x expected need 

    if (fgets(buffer, sizeof buffer, inf) == NULL) 
    return -1; // File EOF or IO error occurred. 
    if (sscanf(buffer, "Grid %d", Grid) != 1) 
    return 1; 

    for (int row = 0; row < 9; row++) { 
    if (fgets(buffer, sizeof buffer, inf) == NULL) 
     return 1; // If Grid line exists, 9 lines _should_ follow 
    char *p = buffer; 
    for (int col = 0; col < 9; col++) { 
     // Use %1d to limit scanning to 1 digit 
     if (sscanf(p, "%1d", &puzzle[row][col]) != 1) 
     return 1; 
     p++; 
    } 
    } 
    return 0; 
} 

Des contrôles pourraient être ajoutés pour s'assurer que des données supplémentaires ne sont pas sur les lignes.

+0

Merci pour la panne! En regardant la fonction principale pour implémenter la fonction ReadPuzzle que vous avez créée, au lieu d'appeler le scanf à l'intérieur des boucles for imbriquées, devrais-je simplement déclarer quelques variables supplémentaires pour passer en arguments, puis passer un appel à ReadPuzzle en utilisant ceux? Aussi, aurais-je besoin de mettre en place une boucle supplémentaire pour continuer à analyser le fichier jusqu'à ce qu'il atteigne EOF? –

+0

@Colton Rudd Oui, vous avez la bonne idée. Appelez 'ReadPuzzle()' après avoir ouvert le fichier pour obtenir 1 puzzle. Si la valeur de retour est 0, le succès! Sinon, la valeur de retour <0 et vous avez terminé. Si la valeur de retour est> 0, quelque chose ne va pas dans le fichier ou le code. – chux

0

Vous voulez probablement faire quelques trucs entre les étapes 2 & 3, mais ce que vous contentez semble raisonnable.

+0

Après avoir lu dans 9 lignes de nombres, je vais utiliser cela comme une entrée pour le programme et exécuter le programme et générer une solution, puis revenir au fichier d'entrée et obtenir le prochain ensemble de nombres et exécuter une autre itération de le programme. C'est ce que je dirais entre 2 et 3 si cela a du sens. –

+0

@ColtonRudd: Fait parfaitement sens; vous ne l'avez pas dit au départ. –

+0

Je vais revenir en arrière et éditer et faire la clarification. Je vous remercie! –