【stanford C++】字符串(String)与流(Stream)

来源:互联网 发布:2017店铺淘宝客怎么玩 编辑:程序博客网 时间:2024/04/28 10:56
字符串(String)与流(Stream)
一、C++中字符串(String)

字符串(String):就是(可能是空的)字符序列。
C++中的字符串在概念上和Java中的字符串类似。

C++字符串用string类型来表示。在使用string类型之前,必须在程序中包含如下头文件
#include <string>

可以通过调用如下方法:
str.length()
来获取字符串中字符的长度。

可以通过如下方式来从一个字符串中读取一个字符
str[index]
尽管字符串不是数组,但是上述语法是一个方便的语法方式。

字符操作
在C++中,头文件<cctype>包含各种有用的处理字符的函数,以下函数用来检查给定的类型是否是一个给定的字符
isalpha, isdigit, isalnum, islower, isupper, isspace, ispunct.

跟Java中字符串不同,C++中字符串是可变的,可以被修改。
改变单个字符的方式:
str[index] = ch

附加更多的文本方式:
str += text

这些操作直接改变字符串本身,而不是对字符串的副本进行操作。

在C++中,==操作符可以直接拿来用于字符串的比较
if(str1 == str2){    /* string match */}

在一个字符串中查询其他一些字符,可以使用find,如果找不到,则返回string::npos,而不是-1。
if(str1.find(str2) != string::npos){    /* found str2 inside str1 */}

通过调用substr方法从string中获取substring。
substr方法需要知道substring的开始位置和长度(不是结束位置)
string allButFirstChar = str.substr(1);string lastFiveChars = str.substr(str.length() - 5, 5);


与Java语言不同的时,在C++中,只能连接字符串和字符到其他的字符串中。

在本课程中,提供了"strlib.h"库,让字符串操作更加容易
string s = "I like " + integerToString(137);
strlib.h的代码如下:
/* * File: strlib.h * -------------- * This file exports several useful string functions that are not * included in the C++ string library. */#ifndef _strlib_h#define _strlib_h#include <iostream>#include <string>/* * Function: integerToString * Usage: string s = integerToString(n); * ------------------------------------- * Converts an integer into the corresponding string of digits. * For example, calling <code>integerToString(123)</code> returns * the string <code>"123"</code>. */std::string integerToString(int n);/* * Function: stringToInteger * Usage: int n = stringToInteger(str); * ------------------------------------ * Converts a string of digits into an integer.  If the string is not a * legal integer or contains extraneous characters other than whitespace, * <code>stringToInteger</code> calls <code>error</code> with an * appropriate message. */int stringToInteger(std::string str);/* * Function: realToString * Usage: string s = realToString(d); * ---------------------------------- * Converts a floating-point number into the corresponding string form. * For example, calling <code>realToString(23.45)</code> returns * the string <code>"23.45"</code>. */std::string realToString(double d);/* * Function: stringToReal * Usage: double d = stringToReal(str); * ------------------------------------ * Converts a string representing a real number into its corresponding * value.  If the string is not a legal floating-point number or contains * extraneous characters other than whitespace, <code>stringToReal</code> * calls <code>error</code> with an appropriate message. */double stringToReal(std::string str);/* * Function: toUpperCase * Usage: string s = toUpperCase(str); * ----------------------------------- * Returns a new string in which all lowercase characters have been converted * into their uppercase equivalents. */std::string toUpperCase(std::string str);/* * Function: toLowerCase * Usage: string s = toLowerCase(str); * ----------------------------------- * Returns a new string in which all uppercase characters have been converted * into their lowercase equivalents. */std::string toLowerCase(std::string str);/* * Function: equalsIgnoreCase * Usage: if (equalsIgnoreCase(s1, s2)) ... * ---------------------------------------- * Returns <code>true</code> if <code>s1</code> and <code>s2</code> are * equal discounting differences in case. */bool equalsIgnoreCase(std::string s1, std::string s2);/* * Function: startsWith * Usage: if (startsWith(str, prefix)) ... * --------------------------------------- * Returns <code>true</code> if the string <code>str</code> starts with * the specified prefix, which may be either a string or a character. */bool startsWith(std::string str, std::string prefix);bool startsWith(std::string str, char prefix);/* * Function: endsWith * Usage: if (endsWith(str, suffix)) ... * ------------------------------------- * Returns <code>true</code> if the string <code>str</code> ends with * the specified suffix, which may be either a string or a character. */bool endsWith(std::string str, std::string suffix);bool endsWith(std::string str, char suffix);/* * Function: trim * Usage: string trimmed = trim(str); * ---------------------------------- * Returns a new string after removing any whitespace characters * from the beginning and end of the argument. */std::string trim(std::string str);/* Private section *//**********************************************************************//* Note: Everything below this point in the file is logically part    *//* of the implementation and should not be of interest to clients.    *//**********************************************************************//* * Friend function: writeQuotedString * Usage: writeQuotedString(outfile, str, forceQuotes); * ---------------------------------------------------- * Writes the string str to outfile surrounded by double quotes, converting * special characters to escape sequences, as necessary.  If the optional * parameter forceQuotes is explicitly set to false, quotes are included * in the output only if necessary. */void writeQuotedString(std::ostream & os, const std::string & str,                       bool forceQuotes = true);/* * Friend function: readQuotedString * Usage: readQuotedString(infile, str); * ------------------------------------- * Reads the next string from infile into the reference parameter str. * If the first character (other than whitespace) is either a single * or a double quote, this function reads characters up to the * matching quote, processing standard escape sequences as it goes. * If not, readString reads characters up to any of the characters * in the string STRING_DELIMITERS in the implementation file. */void readQuotedString(std::istream & is, std::string & str);/* * Friend function: stringNeedsQuoting * Usage: if (stringNeedsQuoting(str)) ... * --------------------------------------- * Checks whether the string needs quoting in order to be read correctly. */bool stringNeedsQuoting(const std::string & str);/* * Friend function: writeGenericValue * Usage: writeGenericValue(os, value, forceQuotes); * ------------------------------------------------- * Writes a generic value to the output stream.  If that value is a string, * this function uses writeQuotedString to write the value. */template <typename ValueType>void writeGenericValue(std::ostream & os, const ValueType & value,                       bool forceQuotes) {   os << value;}template <>inline void writeGenericValue(std::ostream & os, const std::string & value,                              bool forceQuotes) {   writeQuotedString(os, value, forceQuotes);}/* * Friend function: readGenericValue * Usage: readGenericValue(is, value); * ----------------------------------- * Reads a generic value from the input stream.  If that value is a string, * this function uses readQuotedString to read the value. */template <typename ValueType>void readGenericValue(std::istream & is, ValueType & value) {   is >> value;}template <>inline void readGenericValue(std::istream & is, std::string & value) {   readQuotedString(is, value);}#endif

strlib.c的代码如下:
/* * File: strlib.cpp * ---------------- * This file implements the strlib.h interface. */#include <cctype>#include <iostream>#include <sstream>#include "error.h"#include "strlib.h"using namespace std;/* Function prototypes *//* * Implementation notes: numeric conversion * ---------------------------------------- * These functions use the <sstream> library to perform the conversion. */string integerToString(int n) {   ostringstream stream;   stream << n;   return stream.str();}int stringToInteger(string str) {   istringstream stream(str);   int value;   stream >> value >> ws;   if (stream.fail() || !stream.eof()) {      error("stringToInteger: Illegal integer format (" + str + ")");   }   return value;}string realToString(double d) {   ostringstream stream;   stream << uppercase << d;   return stream.str();}double stringToReal(string str) {   istringstream stream(str);   double value;   stream >> value >> ws;   if (stream.fail() || !stream.eof()) {      error("stringToReal: Illegal floating-point format (" + str + ")");   }   return value;}/* * Implementation notes: case conversion * ------------------------------------- * The functions toUpperCase and toLowerCase return a new string whose * characters appear in the desired case. These implementations rely on * the fact that the characters in the string are copied when the * argument is passed to the function, which makes it possible to change * the case of the copy without affecting the original. */string toUpperCase(string str) {   int nChars = str.length();   for (int i = 0; i < nChars; i++) {      str[i] = toupper(str[i]);   }   return str;}string toLowerCase(string str) {   int nChars = str.length();   for (int i = 0; i < nChars; i++) {      str[i] = tolower(str[i]);   }   return str;}/* * Implementation notes: equalsIgnoreCase * -------------------------------------- * This implementation uses a for loop to cycle through the characters in * each string.  Converting each string to uppercase and then comparing * the results makes for a shorter but less efficient implementation. */bool equalsIgnoreCase(string s1, string s2) {   if (s1.length() != s2.length()) return false;   int nChars = s1.length();   for (int i = 0; i < nChars; i++) {      if (tolower(s1[i]) != tolower(s2[i])) return false;   }   return true;}/* * Implementation notes: startsWith, endsWith * ------------------------------------------ * These implementations are overloaded to allow the second argument to * be either a string or a character. */bool startsWith(string str, string prefix) {   if (str.length() < prefix.length()) return false;   int nChars = prefix.length();   for (int i = 0; i < nChars; i++) {      if (str[i] != prefix[i]) return false;   }   return true;}bool startsWith(string str, char prefix) {   return str.length() > 0 && str[0] == prefix;}bool endsWith(string str, string suffix) {   int nChars = suffix.length();   int start = str.length() - nChars;   if (start < 0) return false;   for (int i = 0; i < nChars; i++) {      if (str[start + i] != suffix[i]) return false;   }   return true;}bool endsWith(string str, char suffix) {   return str.length() > 0 && str[str.length() - 1] == suffix;}string trim(string str) {   int finish = str.length() - 1;   while (finish >= 0 && isspace(str[finish])) {      finish--;   }   int start = 0;   while (start <= finish && isspace(str[start])) {      start++;   }   return str.substr(start, finish - start + 1);}/* * Implementation notes: readQuotedString and writeQuotedString * ------------------------------------------------------------ * Most of the work in these functions has to do with escape sequences. */static const string STRING_DELIMITERS = ",:)}]\n";bool stringNeedsQuoting(const string & str) {   int n = str.length();   for (int i = 0; i < n; i++) {      char ch = str[i];      if (isspace(ch)) return false;      if (STRING_DELIMITERS.find(ch) != string::npos) return true;   }   return false;}void readQuotedString(istream & is, string & str) {   str = "";   char ch;   while (is.get(ch) && isspace(ch)) {      /* Empty */   }   if (is.fail()) return;   if (ch == '\'' || ch == '"') {      char delim = ch;      while (is.get(ch) && ch != delim) {         if (is.fail()) error("Unterminated string");         if (ch == '\\') {            if (!is.get(ch)) error("Unterminated string");            if (isdigit(ch) || ch == 'x') {               int base = 8;               if (ch == 'x') base = 16;               int result = 0;               int digit = 0;               while (ch != delim) {                  if (isdigit(ch)) {                     digit = ch - '0';                  } else if (isalpha(ch)) {                     digit = toupper(ch) - 'A' + 10;                  } else {                     digit = base;                  }                  if (digit >= base) break;                  result = base * result + digit;                  if (!is.get(ch)) error("Unterminated string");               }               ch = char(result);               is.unget();            } else {               switch (ch) {                case 'a': ch = '\a'; break;                case 'b': ch = '\b'; break;                case 'f': ch = '\f'; break;                case 'n': ch = '\n'; break;                case 'r': ch = '\r'; break;                case 't': ch = '\t'; break;                case 'v': ch = '\v'; break;                case '"': ch = '"'; break;                case '\'': ch = '\''; break;                case '\\': ch = '\\'; break;               }            }         }         str += ch;      }   } else {      str += ch;      int endTrim = 0;      while (is.get(ch) && STRING_DELIMITERS.find(ch) == string::npos) {         str += ch;         if (!isspace(ch)) endTrim = str.length();      }      if (is) is.unget();      str = str.substr(0, endTrim);   }}void writeQuotedString(ostream & os, const string & str, bool forceQuotes) {   if (!forceQuotes && stringNeedsQuoting(str)) forceQuotes = true;   if (forceQuotes) os << '"';   int len = str.length();   for (int i = 0; i < len; i++) {      char ch = str.at(i);      switch (ch) {       case '\a': os << "\\a"; break;       case '\b': os << "\\b"; break;       case '\f': os << "\\f"; break;       case '\n': os << "\\n"; break;       case '\r': os << "\\r"; break;       case '\t': os << "\\t"; break;       case '\v': os << "\\v"; break;       case '"': os << oct << "\\" << (int(ch) & 0xFF); break;       case '\\': os << "\\\\"; break;       default:         if (isprint(ch)) {            os << ch;         } else {            ostringstream oss;            oss << oct << (int(ch) & 0xFF);            os << "\\" << oss.str();         }      }   }   if (forceQuotes) os << '"';}

在C++中,有两种类型的字符串:
  • C类型字符串,来自于C编程语言
  • C++类型string,C++实现的库
在C++中,尽可能的使用string类型。

对于string s = "Nubian " + "ibex";
这些字符串是C风格的,C风格的字符串是不支持+操作的,该表达式编译不通过。改为如下:
string s = string("Nubian ") + "ibex";
现在显式的转换C风格的字符串为C++类型的字符串,这样该代码是合法的。

二、字符串中的递归操作

1.对一个字符串进行逆序操作
递归的对字符串进行逆序操作,如下示意图所示:

代码实现如下:
/* File: reverse.cpp * * Code to recursively reverse a string. */#include <iostream>#include <string>#include "simpio.h"using namespace std;string reverseString(string line);int main() {string line = getLine("Enter a string: ");cout << reverseString(line) << endl;}/* Returns the reverse of the indicated string. */string reverseString(string line) {/* If the string is empty, it's its own reverse */if (line == "") {return "";}/* Otherwise, reverse all but the first character, then tack * on the first character. */else {return reverseString(line.substr(1)) + line[0];}}

2.回文(palindrome)
回文就是给定的字符串是对称的。
递归的判断给定的字符串是否是回文,示意图如下:

代码实现如下:
/* File: palindrome.cpp * * A program that reads a file of English words, then prints out all * the palindromic words. */#include <iostream>#include <string>#include <fstream>#include "simpio.h"using namespace std;bool isPalindrome(string text);int main() {/* Open the file for reading.  We really should check whether * the file is open before proceeding. */string file = "dictionary.txt";ifstream input(file.c_str());/* Read each line of the file and print out those that are palindromes. */string line;while (getline(input, line)) {if (isPalindrome(line)) {cout << line << endl;}}return 0;}/* Returns whether the given string is a palindrome. */bool isPalindrome(string text) {/* All characters of length 0 or length 1 are guaranteed to * be palindromes. */if (text.length() <= 1) {return true;}/* If the first and last character of the string aren't the same, * the string cannot be a palindrome. */else if (text[0] != text[text.length() - 1]) {return false;}/* Otherwise, this string is a palindrome precisely when the middle * characters are a palindrome. */else {return isPalindrome(text.substr(1, text.length() - 2));}}

3.C++中从File中读取数据

既然我们知道了如何操作字符串了,那么我们开始从外部文件中读取数据来处理。
在C++中,文件读取使用ifstream类来进行处理。必须包含头文件#include <fstream>来使用ifstream。

1)逐行读取
ifstream类通过使用getline函数从文件中读取一行
getline(file, str);

典型的读取文件中各行的循环如下所示:
string line;while(getline(file, line)){    /* ...process line... */}

回文的实现代码使用了文件的读取。

读取格式化的数据
从文件中读取格式化的数据可以通过使用流提取操作符:file>>variable
可以读取任何原始类型和字符串
当读取字符串时,在换行符或空格处即停止。

典型的读取格式化数据循环如下:
type val;while(file >> val){    /* ... process val... */}

4.C++中参数传递

在C++中,有两种方法传递一个参数给一个函数:
  • 传值方式:参数通过拷贝传给一个函数。void myFunction(int x);
  • 引用方式:传递给函数的变量在函数中是可以改变的。void myFunction(int &x)
举例:
int main(){int x = 10;int y = 20;//here: x = 10, y = 20sum(x, y);//here: x = 10, y = 20swap(x, y);//here: x = 20, y = 10cout << x << " " << y << endl;return 0;}//Pass by referencevoid swap(int &x, int &y){int temp = x;x = y;y = temp;}//Pass by valuevoid printSum(int x, int y){x += y;cout << x << endl;}



原创粉丝点击