一,c/c++字符串
1.C/C++中每个字符串都以字符’\0‘作为结尾,这样我们就能很方便地找到字符串的最后尾部。
由于这个原因每个字符串都有一个额外的开销,注意字符串越界的问题;
2.C/C++内存模型把字符串常量放到单独的一个内存区域;
当几个指针指向相同的字符串常量的时候,他们实际上会指向限购听那个的内存地址;
但是用字符串常量初始化数组,情况却不一样,这点很重要,考察你C能力的筹码;
test.c:
#include <stdio.h>
int main()
{
char str1[] = "hello world";
char str2[] = "hello world";
char * str3 = "hello boy";
char * str4 = "hello boy";
if(str1 == str2)
{
printf("str1 and str2 are same.\n");
}
else
{
printf("str1 and str2 are not same\n");
}
if (str3 = str4)
{
printf("str3 and str4 are same.\n");
}
else
{
printf("str3 and str4 are not same.\n");
}
return 0;
}
Makefile:
.PHONY:clean
CC=gcc
CFLAGS=-Wall -g
BIN=test
OBJS=test.o
LIBS=
$(BIN):$(OBJS)
$(CC) $(CFLAGS) $^ -o $@ $(LIBS)
%.o:%.c
$(CC) $(CFLAGS) -c $< -o $@
clean:
rm -f *.o $(BIN)
运行结果:
str1 and str2 are not same
str3 and str4 are same.
str1和str2是两个字符串数组,我们会为他们分配两个长度为12个字节的空间(在栈区),并且把常量区的“hello world”的内容分别拷贝的数组当中。
这是两个初始地址不同的数组;
str3和str4是两个指针,我们无须为她们分配内存一存储字符串的内容,而只需要把他们指向“hello boy”在常量区中的地址就可以了,“hello world”这个字符串常量在内存中只有一个拷贝,因此str3与str4的值是一样的。
二,替换空格
给定字符串中的空格替换成 ’%20‘
思路就是计算出替换后的字符串的长度,利用两个指针,一个指向就字符串的末尾,一个指向新字符串的末尾;
进而从后网前面遍历,这样子节约时间,移位的效率高,因为没有做多余的移位操作;
space.cpp:
#include <iostream>
#include <cstring>
#include <cstdio>
using namespace std;
/*length 为字符数组string的总的容量*/
void ReplaceBlank(char string[], int length)
{
if(string == NULL && length <= 0)
{
return;
}
/*originalLength为字符串string的实际长度*/
int originalLength = 0;
int numberOfBlank = 0;
int i = 0;
while(string[i] != '\0')
{
++ originalLength;
if(string[i] == ' ')
{
++ numberOfBlank;
}
++ i;
}
/*newLength为把空格替换成‘%20’后的长度*/
int newLength = originalLength + numberOfBlank * 2;
if (newLength > length)
{
return ;
}
int indexOforiginal = originalLength;
int indexOfNew = newLength;
while(indexOforiginal >= 0 && indexOfNew > indexOforiginal)
{
if(string[indexOforiginal] == ' ')
{
string[indexOfNew --] = '0';
string[indexOfNew --] = '2';
string[indexOfNew --] = '%';
}
else
{
string[indexOfNew --] = string[indexOforiginal];
}
-- indexOforiginal;
}
}
void Test(char* testName, char string[], int length, char expected[])
{
if(testName != NULL)
printf("%s begins: ", testName);
ReplaceBlank(string, length);
if(expected == NULL && string == NULL)
{
cout<<"passed."<<endl;
}
else if(expected == NULL && string != NULL)
{
cout<<"failed."<<endl;
}
else if(strcmp(string, expected) == 0)
{
cout<<"passed."<<endl;
}
else
{
cout<<"failed."<<endl;
}
}
// 空格在句子中间
void Test1()
{
const int length = 100;
char string[length] = "hello world";
Test("Test1", string, length, "hello%20world");
}
// 空格在句子开头
void Test2()
{
const int length = 100;
char string[length] = " helloworld";
Test("Test2", string, length, "%20helloworld");
}
// 空格在句子末尾
void Test3()
{
const int length = 100;
char string[length] = "helloworld ";
Test("Test3", string, length, "helloworld%20");
}
// 连续有两个空格
void Test4()
{
const int length = 100;
char string[length] = "hello world";
Test("Test4", string, length, "hello%20%20world");
}
// 传入NULL
void Test5()
{
Test("Test5", NULL, 0, NULL);
}
// 传入内容为空的字符串
void Test6()
{
const int length = 100;
char string[length] = "";
Test("Test6", string, length, "");
}
//传入内容为一个空格的字符串
void Test7()
{
const int length = 100;
char string[length] = " ";
Test("Test7", string, length, "%20");
}
// 传入的字符串没有空格
void Test8()
{
const int length = 100;
char string[length] = "helloworld";
Test("Test8", string, length, "helloworld");
}
// 传入的字符串全是空格
void Test9()
{
const int length = 100;
char string[length] = " ";
Test("Test9", string, length, "%20%20%20");
}
int main()
{
Test1();
Test2();
Test3();
Test4();
Test5();
Test6();
Test7();
Test8();
Test9();
return 0;
}
Makefile:
.PHONY:clean
CPP=g++
CFLAGS=-Wall -g
BIN=test
OBJS=space.o
LIBS=
$(BIN):$(OBJS)
$(CPP) $(CFLAGS) $^ -o $@ $(LIBS)
%.o:%.cpp
$(CPP) $(CFLAGS) -c $< -o $@
clean:
rm -f *.o $(BIN)Test1 begins: passed.
运行结果:
Test2 begins: passed.
Test3 begins: passed.
Test4 begins: passed.
Test5 begins: passed.
Test6 begins: passed.
Test7 begins: passed.
Test8 begins: passed.
Test9 begins: passed.