2009-04-07 25 views
7

Tengo una pregunta sobre Fortran 77 y no he podido encontrar una solución.Array of Strings en Fortran 77

Estoy intentando almacenar una matriz de cadenas definidas como las siguientes:

character matname(255)*255 

Wich es una matriz de cadenas de longitud 255 255.

después leí la lista de nombres de una Archivo y me puse el contenido de la matriz de la siguiente manera:

matname(matcount) = mname 

EDIT: En realidadmname valor se harcoded como mname = 'AIR' de tipo character*255, es un parámetro de una función matadd() que ejecuta la línea anterior. Pero esto es solo para pruebas, en el futuro se leerá de un archivo.

Más tarde Quiero imprimir con:

write(*,*) matname(matidx) 

pero parece que imprimir todos los 255 caracteres, se imprime la cadena Asigné y un montón de basura.

  • Así que esa es mi pregunta, ¿cómo puedo saber la longitud de la secuencia almacenada?
  • ¿Debo tener otra matriz con todas las longitudes?
  • ¿Y cómo puedo saber la longitud de la cadena de lectura?

Gracias.

+1

+1 - Fortran? ¿En serio? –

+1

@Ian - ¿Por qué no? – Rook

Respuesta

4

La función que Timotei publicó le dará la longitud de la cadena siempre que la parte de la cadena que le interese solo contenga espacios, que, si estás asignando los valores en el programa Shou Debería ser cierto ya que se supone que FORTRAN debe inicializar las variables para que estén vacías y para los caracteres que significan un espacio.

Sin embargo, si está leyendo desde un archivo, puede seleccionar otros caracteres de control al final de las líneas (particularmente caracteres de retorno de carro o de avance de línea, \ ry/o \ n según su sistema operativo) . También debe tirarlos en la función para obtener la longitud de cadena correcta. De lo contrario, podría obtener algunas declaraciones de impresión divertidas ya que esos caracteres también se imprimen.

Aquí está mi versión de la función que busca espacios allen en blanco al final además de espacios.

function strlen(st) 
    integer   i,strlen 
    character   st*(*) 
    i = len(st) 
    do while ((st(i:i).eq.' ').or.(st(i:i).eq.'\r').or. 
+ (st(i:i).eq.'\n').or.(st(i:i).eq.'\t')) 
    i = i - 1 
    enddo 
    strlen = i 
    return 
    end 

Si hay otros caracteres en la sección "basura", esto no funcionará completamente.

Suponiendo que funciona para sus datos, sin embargo, a continuación, puede cambiar su estado de escritura a tener este aspecto:

write(*,*) matname(matidx)(1:strlen(matname(matidx))) 

y se imprimirá a cabo sólo la cadena real.

En cuanto a si deberías usar otra matriz para mantener las longitudes de la cadena, eso depende de ti. la función strlen() es O (n) mientras que buscar la longitud en una tabla es O (1). Si se encuentra a sí mismo computando las longitudes de estas cadenas estáticas a menudo, puede mejorar el rendimiento para calcular la longitud una vez cuando se leen, almacenarlas en una matriz y buscarlas si las necesita. Sin embargo, si no nota la desaceleración, no me preocuparía.

+0

Tuve que modificar la definición de tipo de la función que recibe la cadena como parámetro a: 'character mname * (*)'. Antes, el final de esa variable era basura aleatoria, ahora está rellenada con espacios. Gracias por la explicación, fue muy claro. Además, no sabía acerca de la * notación. – Siu

5

Puede utilizar esta función para obtener la longitud (sin cola en blanco)

integer function strlen(st) 
     integer  i 
     character  st*(*) 
     i = len(st) 
     do while (st(i:i) .eq. ' ') 
     i = i - 1 
     enddo 
     strlen = i 
     return 
     end 

ya ha recibido aquí: http://www.ibiblio.org/pub/languages/fortran/ch2-13.html

PS: Cuando dice: matname (matidx) se pone toda la cadena (256) caracteres ... así que esa es su cadena más espacios en blanco o basura

+0

+1 pero desearía que fuera más. –

+0

Gracias también, me gustaría votar, pero todavía no tengo suficiente reputación. – Siu

1

Dependiendo del compilador que está utilizando, puede ser capaz de utilizar la función intrínseca trim() para eliminar cualquier líder/espacios finales de una cadena, entonces procesarlo como lo haría normalmente, es decir,

character(len=25) :: my_string 
my_string = 'AIR' 
write (*,*) ':', trim(my_string), ':' 

debería imprimir :AIR:.

Editar: Mejor aún, parece que hay una función len_trim() que devuelve la longitud de una cadena después de haber sido recortada.

0

intel y Compaq Visual Fortran tienen la función intrínseca LEN_TRIM (STRING) que devuelve la longitud sin espacios en blanco o espacios al final.

Si desea suprimir espacios en blanco o espacios iniciales, utilice "Ajuste a la izquierda", es decir ADJUSTF (CADENA)

En estos Fortrans También observo una característica útil: Si se pasa una cadena a una función o subrutina como un argumento, y dentro de la subrutina se declara como CHARACTER * (*), luego usando la función LEN (STRING) en la subrutina recupera la longitud de cadena real pasada, y no la longitud de la cadena como se declara en el programa de llamada .

Ejemplo: CARÁCTER * 1000 CADENA

 . 
     . 

    CALL SUBNAM(STRING(1:72) 

    SUBROUTINE SYBNAM(STRING) 
    CHARACTER*(*) STRING 
    LEN(STRING) will be 72, not 1000 
+0

Usar una estructura para la cuerda y la longitud de la misma, a veces tiene sentido. – Holmz