1.getchar用法
用户按回车后,每次从缓冲区里面读取一个字符
char a,b,c,d;
a=getchar();
b=getchar();
c=getchar();
d=getchar();
cout< cout< cout< cout< 输入abc,输出abc,d为换行符 要想全读取需要while循环中{d=getchar();} getchar有一个int型的返回值.当程序调用getchar时.程序就等着用户按键.用户输入的字符被存放在键盘缓冲区中.直到用户按回车为止(回车字符也放在缓冲区中).当用户键入回车之后,getchar才开始从stdin流中每次读入一个字符.getchar函数的返回值是用户输入的第一个字符的ASCII码,如出错返回-1,且将用户输入的字符回显到屏幕.如用户在按回车之前输入了不止一个字符,其他字符会保留在键盘缓存区中,等待后续getchar调用读取.也就是说,后续的getchar调用不会等待用户按键,而直接读取缓冲区中的字符,直到缓冲区中的字符读完为后,才等待用户按键. 注意:想用getchar就必须先清空以前的,在前面加一个getchar(),要么就可以读掉回车符,下面再用getchar 2.char*s与s[]的等价 3.字符串转换成int,int换成字符串 通常在 int value 被转换的整数,char *string 转换后储存的字符数组,int radix 转换进制数,如2,8,10,16 进制等。 在 atof(将字符串转换成浮点型数) 相关函数atoi,atol,strtod,strtol,strtoul 表头文件#include sprintf 最常见的应用之一莫过于把整数打印到字符串中,所以,sprintf 在大多数场合可以替代 itoa。 如: //把整数123 打印成一个字符串保存在s 中。 sprintf(s, "%d", 123); //产生"123" 可以指定宽度,不足的左边补空格: sprintf(s, "%8d%8d", 123, 4567); //产生:" 123 4567" 当然也可以左对齐: sprintf(s, "%-8d%8d", 123, 4567); //产生:"123 4567" 也可以按照16 进制打印: sprintf(s, "%8x", 4567); //小写16 进制,宽度占8 个位置,右对齐 sprintf(s, "%-8X", 4568); //大写16 进制,宽度占8 个位置,左对齐 这样,一个整数的16 进制字符串就很容易得到,但我们在打印16 进制内容时,通常想要一种左边补0 的等宽格式,那该怎么做呢?很简单,在表示宽度的数字前面加个0 就可以了。 sprintf(s, "%08X", 4567); //产生:"000011D7" 上面以”%d”进行的10 进制打印同样也可以使用这种左边补0 的方式。 这里要注意一个符号扩展的问题:比如,假如我们想打印短整数(short)-1 的内存16 进制表示形式,在Win32 平台上,一个short 型占2 个字节,所以我们自然希望用4 个16 进制数字来打印它: short si = -1; sprintf(s, "%04X", si); 产生“FFFFFFFF”,怎么回事?因为spritnf 是个变参函数,除了前面两个参数之外,后面的参数都不是类型安全的,函数更没有办法仅仅通过一个“%X”就能得知当初函数调用前参数压栈时被压进来的到底是个4 字节的整数还是个2 字节的短整数,所以采取了统一4 字节的处理方式,导致参数压栈时做了符号扩展,扩展成了32 位的整数-1,打印时4 个位置不够了,就把32 位整数-1 的8 位16 进制都打印出来了。 4.字符转成数字,数字转成字符 ch=ch-'0'; //这个减去一个字符'0'就转换成数字了,也可以减去48,因为‘0’的assic码是48. ch=ch+'0' 这个加上一个字符'0'就转换成字符了 字符变成整数:sum=sum*10+p[i]-…0?;1234转换就是1234 整数变成字符:p[i]=n%10+?0?;n/=10 1234转换就是4321需要进行逆序 整数逆序:sum=sum*10+n%10;n/=10 122输出221 5. 变量不能跟函数同名 否则会出现error C2064: 项不会计算为接受2 个参数的函数 6.定义一个未知长度的数组 如果给出的是个长度为n的int数组,那么不能用int a[n]来做。需要用 Int * a=(int *)malloc(sizeof(int)*n)才可以。 7.大写转小写的方式 pOutputStr[i]=pInputStr[i]+32;若是换成小写字母后的第五个字母,加上37即可。或者是加上('a' - 'A')-('V' - 'A'); 8.建立链表的时候,注意处理好表头 首先移动指针p指向首地址,开辟一个s,输入数据后,将s连到p上,接着移动指针p开始移动,注意最后的时候,将首地址head指向第一个数据。Head=head->next 9.c中分隔字符串的函数是strtok函数 char * strtok (char * str, const char * delimiters); 函数说明 strtok()用来将字符串分割成一个个片段。参数str 指向欲分割的字符串,参数delimiters 则为 分割字符串,当strtok()在参数str的字符串中发现到参数delimiters的分割字符时则会将该 字符改为'\0'字符。在第一次调用时,strtok()必需给予参数str字符串,往后的调用则将参数 str设置成NULL。每次调用成功则返回下一个分割后的字符串指针。 char *s[100]; for(int n3=0;n3<100;n3++) { s[n3]=(char *)malloc(20*sizeof(char)); // memset(s[n3], 0, 20 ); }//字符串数组使用前一定要给每一个字符串分配内存。 const char * split =" "; char *p={0}; int i=0; p = strtok (ms,split); while(p!=NULL) { strcpy(s[i],p); i++; p = strtok(NULL,split); } 还可以多个字符分隔:改成const char * split = ",*"; //用逗号(,)和星号(*)对字符串进行分割 此函数用时经常会出现错误指针的问题,尤其是程序中的p指针,虽然是错指针,但是不影响后面的结果。 字符串数组使用前一定要给每一个字符串分配内存。否则会出现“写入位置0x01037871 时发生访问冲突”。 10. 在Debug 模式下未初始化的变量的值 VC 、VS会默认把未初始化的栈内存按字节全部填成0xcc,当字符串看,即0xcccc就是烫烫烫烫……; 把未初始化的堆内存全部填成0xcd,当字符串看,即0xcccc就是屯屯屯屯……;11.strncmp与strncpy,memcpy,substr 11.1 用来比较两个字符串的某几个字符串是不是相等。 函数名: strncmp 功能: 串比较用法: int strncmp(char *str1, char *str2, int maxlen); 说明:此函数功能即比较字符串str1和str2的前maxlen个字符。如果前maxlen字节完全相等,返回值就=0;在前maxlen字节比较过程中,如果出现str1[n]与str2[n]不等,则返回(str1[n]-str2[n])。 char* sss[9] = {"yi", "er", "san", "si", "wu", "liu", "qi", "ba", "jiu"}; char *str="yier"; for(int j=0;j<9;j++) {if(strncmp(str+2,sss[j],2)==0) cout< 这个函数就就可以比较str中的er两个字符是不是也在sss数组中。 同理:char *p="dfsdfsdf"; char s[10]; strncpy(s,p+2,2); s[2]='\0'; cout< 那么s也将输出sd。 这边的关键用法就是str+2后还是一个指针,他指向str的后两位以后的字符数组 由于这个特性,我们的strcmp函数还可以这么用char *str="yier"; char *str2="er";此时调用strcmp(str+2,str2)也可以等于0 11.2 memcpy实现的就是strncpy的功能。void *memcpy(void *dest, const void *src, int n); 由src指向地址为起始地址的连续n个字节的数据复制到以dest指向地址为起始地址的空间内。 两者的区别: 1.source和destin所指内存区域不能重叠,函数返回指向destin的指针。 2.与strcpy相比,memcpy并不是遇到'\0'就结束,而是一定会拷贝完n个字节。 3.如果目标数组destin本身已有数据,执行memcpy()后,将覆盖原有数据(最多覆盖n)。如果要追加数据,则每次执行memcpy后,要将目标数组地址增加到你要追加数据的地址。//注意,source和destin都不一定是数组,任意的可读写的空间均可。 同理,substr也能实现取字符串的功能。a.substr(i,n) const; 功能:从一个字符串复制一个从指定位置开始,并具有指定长度的子字符串。从a[i]开始,取出n个字符。但是c中没有这个函数可用。 11.3 注意对字符串数组进行操作时,需要对字符串数组开辟空间 char *s[100]; for(int i=0;i<100;i++) { s[i]=(char *)malloc(20*sizeof(char));//每个字符串开辟20个字节 } for(int n1=0;n1 strcpy(s[n1],a+n1);//这个s[n1]指的是字符串的指针,是第n1个字符串的指针,会将字符数组a中a[n1]及其以后的字符赋给s[n1] 11.4.strncpy 跟strcpy一样。就是多了个字符字数的限制。 strcpy(字符数组1,字符数组2) 字符串复制函数,是将字符串一个字符一个字符的复制,直到遇到'\0 '字符为止。其中,对'\0 '字符也一起复制。 strncpy(字符数组1,字符串2,字符数) strncpy函数是将字符串2中前n个字符复制到字符数组1中,并给字符数组1加上一个‘\0’。如果需要复制字符串2中前面的若干个字符,则可指出需要复制的字符数。其调用形式如下:举例:strncpy(str1, str2, 2) ; 把str2中头上二个字符复制到str1中去,str1再加一个结束‘\0’。 12.将一个数字i倒序输出的方法 十进制的倒序 while(i) { n=n*10+i%10; i/=10; } 二进制的倒序: while(a) { b[i]=(a & 1); i++; a=a>>1; } for(int j=0;j c=c*2+b[j]; 13.关于链表建立的几点说明 如果链表的数据是人工输入的,那么就先需要一个表头,这个表头是移动指针的初值,但是这个是没有数据的,等着链表建完后,就head=head->next,将head指向第一个有数据的值。如果链表数据是有顺序的(比如0----10),可以先不写这个表头。 14.判断是不是2^n的方法 if(0==(a[i]&(a[i]-1))) 15.位运算 例如一个数and 1的结果就是取二进制的最末位。例如一个数or 1的结果就是把二进制最末位强行变成1。https://www.doczj.com/doc/4b7815019.html,/view/379209.htm 因为这些特性,我们就可以一次取出一个二进制,存在一个数组中,可以进行二进制的反置操作。 while(a) // { // b[i]=(a & 1); // i++; // a=a>>1;} 16.函数名: strstr 函数原型:extern char *strstr(char *str1, char *str2); 功能:找出str2字符串在str1字符串中第一次出现的位置(不包括str2的串结束符)。 返回值:返回该位置的指针,如找不到,返回空指针。 可以用这个函数找到相同的字符串,而不用strcmp法了。 其实用if(strncmp(b,a+j+k,i)==0){ m++;}查找与b相等的字符串 跟 while((t = strstr(str2,temp)) != NULL) {sum++; str2 = t+j; } 效果是一样 17.二维数组的参数传递 可以用二维数组名作为实参或者形参,在被调用函数中对形参数组定义时可以可以指定所有维数的大小,也可以省略第一维的大小说明。如: void Func(int array[3][10]); void Func(int array[][10]); 二者都是合法而且等价,但是不能把第二维或者更高维的大小省略,如下面的定义是不合法的: void Func(int array[][]); 将二维数组当作参数的时候,必须指明所有维数大小或者省略第一维的,但是不能省略第二维或者更高维的大小,这是由编译器原理限制的。在学编译原理这么课程的时候知道编译器是这样处理数组的: 对于数组int p[m][n]; 如果要取p[i][j]的值(i>=0 && i p + i*n + j; 从以上可以看出,如果我们省略了第二维或者更高维的大小,编译器将不知道如何正确的寻址。但是我们在编写程序的时候却需要用到各个维数都不固定的二维数组作为参数,这就难办了,编译器不能识别阿,怎么办呢?不要着急,编译器虽然不能识别,但是我们完全可以不把它当作一个二维数组,而是把它当作一个普通的指针,再另外加上两个参数指明各个维数,然后我们为二维数组手工寻址,这样就达到了将二维数组作为函数的参数传递的目的,根据这个思想,我们可以把维数固定的参数变为维数随即的参数, 18.最大公共字符串的问题 四次循环:第一次循环长度,第二个循环公共字符串在字符数组A的首位置,第三个循环公共字符串在字符数组B的首位置,第四个循环是看两个数组中有没有符合条件的 二次循环:第一个循环字符数组A,第二个循环字符数组B。在循环内部,判断前两个循环的字符有无相等的:如果有一个字符数组从第一个字符就与另一个字符数组中有相同的,那么记下相同的字符数,因为是第一个字符,所以肯定是公共字符串的首位置。如果不是从第一个字符就相等,那么就需要才才c[i][j]=c[i-1][i-1],这样就能找到很多连续字符相等的,找出连续字符相等的最长的即可 19.大整数的加减法 大整数运算与普通运算的不同:当参与运算的操作数超出了整形int或者实型double的储存范围时,就必须采用其他方法,常用字符串或者数组来保存。 若无特殊说明,保存大整数约定:低位在前,高位在后。例如用string s来表示整数12345,则s=“54321”。 for (int j=0; j { A[j] = A[j]+B[j]; A[j+1] = A[j+1]+A[j]/10;//先把进的位加到A中 A[j] = A[j]%10; } 这样的处理很精妙,因为最后一位的A[j+1]也能同时产生。 20.字符数组与字符串区别 最明显的区别就是字符串会自动给加上?\0?。而字符数组需要自己加上。因此我们在定义一个字符数组的时候注意要给‘\0’留出位置。像char a[2]={'a','b'};这样的,就是错误的。因为数组a[2]的元素只有a[0],a[1],没有a[2]的存在,因此此时a[1]需要为?\0?才行。 21.i\0标准输入输出 C语言要求系统为每个程序提供两个指针,这两个指针分别指向键盘和屏幕,并将这两个指针命名为:stdin和stdout.这两个指针就是所谓的标准输入和标准输出。C语言提供了专门用于从标准输入获取信息和向标准输出显示信息的函数,即scanf()和printf().此时,从键盘获取输入,向屏幕显示信息。使用scanf()和printf()时,无需向其提供文件指针,这是因为它们知道所需的文件指针,它们操作的对象便是标准输入和标准输出所指向的文件。而fprintf(stdout, "Please input a string: ");需要将标准输出流的指针传进去 22.字符串的几个计算总结 22.1查找一个字符串中出现次数最小的字符。 思路:将字符存在一个结构体数组中,这个结构体有两个元素,一个是字符,一个是出现的次数,初始时次数都为0。然后遍历整个数组,进行次数的赋值。程序如下: for(int k=0;k // for(int l=0;l // { // if (sb[k].a==sb[l].a) // sb[k].count+=1; // } 经过这个循环以后,结构体数组中内容就是各个字符,以及他们出现的次数,找出最小的那个,并记录下最小次数所在的结构体数组的下标,这样就可以找到这个元素了。 min=sb[0]; // // int m=0; // for(m=0;m // { // // if(sb[m].count // { // min=sb[m]; // dex1=m; // } // } 注意的是,如果出现两个字符次数相同的情况,只能输出最先出现的那个。 还有一种简单的方法: #include #include #include using namespace std; void main() {int a[128]; memset(a,0,sizeof(a));//注意,字符数不能直接写128,否则32-127位是一个大的负数,不是0。string s="gdssdsgs"; int n=s.size(); int i = 0; for ( i = 0; i { int p=s[i];//强制转换,将输出assic码 a[p]+=1;} for (int j = 0;j<128; j++ ) {if(a[j]>0 )