2017-07-03 3 views
2

Je rencontre un problème avec l'utilisation de getline/fgets. J'essaie de lire à partir de stdin tout en piping l'entrée d'un fichier, puis le traiter. Bien que ça marche très bien avec gcc 4.8.5 sur opensuse, ça ne marche pas sur Arch Linux avec gcc 7 et sur le dernier ubuntu avec gcc 5. Ce dernier va simplement sauter quelques lignes d'entrée. (Je passe le même fichier). Dans l'exemple, mon programme sauterait la troisième et la quatrième ligne lorsqu'il est passé mais pas lorsqu'il est entré manuellement. Même chose avec des fichiers plus gros que toujours les mêmes lignes sont ignorées. Des pensées? Très appréciée. Je vous remercie.C fgets et entrée de saut getline de stdin

L'entrée est de la forme (chaque ligne est suivie d'un saut de ligne):

0 1 2 
2 3 4 
3 4 5 
2 4 5 
1 2 3 
1 
2 
3 

Mon code ressemble à ceci:

int main(int argc, char *argv[]) { 

int bytes; 
size_t nbytes = 100; 
char *str = (char *) malloc(nbytes+1); // 1 byte for \0 
long i = 0; 
node *itemArray = malloc(sizeof(itemArray)); 

while ((bytes = getline(&str, &nbytes, stdin) != -1)) { 
    char* token; 
    char *rest = str; 
    int callNums = 0; 
    long from = 0; 
    long to = 0; 
    long weight = 0; 

    while((token = strtok_r(rest, " ", &rest))) { 
     if(callNums == 0) { 
      from = atol(token); 
        } 
     if(callNums == 1) to = atol(token); 
     if(callNums == 2) weight = atol(token); 
     callNums++; 
    } 

    if(callNums == 3) { 
     if(i == 0) { 
      itemArray[i].from = from; 
      itemArray[i].to = to; 
      itemArray[i].weight = weight; 
      printf("%li %li %li \n", itemArray[i].from, itemArray[i].to, itemArray[i].weight); 
     } 

     if(i > 0) { 
      node *tmp = realloc(itemArray, (i * sizeof(itemArray))); 
      if(tmp) { 
       itemArray = tmp; 
       itemArray[i].from = from; 
       itemArray[i].to = to; 
       itemArray[i].weight = weight; 
       printf("%li %li %li \n", itemArray[i].from, itemArray[i].to, itemArray[i].weight); 
      } 
      else { printf("realloc failed"); 
       exit(-1); } 
     } 
     ++i; 
    } 
    } 
    } 
    free(str); 
    free(itemArray); 
    return(0); 
} 
+0

Etes-vous sûr que cet exemple est représentatif? Je ne vois pas de 'fgets()'. – EOF

+0

J'ai changé le code de 'fgets()' en 'getline', pensant que je pourrais résoudre le problème de cette façon. Mon code saute ces deux lignes indépendamment de ce que j'utilise. J'aurais dû le mentionner. Mes excuses. – markus

+0

Et laisser 'getline' allouer de la mémoire pour moi va ajouter du contenu aléatoire où l'entrée de lecture réelle devrait être. – markus

Répondre

1

pour cette solution. En définissant itemArray sur NULL, le premier appel à realloc agit comme malloc. Définir str à NULL et nbytes à 0 devrait fonctionner correctement avec getline. Sscanf devrait fonctionner pour analyser trois longs d'une chaîne. Si trois sont analysés avec succès, ils seront ajoutés à itemarray.

int main(int argc, char *argv[]) { 

    int bytes; 
    size_t nbytes = 0; 
    char *str = NULL; 
    long i = 0; 
    node *itemArray = NULL; 

    while ((bytes = getline (&str, &nbytes, stdin) != -1)) { 
     int callNums = 0; 
     long from = 0; 
     long to = 0; 
     long weight = 0; 

     if (3 == sscanf (str, "%ld%ld%ld", &from, &to, &weight)) { 

      node *tmp = realloc (itemArray, ((i + 1) * sizeof (*tmp))); 
      if(tmp) { 
       itemArray = tmp; 
       itemArray[i].from = from; 
       itemArray[i].to = to; 
       itemArray[i].weight = weight; 
       printf ("%li %li %li \n", itemArray[i].from, itemArray[i].to, itemArray[i].weight); 
      } 
      else { 
       printf("realloc failed"); 
       exit(-1); 
      } 
      ++i; 
     } 
    } 
    free(str); 
    free(itemArray); 
    return(0); 
} 
+0

Merci beaucoup! Cela marche. – markus