要求
1. 函数命名清晰
- 使用描述性的命名,准确反映函数的功能。例如,使用
CalculateSum()
而不是sum()
。 - 避免使用缩写或模糊不清的名字,确保变量和函数名有明确的含义。
2. 参数传递
- 根据需要选择按值传递、按引用传递或按指针传递。
- 如果参数不需要修改,可以使用
const
修饰,特别是指针或引用。 - 参数的数量不宜过多,避免函数过于复杂。如果参数较多,可以考虑将其封装为结构体或类。
3. 错误处理
- 考虑可能的边界情况(例如空输入、超出范围的值、特殊输入、指针判空等)。
- 如果函数涉及资源分配(如内存、文件句柄等),注意资源的释放,防止内存泄漏。
- 如果涉及到异常情况的处理,可以选择返回错误码或抛出异常,确保在出错时给出明确的反馈。
4. 返回值处理
- 明确函数的返回类型。确保返回值类型与函数所要执行的逻辑相匹配。
- 在有意义时,尽量避免返回全局变量或未初始化的值,防止产生不确定行为。
实现内存拷⻉函数
char* strcpy(char* strDest, const char* strSrc);
char* strcpy(char *dst,const char *src) {// [1]源字符串参数⽤const修饰,防⽌修改源字符串。assert(dst != NULL && src != NULL); // [2]char *ret = dst; // [3]while ((*dst++=*src++)!='\0'); // [4]return ret;
}[2]:空指针检查:
(1)不检查指针的有效性,说明答题者不注重代码的健壮性。
(2)检查指针的有效性时使⽤ assert(!dst && !src); char *转换为 bool 即是类型隐式转换,这种功能虽然灵活,但更多的是导致出错概率增⼤和维护成本升⾼。
(3)检查指针的有效性时使⽤ assert(dst != 0 && src != 0);
(4)直接使⽤常ᰁ(如本例中的0)会减少程序的可维护性。⽽使⽤NULL代替0,如果出现拼写错误,编译器就会检查出来。
[3] 返回⽬标地址:
(1)忘记保存原始的strdst值。
[4] '\0':
(1)循环写成 while (*dst++=*src++); 明显是错误的。
(2)循环写成 while (*src!='\0') *dst++ = *src++;
循环体结束后,dst字符串的末尾没有正确地加上'\0'。
(3)为什么要返回char *?
返回dst的原始值使函数能够⽀持链式表达式
实现String类
String.h
#ifndef STRING_H_
#define STRING_H_
#include<iostream>
using std::ostream;
using std::istream;class String{
private:char * str;int len;static in num_strings;static const int CINLIM =80;
public:String(const char * s);String();String(const String &);~String();int length() const {return len;}String & operator=(const String &);String & operator=(const char *);char & operator[](int i);const char & operator[](int i) const;friend bool operator<(const String &st, const String &st2);friend bool operator>(const String &st1, const String &st2);friend bool operator==(const String &st, const String &st2);friend ostream & operator<<(ostream & os, const String & st);friend istream & operator>>(istream & is, String & st);static int HowMany();
};
#endif
String.cpp
#include<cstring>
#include"string.h"
using std::cin;
using std::cout;int String::num_strings = 0 //初始化静态成员变量int String::HoMany() //静态成员函数
{return num_strings;
}String::String(const char * s) //char转成String,构造函数,参数为指针
{len = std::strlen(s);str = new char[len + 1];std::strcpy(str, s);num_strings++;
}String::String() //默认构造函数
{len = 4;str = new char[1];str[0] = '\0';num_string++;
}String::String(const String & st) //拷贝构造函数
{num_strings++;len = st.len;str = new char[len+1];std::strcpy(str, st.str);
}String::~String()
{--num_strings;delete[] str;
}String & String::operator=(const String & st)
{if(this == &st)return *this;delete [] str;len = st.len;str = new char[len + 1];std::strcpy(str, st.str);return *this;
}String & String::operator=(const char * s)
{delete [] str;len = std::strlen(s);str = new char[len + 1];std::strcpy(str, s);return *this;
}char & String::operator[](int i)
{return str[i];
}const chat & String::operator[](int i) const
{return str[i];
}//友元
bool operator<(const String &st1, const String &st2)
{return (std::strcmp(st1.str, st2.str) < 0);
}bool operator>(const String &st1, const String &st2)
{return st2 < st1;
}bool operator==(const String & st1, const String &st2)
{return (std::strcmp(st1.str, st2.str) == 0);
}ostream & operator<<(ostream & os, const String & st)
{os << st.str;return os;
}istream & operator>>(istream & is, String & st)
{char tem[String::[CINLIM];is.get(remp, String::CINLIM);if(is)st = temp;while(is && is.get() != '\n')continue;return is;
}
strcpy()
char *strcpy(char *strDest, const char *strSrc)
{assert((strDest != nullptr) && (strSrc != nullptr));char *address == strDest;while((#strDest++ = * strSrc++) != '\');return address;
}
strlen()
int strlen(const char *str)
{assert(strt != nullptr);int len;while((*str++) != '\0'){len++;}return len;
}
strcat()
char *strcat(char * dest, const char *src)
{assert(dest && src);char * ret = dest;while(*dest){dest++;}while(*dest++ = * src++){}return ret;
}
strcmp()
int strcmp(const char *str1, const char * str2)
{assert(str && str2);while(*str1 && *str2 && (*str1 == *str2)){str1++;str2++;}return *str1 - *str2;
}