字符串(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 = 20
sum(x, y);
//here: x = 10, y = 20
swap(x, y);
//here: x = 20, y = 10
cout << x << " " << y << endl; return 0;
} //Pass by reference
void swap(int &x, int &y)
{
int temp = x;
x = y;
y = temp;
} //Pass by value
void printSum(int x, int y)
{
x += y;
cout << x << endl;
}


【stanford C++】字符串(String)与流(Stream)的更多相关文章

  1. delphi 字符串string转流TStream

    function StringToFile(mString : string; mFileName : TFileName) : Boolean;var vFileChar : file of Cha ...

  2. C# 字符串string和内存流MemoryStream及比特数组byte[]之间相互转换

    定义string变量为str,内存流变量为ms,比特数组为bt 1.字符串转比特数组 复制代码 代码如下: (1)byte[] bt=System.Text.Encoding.Default.GetB ...

  3. c#中字节数组byte[]、图片image、流stream,字符串string、内存流MemoryStream、文件file,之间的转换

    字节数组byte[]与图片image之间的转化 字节数组转换成图片 public static Image byte2img(byte[] buffer) { MemoryStream ms = ne ...

  4. Atiti 重定向标准输出到字符串转接口adapter stream流体系 以及 重定向到字符串

    Atiti 重定向标准输出到字符串转接口adapter stream流体系 以及 重定向到字符串 原理::syso  向ByteArrayOutputStream这个流理想write字节..然后可以使 ...

  5. 字符串string和内存流MemoryStream及比特数组byte[]互转

    原文:字符串string和内存流MemoryStream及比特数组byte[]互转   字符串string和内存流MemoryStream及比特数组byte[]互转比较 定义string变量为str, ...

  6. 将String转化成Stream,将Stream转换成String, C# Stream 和 byte[] 之间的转换(文件流的应用)

    static void Main( string[] args ) { string str = "Testing 1-2-3"; //convert string 2 strea ...

  7. nodeJS之流stream

    前面的话 当内存中无法一次装下需要处理的数据时,或者一边读取一边处理更加高效时,我们就需要用到数据流.NodeJS中通过各种Stream来提供对数据流的操作.本文将详细说明NodeJS中的流strea ...

  8. Java笔记:Java 流(Stream)、文件(File)和IO

    更新时间:2018-1-7 12:27:21 更多请查看在线文集:http://android.52fhy.com/java/index.html java.io 包几乎包含了所有操作输入.输出需要的 ...

  9. Java - 17 Java 流(Stream)、文件(File)和IO

    Java 流(Stream).文件(File)和IO Java.io包几乎包含了所有操作输入.输出需要的类.所有这些流类代表了输入源和输出目标. Java.io包中的流支持很多种格式,比如:基本类型. ...

随机推荐

  1. MySql状态查看方法 MySql如何查看连接数和状态?

    原文:MySql状态查看方法 MySql如何查看连接数和状态? 如果是root帐号,你能看到所有用户的当前连接.如果是其它普通帐号,只能看到自己占用的连接 怎么进入mysql命令行呢? mysql的安 ...

  2. JS时间戳比较大小:对于一组时间戳(开始时间~结束时间)和另一组时间戳进行比较,用于判断被比较时间戳组是否在要求范围内

    /* *JS时间戳比较大小:对于一组时间戳(开始时间~结束时间)和另一组时间戳进行比较,用于判断被比较时间戳组是否在要求范围内 *@param date1 date2(形如:'2015-01-01'类 ...

  3. Appium Server 源码分析之启动运行Express http服务器

    通过上一个系列Appium Android Bootstrap源码分析我们了解到了appium在安卓目标机器上是如何通过bootstrap这个服务来接收appium从pc端发送过来的命令,并最终使用u ...

  4. .net使用cefsharp开源库开发chrome

    .net使用cefsharp开源库开发chrome 离上篇写介绍pc端的混合开发和为什么以cefsharp入手研究混合开发已经有好几天,一直忙,抽不出时间继续写怎么搭建cefsharp开发环境.其实没 ...

  5. 19.最经济app发短信的方法

    在创业团队.一个重要的原则是能省就省,该花的花,明智地使用金钱. 今的app,为了获取用户的社交关系.须要用户的手机号注冊. 用手机号注冊就涉及到一个发送短信验证码的问题,那怎么才干在短信服务上投入最 ...

  6. HTML5----input-datalist输入框自己主动提示功能

    效果图: <label for="word_name">字母 : </label> <input id="word_name" n ...

  7. solr与.net主从复制

    solr主从复制 solr与.net系列课程(七)solr主从复制    既然solr是解决大量数据全文索引的方案,由于高并发的问题,我们就要考虑solr的负载均衡了,solr提供非常简单的主从复制的 ...

  8. Android_WebServices_介绍

    本博文为子墨原创,转载请注明出处! http://blog.csdn.net/zimo2013/article/details/38036289 1.WebService的介绍 WebService为 ...

  9. Android 实现用户列表信息的功能,然后选择删除幻灯片删除功能

    在项目开发过程中.经常须要对用户列表的信息进行删除的操作.Android中经常使用的删除操作方式有两种 .一种就是类似微信的滑动出现删除button方式,另一种是通过CheckBox进行选择.然后通过 ...

  10. 一个用MFC实现Com聚合样本

    ComATLATLMFCMFC MFCIUnknownMFCCCmdTargetComMFCCom MFCCOM 1. 1.1 #pragma once typedef long HRESULT; / ...