1 /***********************************************************************
2 * GNU Lesser General Public License
4 * This file is part of the GFDL Flexible Modeling System (FMS).
6 * FMS is free software: you can redistribute it and/or modify it under
7 * the terms of the GNU Lesser General Public License as published by
8 * the Free Software Foundation, either version 3 of the License, or (at
9 * your option) any later version.
11 * FMS is distributed in the hope that it will be useful, but WITHOUT
12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with FMS. If not, see <http://www.gnu.org/licenses/>.
18 **********************************************************************/
25 // struct to store a string and id associated with that string
31 // Compares two my_type types by the arr_name
32 static int arr_name_sorter(const void* p1
, const void* p2
)
34 const my_type
*the_type1
= p1
;
35 const my_type
*the_type2
= p2
;
37 return strcmp(the_type1
->arr_name
, the_type2
->arr_name
);
40 // Sorts an array of strings in alphabetical order
41 // Implements a binary search to search for a string in an array of strings
42 // arr -> pointer of character array
43 // n -> length of the array
44 // id - > indices of the character array
45 void fms_sort_this(char **arr
, int* n
, int* id
)
47 int i
; // For do loops
50 // Save the array and the id into a struct
51 the_type
= (my_type
*)calloc(*n
, sizeof(my_type
));
53 the_type
[i
].id
= id
[i
];
54 strcpy(the_type
[i
].arr_name
, arr
[i
]);
57 qsort(the_type
, *n
, sizeof(my_type
), arr_name_sorter
);
59 // Copy the sorted array and the sorted ids
61 id
[i
] = the_type
[i
].id
;
62 strcpy(arr
[i
], the_type
[i
].arr_name
);
66 // Implements a binary search to search for a string in an array of strings
67 // arr -> pointer of character array
68 // n -> length of the array
69 // find me -> string to find
70 // np -> the number of times the string was found
71 // returns a string with the indices ;)
72 char* fms_find_my_string_binding(char** arr
, int *n
, char *find_me
, int *np
)
74 int L
= 0; // Left bound
75 int R
= *n
; // Right bound
76 int m
; // Middle of the bound
77 int mm
; // Index currently looking at
78 int is_found
; // Result from strcmp: 0 if string was found <0 if the string is "less" >0 if the string is "greater"
79 int *p
; // Array to store the indices
80 int i
; // For do loops
85 // Start looking in the midle of the array
86 m
= ceil((L
+ R
) / 2);
87 //printf("L is set to %i from L=%i and R=%i \n", m, L, R);
89 //printf("Checking %i:%s \n", m, (arr[m]));
90 is_found
= strcmp(find_me
,(arr
[m
]));
94 p
= malloc(sizeof(int) * *np
);
95 p
[*np
-1] = m
+ 1; //Because fortran indices start at 1 ;)
96 //printf("Array found at %i %i %i \n", *np, m, p[*np-1]);
98 // The string can be found in multiple indices of the array, so look to the left of the index where the string
99 // was initially found
101 while (is_found
== 0) {
102 if (mm
!= 0) { // Only look to the left if m is not the begining of the array
104 is_found
= strcmp(find_me
,(arr
[mm
]));
105 if (is_found
== 0 ) {
107 p
= realloc(p
, sizeof(int) * *np
);
109 //printf("Array found at %i %i %i\n", *np, mm, p[*np-1]);
111 } else {is_found
= -999;} //Done looking
113 // The string can be found in multiple indices of the array, so look to the right of the index where the string was
117 while (is_found
== 0) {
118 if (mm
!= *n
-1) { // Only look to the right if m is not the end of the array
120 is_found
= strcmp(find_me
,(arr
[mm
]));
121 if (is_found
== 0 ) {
123 p
= realloc(p
, sizeof(int) * *np
);
125 //printf("Array found at %i %i %i\n", *np, mm, p[*np-1]);
127 } else {is_found
= -999;} //Done looking}
130 // If find_me is greater than arr[m] (i.e find_me="potato" is greater than arr[m]="banana")
131 } else if (is_found
> 0) {
132 // Set the lower bound to start in m (ignore the first half)
134 //printf("L is set to %i \n", L);
136 // If find_me is less than arr[m] (i.e find_me="potato" is less than arr[m] = "soccer")
138 // Set the upper bound to start in m (ignore the lower half)
140 //printf("R is set to %i \n", R);
145 // This is the magical part:
146 // Save the array of indices where the string was found into a string
147 // The fortran side is going to allocate the array to the correct size and read the string into the array
148 // The alternative (normal) way is to have a seperate function that gets the number of times the string is found
149 // The fortran side will allocate the array to the correct size and send that into another function that
150 // fill in that array. That will require you to search through the array twice ...
156 for(i
=0; i
<*np
; i
++){
157 if (i
== *np
-1) {sprintf( &string
[ strlen(string
) ], "%d ", p
[i
] );}
158 else {sprintf( &string
[ strlen(string
) ], "%d ,", p
[i
] );}
161 string_p
= (char*) malloc((strlen(string
)+1)*sizeof(char));
162 strcpy(string_p
, string
);
167 * @brief Finds the number of unique strings in an array
168 * @param[in] arr Array of strings
169 * @param[in] n Size of the array
170 * @return Number of unique strings in an array
172 int fms_find_unique(char** arr
, int *n
)
175 int nfind
; // Number of unique strings in an array
176 int * ids
= calloc(*n
, sizeof(int)); // Array of integers initialized to 0
178 fms_sort_this(arr
, n
, ids
);
182 if (strcmp(arr
[i
], arr
[i
-1]) != 0){ nfind
= nfind
+ 1;}
189 * @brief Returns a c string pointer
190 * @param[in] cs Input c string pointer
191 * @return c string pointer
193 char * cstring2cpointer (char * cs
)