2009-09-08 6 views
3

Je souhaite lire les nombres hexadécimaux d'un fichier texte dans un entier non signé afin de pouvoir exécuter des instructions Machine. C'est juste une chose de type simulation qui regarde à l'intérieur du fichier texte et en fonction des valeurs et de l'instruction correspondante sort les nouvelles valeurs dans les registres.Comment lire les nombres hexadécimaux dans un int non signé C

Par exemple, les instructions seraient:

  • 1RXY -> Enregistrer registre d'adresse mémoire R avec la valeur dans XY
  • 2RXY -> Enregistrer le registre R avec la valeur XY
  • BRXY -> Jump pour enregistrer R si xy est ceci et cela, etc ..
  • ARXY -> et le registre R avec valeur à adresse mémoire XY

Le fichier texte contient quelque chose comme ceci dans une nouvelle ligne. (En hexadécimal)

  • 120F
  • B007
  • 290B

Mon problème est la copie de chaque instruction individuelle dans un entier non signé ... Comment puis-je faire?

#include <stdio.h> 
int main(){ 
    FILE *f; 
    unsigned int num[80]; 

    f=fopen("values.txt","r"); 
    if (f==NULL){ 
     printf("file doesnt exist?!"); 
    } 

    int i=0; 
    while (fscanf(f,"%x",num[i]) != EOF){ 
     fscanf(f,"%x",num[i]); 
     i++; 
    } 
    fclose(f); 
    printf("%x",num[0]); 
} 
+0

Est-ce CHIP8? (15 caractères) – LiraNuna

Répondre

4

Vous êtes sur la bonne voie. Voici les problèmes que j'ai vu:

  • Vous devez quitter si fopen() retour NULL - vous imprimez un message d'erreur mais continue.
  • Votre boucle devrait se terminer si i >= 80, de sorte que vous ne lisiez pas plus d'entiers que vous n'avez d'espace.
  • Vous devez transmettre l'adresse de num[i], et non la valeur, à fscanf.
  • Vous appelez fscanf() deux fois dans la boucle, ce qui signifie que vous jetez la moitié de vos valeurs sans les stocker.

Voici ce qu'il ressemble à ces questions fixes:

#include <stdio.h> 

int main() { 
    FILE *f; 
    unsigned int num[80]; 
    int i=0; 
    int rv; 
    int num_values; 

    f=fopen("values.txt","r"); 
    if (f==NULL){ 
     printf("file doesnt exist?!\n"); 
     return 1; 
    } 

    while (i < 80) { 
     rv = fscanf(f, "%x", &num[i]); 

     if (rv != 1) 
      break; 

     i++; 
    } 
    fclose(f); 
    num_values = i; 

    if (i >= 80) 
    { 
     printf("Warning: Stopped reading input due to input too long.\n"); 
    } 
    else if (rv != EOF) 
    { 
     printf("Warning: Stopped reading input due to bad value.\n"); 
    } 
    else 
    { 
     printf("Reached end of input.\n"); 
    } 

    printf("Successfully read %d values:\n", num_values); 
    for (i = 0; i < num_values; i++) 
    { 
     printf("\t%x\n", num[i]); 
    } 

    return 0 
} 
+0

+1 J'aurais déclaré 'rv' comme local dans la boucle dans laquelle vous l'utilisez, mais ce n'est pas vraiment grave. –

+1

Avoir 'rv' disponible en dehors de la boucle pour vous permettre de faire la distinction entre un échec de correspondance et un échec de lecture/EOF. – caf

2

Dans ce cas, l'ensemble de votre entrée est hex majuscules pendant que vous essayez de lire hex minuscules . Pour résoudre ce problème, remplacez %x par %X.

+0

% je ne lirai hexadécimal que s'il a un préfixe 0x dessus ... –

+2

Ou vous pouvez utiliser 'strtol()' qui a un contrôle arbitraire sur la base que vous voulez, et pourrait être légèrement plus rapide car il n'a pas à analyser une chaîne de format. Pas que j'ai une tendance naturelle à écarter de 'scanf()' et 'printf()' juste à cause de la légère surcharge nécessaire pour analyser la chaîne de format ou quoi que ce soit ... –

+0

Chris: Vous avez raison, mon mauvais! J'ai oublié pourquoi je le pensais ... édité. – LiraNuna

2

Vous lisez deux chiffres dans chaque élément de votre tableau (si vous perdez la moitié d'entre eux comme vous les écrasez. Essayez d'utiliser simplement

while (i < 80 && fscanf(f,"%x",&num[i]) != EOF) 
    i++; 

pour votre boucle

modifier

Il vous manque également le '&' pour obtenir l'adresse de l'élément de tableau, donc vous passez un pointeur de poubelle aléatoire à scanf et vous vous écrasez probablement.L'option -Wall est votre ami

0

Voulez-vous que chacune des lignes (chacune de 4 caractères) soit séparée en 4 éléments de tableau différents? Si vous le faites, je vais essayer ceci:

/* read the line */ 
/* fgets(buf, ...) */ 

/* check it's correct, mind the '\n' */ 
/* ... strlen ... isxdigit ... */ 

/* put each separate input digit in a separate array member */ 
num[i++] = convert_xdigit_to_int(buf[j++]); 

Lorsque la fonction convert_xdigit_to_int() convertit simplement '0' (le caractère) à 0 (un entier), '1' 1, '2' à 2 , ... '9' à 9, 'a' ou 'A' à 10, ...

Bien sûr, ce pseudo-code se trouve dans une boucle qui s'exécute jusqu'à ce que le fichier soit épuisé ou que le tableau soit rempli.Peut-être mettre les fgets() comme condition pendant un certain temps (...)

while(/*there is space in the array && */ fgets(...)) { 
} 
4

Vous pouvez également utiliser la fonction strtol(). Si vous utilisez une base de 16, votre valeur de chaîne hexadécimale sera convertie en int/long.

errno = 0; 
my_int = strtol(my_str, NULL, 16); 
/* check errno */ 

Edit: Une autre note, divers outils d'analyse statique peut les choses comme drapeau atoi() et scanf() comme dangereux. atoi est obsolète en raison du fait qu'il ne vérifie pas les erreurs comme strtol(). En revanche, scanf() peut faire un débordement de tampon car il ne vérifie pas le type envoyé dans scanf(). Par exemple, vous pouvez donner un pointeur sur un raccourci vers scanf où la valeur lue est en fait longue .... et boom.

+1

Vous ne voyez pas pourquoi vous devez mettre 'errno' à zéro ... –

+0

C'est parce que si' strtol' réussit, il ne changera pas 'errno', et vous devez vérifier dans ce cas s'il existe un' ERANGE' erreur d'une conversion réussie qui a abouti à 'LONG_MAX' ou' LONG_MIN'. – caf

+0

Il est recommandé de mettre à zéro zéro avant un appel de fonction si vous envisagez de le vérifier immédiatement après l'appel. La valeur de errno peut avoir changé par d'autres moyens avant cet appel. – John

Questions connexes