c++ 字符串工具類
1 #ifndef STRINGUTILS_H__
2 #define STRINGUTILS_H__
3
4 #include <sstream>
5 #include <string>
6 #include <vector>
7 #include <algorithm>
8 #include <stdarg.h>
9
10 /**
11 * Collection of various helper methods for strings.
12 *
13 * \sa std::string
14 *
15 * \todo Test, test, test!
16 */
17 namespace StringUtils {
18
19 /**
20 * Converts the string \a str to lowercase.
21 * \param str String to convert.
22 * \return Lowercase version of \a str.
23 */
24 static std::string lowercase(const std::string& str) {
25 std::string toReturn(str);
26 std::transform(toReturn.begin(), toReturn.end(), toReturn.begin(), ::tolower);
27 return toReturn;
28 };
29 /**
30 * Converts the string \a str to uppercase.
31 * \param str String to convert.
32 * \return Uppercase version of \a str.
33 */
34 static std::string uppercase(const std::string& str) {
35 std::string toReturn(str);
36 std::transform(toReturn.begin(), toReturn.end(), toReturn.begin(), ::toupper);
37 return toReturn;
38 };
39 /**
40 * Splits \a str into a vector of strings representing float values.
41 * Floats formatted as [-][0-9]*.[0-9]* are considered, all other characters in between are ignored.
42 *
43 * \param str Input string to parse.
44 *
45 * \note TODO: The detection algorithm is a litte simplified and will not yield correct results
46 * in every case.
47 **/
48 static std::vector<std::string> parseFloats(const std::string& str){
49 static const std::string floatCharacters("0123456789.-");
50 std::vector<std::string> toReturn;
51 size_t strpos = 0;
52 size_t endpos = 0;
53 // we just started or just finished parsing an entry, check if finished and skip to beginning of next entry
54 while ((endpos != std::string::npos) && (strpos = str.find_first_of(floatCharacters, strpos)) != std::string::npos) {
55 // strpos currently points to the beginning of a float, now find its end
56 endpos = str.find_first_not_of(floatCharacters, strpos + 1);
57 // extract float
58 std::string token = str.substr(strpos, endpos - strpos);
59 // sanity checks
60 size_t signPos = token.rfind('-');
61 if (signPos == 0 || signPos == std::string::npos) { // sign only allowed at beginning
62 if (token.find('.') == token.rfind('.')) { // only one . allowed
63 toReturn.push_back(token);
64 }
65 }
66 strpos = endpos + 1;
67 }
68 return toReturn;
69 };
70 /**
71 * Replaces all occurrences of \a from in \a str with \a to.
72 * \param str String to perform replacement on.
73 * \param from String to be replaced.
74 * \param to String replace.
75 * \return \a str with all occurrences of \a from replaced with \a to.
76 */
77 static std::string replaceAll(const std::string& str, const std::string& from, const std::string& to)
78 {
79 std::string toReturn(str);
80 std::string::size_type strpos = 0;
81 std::string::size_type foundpos;
82 while ((foundpos = toReturn.find(from, strpos)) != std::string::npos) {
83 toReturn.replace(foundpos, from.size(), to);
84 strpos = foundpos + to.size();
85 }
86 return toReturn;
87 };
88 static bool replace(std::string& str, const std::string& from, const std::string& to) {
89 size_t start_pos = str.find(from);
90 if (start_pos == std::string::npos)
91 return false;
92 str.replace(start_pos, from.length(), to);
93 return true;
94 };
95
96 static bool replaceLast(std::string& str, const std::string& from, const std::string& to) {
97 size_t start_pos = str.rfind(from);
98 if (start_pos == std::string::npos)
99 return false;
100 str.replace(start_pos, from.length(), to);
101 return true;
102 };
103 /**
104 * Splits the string \a str into pieces separated by the delimiters in \a delimiter.
105 * \param str String to split.
106 * \param delimiter Set of delimiters.
107 * \return Vector of the split substrings.
108 */
109 static std::vector<std::string> split(const std::string& line, const std::string& delimiter) {
110 std::vector<std::string> toReturn;
111 std::string::size_type linepos = 0;
112 std::string::size_type endpos = 0;
113 // we are at the beginning of an entry, skip whitespace and check if not already reached end of line
114 while (endpos != std::string::npos) {
115 endpos = line.find_first_of(delimiter, linepos);
116 toReturn.push_back(line.substr(linepos, endpos - linepos));
117 linepos = endpos + 1;
118 }
119 return toReturn;
120 };
121 template<class T>
122 static std::vector<T> splitStringT(const std::string& line, const std::string& delimiter) {
123 std::vector<T> toReturn;
124 std::string::size_type linepos = 0;
125 std::string::size_type endpos = 0;
126 // we are at the beginning of an entry, skip whitespace and check if not already reached end of line
127 while (endpos != std::string::npos) {
128 endpos = line.find_first_of(delimiter, linepos);
129 toReturn.push_back(StringUtils::fromString<T>(line.substr(linepos, endpos - linepos)));
130 linepos = endpos + 1;
131 }
132 return toReturn;
133 };
134 /**
135 * Trims the string \a str.
136 * All leading and trailing occurrences of the characters in \a whitespace will be removed.
137 *
138 * \param str The string to trim.
139 * \param whitespace Set of whitespace characters which shall be removed at the beginning and the end.
140 * \return The original string without leading and trailing whitespace.
141 */
142 static std::string trim(const std::string& str, const std::string& whitespace = " \t\n\r\0\x0B") {
143 std::string::size_type first = str.find_first_not_of(whitespace);
144 if (first == std::string::npos) {
145 return "";
146 }
147 else {
148 std::string::size_type last = str.find_last_not_of(whitespace);
149 return str.substr(first, last - first + 1);
150 }
151 };
152 /**
153 * Splits the string \a str into trimmed pieces separated by the delimiters in \a delimiter.
154 * Delimiters in quoted strings (\a quotes) will be ignored, double quotes within quoted strings will be
155 * interpreted as literal quotes. Each token will be trimmed.
156 *
157 * \param str String to split.
158 * \param delimiter Set of delimiters.
159 * \param quotes Character used for quotes.
160 * \param whitespace Set of whitespace characters which shall be removed during trimming.
161 * \return Vector of the split substrings.
162 */
163 static std::vector<std::string> splitStringsafe(const std::string& str, const std::string& delimiter, char quotes = '"', const std::string& whitespace = " \t\n\r\0\x0B")
164 {
165 std::vector<std::string> toReturn;
166 std::string::size_type strpos = 0;
167 std::string::size_type endpos = 0;
168 // we are at the beginning of an entry, skip whitespace and check if not already reached end of str
169 while ((endpos != std::string::npos) && (strpos = str.find_first_not_of(whitespace, strpos)) != std::string::npos) {
170 // now strpos points to the first non blank character, here starts the entry
171 // check whether there are quotes
172 if (str[strpos] == quotes) {
173 // find position of closing quotes
174 endpos = str.find_first_of('"', strpos + 1);
175 std::string toPush = str.substr(strpos + 1, endpos - strpos - 1);
176 // ensure we haven't found double quotes ("") which shall be resolved to one double quote in resulting string
177 while ((endpos != std::string::npos) && (endpos + 1 < str.length()) && (str[endpos + 1] == '"')) {
178 strpos = endpos + 1;
179 endpos = str.find_first_of('"', endpos + 2);
180 toPush.append(str.substr(strpos, endpos - strpos));
181 }
182 // push string in quotes onto toReturn
183 toReturn.push_back(trim(toPush, whitespace));
184 // ignore everything until next delimiter
185 endpos = str.find_first_of(delimiter, endpos);
186 }
187 // ok, this entry is not in quotes - just push everything until next delimiter onto toReturn
188 else {
189 endpos = str.find_first_of(delimiter, strpos);
190 toReturn.push_back(trim(str.substr(strpos, endpos - strpos), whitespace));
191 }
192 strpos = endpos + 1;
193 }
194 return toReturn;
195 };
196
197 /**
198 * Converts the value \a value to a string.
199 * \param value The value to convert, must be compatible with std::stringstream.
200 * \return A string representation of \a value.
201 */
202 template<class T>
203 static std::string toString(const T& value) {
204 std::ostringstream stream;
205 stream << value;
206 return stream.str();
207 };
208 /**
209 * Converts the string \a str to its original value.
210 * \param str The string to convert
211 * \return The back-converted value of \a str, type must be compatible with std::stringstream.
212 * \throw tgt::Exception on conversion failure
213 */
214 template<class T>
215 static T fromString(const std::string& str) {
216 T toReturn;
217 std::istringstream stream;
218 stream.str(str);
219 try
220 {
221 stream >> toReturn;
222 }
223 catch (std::exception& ex)
224 {
225 std::cout << "Failed to convert string '" << str << "'" << " exception=" << ex.what() << std::endl;
226 return NULL;
227 }
228 return toReturn;
229 };
230 /**
231 * Joins the substrings in \a tokens together using \a delimiter in between.
232 * \param tokens List of substrings to join.
233 * \param delimiter Delimiter which shall be placed between the substrings.
234 * \return A string containing the joined substrings.
235 */
236 template<typename T>
237 static std::string join(const std::vector<T>& tokens, const std::string& delimiter) {
238 if (tokens.empty())
239 return "";
240 std::stringstream s;
241 s << tokens[0];
242 for (std::vector<T>::size_type i = 1; i < tokens.size(); ++i)
243 s << delimiter << tokens[i];
244 return s.str();
245 };
246
247
248 static bool startsWith(const std::string &str, const std::string &prefix) {
249 return str.size() >= prefix.size() &&
250 str.compare(0, prefix.size(), prefix) == 0;
251 };
252 static bool endsWith(const std::string &str, const std::string &suffix) {
253 return str.size() >= suffix.size() &&
254 str.compare(str.size() - suffix.size(), suffix.size(), suffix) == 0;
255 };
256
257 static std::string format(const char* format,
)//一個參數數量可變的函數
258 {
259 std::string ret;
260 va_list ap;//新特性
261 va_start(ap, format);
262 char* buf = (char*)malloc(1024 * 100);
263 if (buf != nullptr)
264 {
265 vsnprintf(buf, 1024 * 100, format, ap);
266 ret = buf;
267 free(buf);
268 }
269 va_end(ap);
270 return ret;//返回字符串
271 };
272 }
2 #define STRINGUTILS_H__
3
4 #include <sstream>
5 #include <string>
6 #include <vector>
7 #include <algorithm>
8 #include <stdarg.h>
9
10 /**
11 * Collection of various helper methods for strings.
12 *
13 * \sa std::string
14 *
15 * \todo Test, test, test!
16 */
17 namespace StringUtils {
18
19 /**
20 * Converts the string \a str to lowercase.
21 * \param str String to convert.
22 * \return Lowercase version of \a str.
23 */
24 static std::string lowercase(const std::string& str) {
25 std::string toReturn(str);
26 std::transform(toReturn.begin(), toReturn.end(), toReturn.begin(), ::tolower);
27 return toReturn;
28 };
29 /**
30 * Converts the string \a str to uppercase.
31 * \param str String to convert.
32 * \return Uppercase version of \a str.
33 */
34 static std::string uppercase(const std::string& str) {
35 std::string toReturn(str);
36 std::transform(toReturn.begin(), toReturn.end(), toReturn.begin(), ::toupper);
37 return toReturn;
38 };
39 /**
40 * Splits \a str into a vector of strings representing float values.
41 * Floats formatted as [-][0-9]*.[0-9]* are considered, all other characters in between are ignored.
42 *
43 * \param str Input string to parse.
44 *
45 * \note TODO: The detection algorithm is a litte simplified and will not yield correct results
46 * in every case.
47 **/
48 static std::vector<std::string> parseFloats(const std::string& str){
49 static const std::string floatCharacters("0123456789.-");
50 std::vector<std::string> toReturn;
51 size_t strpos = 0;
52 size_t endpos = 0;
53 // we just started or just finished parsing an entry, check if finished and skip to beginning of next entry
54 while ((endpos != std::string::npos) && (strpos = str.find_first_of(floatCharacters, strpos)) != std::string::npos) {
55 // strpos currently points to the beginning of a float, now find its end
56 endpos = str.find_first_not_of(floatCharacters, strpos + 1);
57 // extract float
58 std::string token = str.substr(strpos, endpos - strpos);
59 // sanity checks
60 size_t signPos = token.rfind('-');
61 if (signPos == 0 || signPos == std::string::npos) { // sign only allowed at beginning
62 if (token.find('.') == token.rfind('.')) { // only one . allowed
63 toReturn.push_back(token);
64 }
65 }
66 strpos = endpos + 1;
67 }
68 return toReturn;
69 };
70 /**
71 * Replaces all occurrences of \a from in \a str with \a to.
72 * \param str String to perform replacement on.
73 * \param from String to be replaced.
74 * \param to String replace.
75 * \return \a str with all occurrences of \a from replaced with \a to.
76 */
77 static std::string replaceAll(const std::string& str, const std::string& from, const std::string& to)
78 {
79 std::string toReturn(str);
80 std::string::size_type strpos = 0;
81 std::string::size_type foundpos;
82 while ((foundpos = toReturn.find(from, strpos)) != std::string::npos) {
83 toReturn.replace(foundpos, from.size(), to);
84 strpos = foundpos + to.size();
85 }
86 return toReturn;
87 };
88 static bool replace(std::string& str, const std::string& from, const std::string& to) {
89 size_t start_pos = str.find(from);
90 if (start_pos == std::string::npos)
91 return false;
92 str.replace(start_pos, from.length(), to);
93 return true;
94 };
95
96 static bool replaceLast(std::string& str, const std::string& from, const std::string& to) {
97 size_t start_pos = str.rfind(from);
98 if (start_pos == std::string::npos)
99 return false;
100 str.replace(start_pos, from.length(), to);
101 return true;
102 };
103 /**
104 * Splits the string \a str into pieces separated by the delimiters in \a delimiter.
105 * \param str String to split.
106 * \param delimiter Set of delimiters.
107 * \return Vector of the split substrings.
108 */
109 static std::vector<std::string> split(const std::string& line, const std::string& delimiter) {
110 std::vector<std::string> toReturn;
111 std::string::size_type linepos = 0;
112 std::string::size_type endpos = 0;
113 // we are at the beginning of an entry, skip whitespace and check if not already reached end of line
114 while (endpos != std::string::npos) {
115 endpos = line.find_first_of(delimiter, linepos);
116 toReturn.push_back(line.substr(linepos, endpos - linepos));
117 linepos = endpos + 1;
118 }
119 return toReturn;
120 };
121 template<class T>
122 static std::vector<T> splitStringT(const std::string& line, const std::string& delimiter) {
123 std::vector<T> toReturn;
124 std::string::size_type linepos = 0;
125 std::string::size_type endpos = 0;
126 // we are at the beginning of an entry, skip whitespace and check if not already reached end of line
127 while (endpos != std::string::npos) {
128 endpos = line.find_first_of(delimiter, linepos);
129 toReturn.push_back(StringUtils::fromString<T>(line.substr(linepos, endpos - linepos)));
130 linepos = endpos + 1;
131 }
132 return toReturn;
133 };
134 /**
135 * Trims the string \a str.
136 * All leading and trailing occurrences of the characters in \a whitespace will be removed.
137 *
138 * \param str The string to trim.
139 * \param whitespace Set of whitespace characters which shall be removed at the beginning and the end.
140 * \return The original string without leading and trailing whitespace.
141 */
142 static std::string trim(const std::string& str, const std::string& whitespace = " \t\n\r\0\x0B") {
143 std::string::size_type first = str.find_first_not_of(whitespace);
144 if (first == std::string::npos) {
145 return "";
146 }
147 else {
148 std::string::size_type last = str.find_last_not_of(whitespace);
149 return str.substr(first, last - first + 1);
150 }
151 };
152 /**
153 * Splits the string \a str into trimmed pieces separated by the delimiters in \a delimiter.
154 * Delimiters in quoted strings (\a quotes) will be ignored, double quotes within quoted strings will be
155 * interpreted as literal quotes. Each token will be trimmed.
156 *
157 * \param str String to split.
158 * \param delimiter Set of delimiters.
159 * \param quotes Character used for quotes.
160 * \param whitespace Set of whitespace characters which shall be removed during trimming.
161 * \return Vector of the split substrings.
162 */
163 static std::vector<std::string> splitStringsafe(const std::string& str, const std::string& delimiter, char quotes = '"', const std::string& whitespace = " \t\n\r\0\x0B")
164 {
165 std::vector<std::string> toReturn;
166 std::string::size_type strpos = 0;
167 std::string::size_type endpos = 0;
168 // we are at the beginning of an entry, skip whitespace and check if not already reached end of str
169 while ((endpos != std::string::npos) && (strpos = str.find_first_not_of(whitespace, strpos)) != std::string::npos) {
170 // now strpos points to the first non blank character, here starts the entry
171 // check whether there are quotes
172 if (str[strpos] == quotes) {
173 // find position of closing quotes
174 endpos = str.find_first_of('"', strpos + 1);
175 std::string toPush = str.substr(strpos + 1, endpos - strpos - 1);
176 // ensure we haven't found double quotes ("") which shall be resolved to one double quote in resulting string
177 while ((endpos != std::string::npos) && (endpos + 1 < str.length()) && (str[endpos + 1] == '"')) {
178 strpos = endpos + 1;
179 endpos = str.find_first_of('"', endpos + 2);
180 toPush.append(str.substr(strpos, endpos - strpos));
181 }
182 // push string in quotes onto toReturn
183 toReturn.push_back(trim(toPush, whitespace));
184 // ignore everything until next delimiter
185 endpos = str.find_first_of(delimiter, endpos);
186 }
187 // ok, this entry is not in quotes - just push everything until next delimiter onto toReturn
188 else {
189 endpos = str.find_first_of(delimiter, strpos);
190 toReturn.push_back(trim(str.substr(strpos, endpos - strpos), whitespace));
191 }
192 strpos = endpos + 1;
193 }
194 return toReturn;
195 };
196
197 /**
198 * Converts the value \a value to a string.
199 * \param value The value to convert, must be compatible with std::stringstream.
200 * \return A string representation of \a value.
201 */
202 template<class T>
203 static std::string toString(const T& value) {
204 std::ostringstream stream;
205 stream << value;
206 return stream.str();
207 };
208 /**
209 * Converts the string \a str to its original value.
210 * \param str The string to convert
211 * \return The back-converted value of \a str, type must be compatible with std::stringstream.
212 * \throw tgt::Exception on conversion failure
213 */
214 template<class T>
215 static T fromString(const std::string& str) {
216 T toReturn;
217 std::istringstream stream;
218 stream.str(str);
219 try
220 {
221 stream >> toReturn;
222 }
223 catch (std::exception& ex)
224 {
225 std::cout << "Failed to convert string '" << str << "'" << " exception=" << ex.what() << std::endl;
226 return NULL;
227 }
228 return toReturn;
229 };
230 /**
231 * Joins the substrings in \a tokens together using \a delimiter in between.
232 * \param tokens List of substrings to join.
233 * \param delimiter Delimiter which shall be placed between the substrings.
234 * \return A string containing the joined substrings.
235 */
236 template<typename T>
237 static std::string join(const std::vector<T>& tokens, const std::string& delimiter) {
238 if (tokens.empty())
239 return "";
240 std::stringstream s;
241 s << tokens[0];
242 for (std::vector<T>::size_type i = 1; i < tokens.size(); ++i)
243 s << delimiter << tokens[i];
244 return s.str();
245 };
246
247
248 static bool startsWith(const std::string &str, const std::string &prefix) {
249 return str.size() >= prefix.size() &&
250 str.compare(0, prefix.size(), prefix) == 0;
251 };
252 static bool endsWith(const std::string &str, const std::string &suffix) {
253 return str.size() >= suffix.size() &&
254 str.compare(str.size() - suffix.size(), suffix.size(), suffix) == 0;
255 };
256
257 static std::string format(const char* format,

258 {
259 std::string ret;
260 va_list ap;//新特性
261 va_start(ap, format);
262 char* buf = (char*)malloc(1024 * 100);
263 if (buf != nullptr)
264 {
265 vsnprintf(buf, 1024 * 100, format, ap);
266 ret = buf;
267 free(buf);
268 }
269 va_end(ap);
270 return ret;//返回字符串
271 };
272 }
posted on 2017-05-25 09:59 Benjamin 閱讀(1273) 評論(0) 編輯 收藏 引用 所屬分類: C/C++