Domanda La funzione strtok!

Spown79

Utente Iron
21 Luglio 2023
5
2
1
5
Salve devo svolgere un esercizio per esame universitario!
Sono arrivato al punto in cui devo associare una sequenza di numeri, digitati dall'utente, ad un file che contiene una serie di parole su più righe.
Alla fine, la sequenza di numeri inserita dall'utente, deve restituire un frase nascosta prelevata dalle parole contenute nel file!
Vi posto il codice intero...


C:
#include <stdio.h>
#include <string.h>
#include <stdlib.h>

#define DELIM " ,;.:\"'-?!@_"

int main() {
    char word[100];
    char *res;
    char *token;
    int num_word = 0;
        
    FILE *f_in = fopen("Test.txt", "r");
    if(f_in == NULL) {
        perror("\n The file could not be opened!\n");
        exit(1);
    }
    
    [B]printf("\n * The text in the file * \n");
    printf(" ************************\n");
    while(!feof(f_in)) {
        res = fgets(word, 100, f_in);
        if(res == NULL) {
            perror("\n The file is empty!\n");
        }
        else {
            token = strtok(word, DELIM);
            while(token) {
                num_word++;
                printf(" %s ", token);
                token = strtok(NULL, DELIM);
            }
            printf(" Number word is: %d \n", num_word);
        }
    }[/B]
      
    fclose(f_in);
    
    printf("\n\n The end of run!");
    return 0;
}

Mi sono bloccato a questo punto: leggo tutte le stringhe dal file...ma ora come a faccio, ad esempio, a prelevare la parola 1 del rigo 1, oppure la parola 3 del rigo 2?
 
Ultima modifica:
Non c'è bisogno di usare strtok, puoi fare una cosa del genere:
C:
#include <stdio.h>

int main() {
  char words[1024][32];
  FILE *fp = fopen("Test.txt", "r");

  if (fp == NULL) {
    perror("The file could not be opened!\n");
    return 1;
  }

  int n;
  for (n = 0; fscanf(fp, "%s", words[n]) != EOF; n++)
    printf("words[%d] = %s\n", n, words[n]);

  printf("\nThere are %d words\n", n);

  fclose(fp);
  return 0;
}

Quando fai words[k] accedi alla k-esima parola.
 
Ultima modifica:
Non c'è bisogno di usare strtok, puoi fare una cosa del genere:
C:
#include <stdio.h>

int main() {
  char words[1024][32];
  FILE *fp = fopen("Test.txt", "r");

  if (fp == NULL) {
    perror("The file could not be opened!\n");
    return 1;
  }

  int n;
  for (n = 0; fscanf(fp, "%s", words[n]) != EOF; n++)
    printf("words[%d] = %s\n", n, words[n]);

  printf("\nThere are %d words\n", n);

  fclose(fp);
  return 0;
}

Quando fai words[k] accedi alla k-esima parola.
Perfetto grazie, ora provo a completarlo...
Messaggio unito automaticamente:

Ho aggiunto la parte che mi mancava...questo il codice:
C:
#include <stdio.h>
#include <string.h>

int main() {
    char words[100][8];
    FILE *fp = fopen("Test.txt", "r");

    if (fp == NULL) {
        perror("The file could not be opened!\n");
        return 1;
    }
    
    int mess[4];
    int i;
    for(i = 0; i < 4; i++) {
        printf("\n Digit a numer: ");
        scanf("%d", &mess[i]);
    }
    
    printf("\n The vector --> ");
    for(i = 0; i < 4; i++) {
        printf(" %d ", mess[i]);
    }
    printf("\n");
    int n;
    for(n = 0; fscanf(fp, "%s", words[n]) != EOF; n++) {
        for(i = 0; i < 4; i++) {
            if(n == mess[i]) {
                printf(" %s ", words[n]);
            }
        }
        //printf(" Word[%d] = %s\n", n, words[n]);
    }

    fclose(fp);
    
    printf( "\n Type \"ENTER\" to exit the programm... " );
    getchar();
    return 0;
}

Mi stampa le parole del file indicate dai numeri inseriti dall'utente...
Il problema, che proverò a risolvere nel pomeriggio, è che devo dividere il contenuto del file in righe...
e quindi prelevare una parola per ogni rigo!
Vorrei solo suggerimenti non il codice, così da provarci prima di avere la soluzione...
Grazie mille per i preziosi consigli!
 
Il problema, che proverò a risolvere nel pomeriggio, è che devo dividere il contenuto del file in righe...
e quindi prelevare una parola per ogni rigo!
Se il file ha esattamente N parole su ogni riga, come penso che sia, il problema si risolve in un attimo con word[x * N + y].

Altrimenti hai ragione a parlare di strtok perché il problema è molto più complicato. Potresti fare tutto con strtok oppure usare fgets per dividere in righe e strtok per dividere ogni riga in colonne. Ti mostro una delle due soluzioni, almeno vedi anche come si usa strtok, ma secondo me non ne hai bisogno perché il tuo file ha un numero prefissato di parole per ogni riga.
C:
#include <stdio.h>
#include <string.h>

int main() {
  int count[1024];      // count the number of words for each line
  char *word[1024][32]; // max 1024 lines and 32 words per line

  char file[1 << 20];   // max 1MB
  FILE *fp = fopen("file.txt", "r");
  fread(file, sizeof(char), 1 << 20, fp);
  fclose(fp);

  int lines = 0;
  for (char *p = strtok(file, "\n"); p != NULL; p = strtok(NULL, "\n"))
    word[lines++][0] = p;

  for (int i = 0; i < lines; i++) {
    count[i] = 0;
    for (char *p = strtok(word[i][0], " "); p != NULL; p = strtok(NULL, " "))
      word[i][count[i]++] = p;
  }

  for (int i = 0; i < lines; i++)
    for (int j = 0; j < count[i]; j++)
      printf("word[%d][%d] = %s\n", i, j, word[i][j]);

  return 0;
}
 
  • Mi piace
Reazioni: --- Ra ---
Ultima modifica:
In realtà la dimensione delle righe è fissa, così come anche le parole per ogni riga all'interno del file...
La traccia infatti mi dice solo di estrapolare un messaggio segreto da una serie di numeri immessi dall'utente...
pertanto l'unica variabile che cambia è l'immissione dei numeri...
Quindi forse potrei evitare di usare strtok...
Messaggio unito automaticamente:

dovrei confrontare il numero di una parola per riga con il valore singolo inserito dall'utente (che poi è l'unica cosa che può cambiare), solo che non riesco a fare bene il confronto

Posto solo la porzione di codice incriminata:
C:
for (n = 1; fscanf(f_in, "%s", words[n]) != EOF; n++) {
        for(i = 0; i <= DIM2; i++) {
            if(v[n] == v[i])
                printf(" words[%d] = %s\n", n, words[n]);
        }
    }

Praticamente mi restituisce solo le prime parole, come è giusto che sia, ma non è quello che voglio!!!
 
Immagino che non hai ben capito il consiglio che ti ho dato nell'ultimo messaggio.
Se tutte le righe hanno esattamente 5 parole, ti basta fare una cosa del genere:
C:
#include <stdio.h>

int main() {
  char words[1024][32];

  // apri il file
  FILE *fp = fopen("file.txt", "r");
  if (fp == NULL) {
    perror("The file could not be opened!\n");
    return 1;
  }

  // leggi il file
  int n = 0;
  while (fscanf(fp, "%s", words[n]) != EOF) n++;
  fclose(fp);

  // chiedi le coordinate
  while (1) {
    int x, y;
    printf("Insert the coordinates: ");
    scanf("%d %d", &x, &y);
    printf("%s\n", words[x * 5 + y]);   // stampa la y-esima parola della riga x
  }

  return 0;
}
Nota che è esattamente il codice che ho postato nel mio primo post. Ho solo aggiunto un ciclo while che ti chiede all'utente di inserire riga e colonna, poi ho usato words[x * N + y] come ti ho suggerito nel mio secondo post. Puoi provarlo usando questo file.txt:
Codice:
a0 a1 a2 a3 a4
b0 b1 b2 b3 b4
c0 c1 c2 c3 c4
d0 d1 d2 d3 d4
e0 e1 e2 e3 e4
f0 f1 f2 f3 f4
g0 g1 g2 g3 g4
h0 h1 h2 h3 h4
i0 i1 i2 i3 i4
j0 j1 j2 j3 j4
k0 k1 k2 k3 k4
l0 l1 l2 l3 l4
m0 m1 m2 m3 m4
n0 n1 n2 n3 n4
o0 o1 o2 o3 o4
p0 p1 p2 p3 p4
q0 q1 q2 q3 q4
r0 r1 r2 r3 r4
s0 s1 s2 s3 s4
t0 t1 t2 t3 t4
u0 u1 u2 u3 u4
v0 v1 v2 v3 v4
w0 w1 w2 w3 w4
x0 x1 x2 x3 x4
y0 y1 y2 y3 y4
z0 z1 z2 z3 z4
Questo è un esempio di esecuzione:
Codice:
Insert the coordinates: 12 3
m3
Insert the coordinates: 20 2
u2
Insert the coordinates: 0 0
a0
Insert the coordinates: 14 1
o1
Insert the coordinates: 16 4
q4
Se non ti è chiaro come funziona, te lo posso spiegare.


Posto solo la porzione di codice incriminata:
C:
for (n = 1; fscanf(f_in, "%s", words[n]) != EOF; n++) {
for(i = 0; i <= DIM2; i++) {
if(v[n] == v[i])
printf(" words[%d] = %s\n", n, words[n]);
}
}
Praticamente mi restituisce solo le prime parole, come è giusto che sia, ma non è quello che voglio!!!
Questa cosa qui, se opportunamente modificata, va bene solo se le richieste sono in ordine: se io ti chiedo di dirmi la terza parola nella riga 100 e poi ti chiedo di dirmi la seconda parola nella riga 5, il tuo codice non va bene. Per farlo funzionare con il controllo messo dentro il ciclo che usa la fscanf dovresti chiudere e riaprire il file (o usare fseek o rewind) per ogni parola che vai a stampare.

Non ho in mano il testo del tuo esercizio e l'input con le coordinate ma, dalle informazioni che mi hai dato, io leggerei tutto il file e lo salverei in un array. Dopo che hai ogni parola accessibile attraverso un array, puoi prendere in input le coordinate e interrogare direttamente l'array.
 
  • Mi piace
Reazioni: nullptr