¿La mejor manera de obtener números de entrada?

Me gustaría hacer un bucle carácter por carácter de un archivo de entrada que tiene texto y números. Pensé que podría simplemente bucle …

char count; while( c != ' ' && c != '\n' && c != '\t' ) { count += c; c = fgetc(fp); } 

para decir obtener “11” del archivo de texto y luego usar atoi para convertir a un int, pero luego me di cuenta de que solo estaba agregando números ASCII. Soy bastante nuevo en C y, por lo que entiendo, las cadenas son solo matrices de caracteres. ¿Esto significa que tengo que poner “1” y “1” en una matriz de caracteres? ¿Pero entonces tendría que preocuparme por el tamaño del arreglo y convertirlo en un número?

Si bien parece ser la solución natural, por lo general, fscanf() uso de fscanf() en entradas potencialmente mal formadas .

Hay varios problemas con la función, entre ellos:

  • La incapacidad de recuperarse correctamente de un error (por debajo de ftell() / fseek() ), porque no se sabe exactamente dónde se detuvo la entrada de análisis.
  • La facilidad con la que lleva al uso de valores no inicializados (si el formato no coincide con la entrada y no verificó el código de retorno correctamente).
  • Algunos casos de esquina donde fscanf() ahoga en la entrada donde atoi() / strtol() no ( “0xz” …).

Todo esto relega a fscanf() para leer solo entradas bien formateadas , es decir, cosas que su propio progtwig había escrito anteriormente en un formato conocido.

Para cualquier tipo de entrada que no esté en el formato esperado, recomiendo leer una línea a la vez ( fgets() ) y analizarla en la memoria , por ejemplo con strtol() :

 #include  #include  #include  #define LINE_BUFFER_SIZE 256; // ... char line[ LINE_BUFFER_SIZE ]; fgets( line, LINE_BUFFER_SIZE, fp ); char * scanptr; errno = 0; long number = strtol( line, &scanptr, 0 ); if ( scanptr == line ) { // not a number... } 
  • scanptr ahora apunta a donde terminó el análisis de números.
  • number contiene el número analizado, 0 si la línea no comenzó con un número, y LONG_MAX resp. LONG_MIN si el número encontrado está fuera de long scope (en cuyo caso errno == ERANGE también).

No sé cuáles son sus requisitos exactos, por lo que no puedo dar un buen ejemplo de qué hacer si no encuentra un número o qué hacer con el texto. Pero ya que tiene la línea (o, los primeros caracteres LINE_BUFFER_SIZE de una línea más larga …) en la memoria, tiene toda la gama de funciones de cadena a su disposición. strpbrk( line, "0123456789" ) se puede usar para buscar el siguiente dígito, o strpbrk( line, "+-0123456789" ) si puede tener +- en su entrada …

La mayoría de la gente usaría fscanf :

 int number, items_scanned; items_scanned = fscanf(fp, "%d", &number); if (items_scanned == 0) { /* Scanning for a number failed */ printf("Scan failed!\n"); } printf("Found number: %d\n", number); 

fscanf salta espacios en blanco. Tendrá éxito si encuentra un número y falla si encuentra algo más.