C和C++学习心得(更新中)

1.关于库函数的调用,使用strcmp(),strcpy(),strcat()等函数,需要加上#include,还有值得注意的一点是,在调用strcpy时,假设你写了正常的调用语句,如strcpy(str1,str2),编译器仍会报错,则可能需要使用更安全的strcpy_s() 相关详解

2.字符的输入可使用cin.get(),和C中gets()函数的用法差不多,如ar=cin.get(),可用于在多组字符串的输入中吸收无关字符(如输入数据后的回车击键)。而字符串的输入可以使用cin.getline()函数,该函数使用规则:cin.getline()实际上有三个参数,cin.getline(接受字符串到m,接受个数5,结束字符),当第三个参数省略时,系统默认为'\0' 是'/n'吧。相关详解

示例代码

int repeat,i;
char c,ar,str[100];
cin>>repeat;//输入循环次数
for(i=1;i<=repeat;i++){
	ar=cin.get();//吸收回车的击键
	cin.getline(t,100);
	cin>>m;
	strmcpy(s,t,m);//调用一个自定义函数
}

3.字符和字符串的输出,使用cout即可,输出字符串记得要用字符数组的首地址(即函数名)。值得一提的是在C语言中,%g的作用(详解)
还有就是强制转换(type)可以用于浮点数的取整数部分的运算,下面的代码可以将实数分为整数部分和非整数部分两部分。

#include <stdio.h>
void splitfloat( float x, int *intpart, float *fracpart );//用于将实数拆分成整数部分和小数部分
int main()
{
    float x, fracpart;
    int intpart;
    scanf("%f", &x);
    splitfloat(x, &intpart, &fracpart);
    printf("The integer part is %d\n", intpart);
    printf("The fractional part is %g\n", fracpart);
    return 0;
}
void splitfloat( float x, int *intpart, float *fracpart )
{
	int i,len=0;
	float store;
	*intpart=0;
	if(0.0<=x&&x<1.0){
		*fracpart=x;
	}
	else{
		*intpart=(int)x;
		*fracpart=x-*intpart;
	}
}

4.在这里提一下,指针数组的使用。示例如下:

const char*week[7]={"Sunday","Monday","Tuesday","Wednesday","Thursday","Friday","Saturday"};

其实在这里我有一些疑惑,把char*前的const去掉,编译器会报错????相关用法和说明
5.无形参和实参的自定义函数使用
如无返回值:

声明:void a(void);
定义:void a(void){}
调用:a(); 或  a(void);

有返回值就把void换成相应类型即可
6.关于string类型(相关详细内容)
(和数组很像)甚至可以如下这么操作:

string name="ycy"
name="This is"+name;//输出 This is ycy

还可以使用函数

#include <iostream>
#include <string>
 
using namespace std;
 
int main()
{
    string strDemo = "I am";
 
    strDemo.insert(4, " good.");
 
    cout << "strDemo is: " << strDemo << endl;
 
    return 0;
}

下面这段代码可以完成string类型的a与char类型的temp数组的连接,并把得到的新字符串储存在a中
字符串(字符数组和string都可)的连接可使用strcat函数:strcat(str1,str2),把str1的尾和str2的头连接,并把新字符串储存到str1中。
string类型的连接:str1=str1+str2(str1必须放前面)

#include<iostream>
#include<string>
using namespace std;
string a="Hello",b="1";
char temp[100]="World";
int main()
{
	b.assign(temp, sizeof(temp));//利用此语句可将temp数组中储存的字符串赋给string类型的b(#include<string>)
	cout<<b<<endl;
	a=temp+a;
	cout<<a;
	return 0;
}

7.动态内存分配和释放
·void*malloc(unsigned size)和free()
具体使用

int *p;
p=(int*)malloc(sizeof(int));//申请一个int类型的内存空间
free(p)//用完后记得释放
p=(int*)malloc(n*sizeof(int));//申请n个int类型数据的内存空间,此时p相当于一个长度为n的数组的首地址
free(p)//用完后记得释放

·也可使用new和delete关键字 new和delete的用法

int*p;
p=new int;//直接申请一个int 类型的数据内存空间
delete p;//释放内存空间
p=new int[num]//申请n个int类型数据的内存空间,此时p相当于一个长度为n的数组的首地址(num为一个已知数?)
delete p;

使用new关键字动态申请一个三维数组

float (* fp)[25][10]; 
fp=new float[10][25][10];

8.链表的使用注意事项
若单链表非空,头指针head一定指向单链表中的第一个节点。如果有头结点,则head指向头结点。
有头结点的单链表永远非空(头结点:head=头结点的地址,head->next=第一个有存实质性内容的节点,头结点本身的数据域不存啥有用的东西),有头结点的话,在删除,插入等操作中,就不需要判断所在的节点位置情况,可使用统一的处理方法,比较方便。
没有头结点的单链表,单链表为空时,head=NULL。
在操作单链表时,要特别注意不要使用越界,特别注意在遍历链表或搜寻特定节点时,p,p->next是否都不能为NULL。
在对链表中的结点进行排序时,记得只需置换数值域的数据。

对链表的几种基本操作

#include <iostream>
#include<malloc.h>
using namespace std;
struct Node {
    int data;
    Node* next;
};
void IniNode(Node** head)//准初始化函数
{
    (*head) = (Node*)malloc(sizeof(Node));
    if ((*head) == NULL)
    {
        cout << "Fail!" << endl;
        exit(0);
    }
    else cout << "Succeed!" << endl;
    (*head)->next = NULL;//该链表有头结点
}
Node* GetNode(int item)//创建动态节点(存有数据)
{
    Node* newp = (Node*)malloc(sizeof(Node));
    if (!newp)
    {
        cout << "Overflow" << endl;
        exit(0);
    }
    newp->data = item;
    newp->next = NULL;
    return newp;
}
void InsetAfter(Node* p, Node* newp)//后插运算
{
    newp->next =p->next;
    p->next = newp;
}
void ListInsert(Node* head, int item)//将新增链表结点按升序插入
{
    Node  *p = head,*newp;
    newp = GetNode(item);
    while (p->next) 
    {
        if (p->next->data < item)
            p = p->next;
        else break;
    }
    InsetAfter(p, newp);
    
}
Node* DeleteAfter(Node* p)//后删操作,删除p后的结点
{
    Node* temp = p->next;
    if (temp)
        p->next = temp->next;
    return temp;
}
Node* FindNode(const Node* h, int item)//查找指定结点
{
    Node* p = h->next;
    while (p)
    {
        if (p->data == item)
            break;
        p = p->next;
    }
    return p;
}
void ListClear(Node* h)//清表操作,清到只剩一个头结点的空单链表
{
    Node* p = DeleteAfter(h);
    while (p)
    {
        free(p);
        p = DeleteAfter(h);//此处注意,删的结点一直是head头结点后的结点
    }
    cout << "Clear!" << endl;
}
void Revert(Node* h)//逆置链表操作
{
    Node* rear = h->next,*p;
    while (rear->next)
    {
        p = DeleteAfter(rear);
        InsetAfter(h, p);
    }
}
void disp(Node* head)//展示链表
{
    for (Node* ptr = head; ptr->next; ptr = ptr->next)
    {
        cout << ptr->next->data << endl;
    }
}
int main()
{
    Node *head = NULL,*p=NULL;
    int num[5] = { 1,3,5,4,2};
    IniNode(&head);
    for (int i = 0; i < 5; i++) 
    {
        ListInsert(head, num[i]);
    }
    disp(head);
    cout << endl;
    Revert(head);
    disp(head);
    ListClear(head);
    return 0;
}


9.初始化数组
方法一:在定义int类型数组时,如果写成:

int a[1000]={1};

此时,数组中除了a[0]=1,其他元素全部被系统初始化为0
方法二:memset()函数,可用于多次初始化 memset函数(初始化) c++语言中memset函数怎么用?

#include<stdio.h>
#include<string.h>
int main
{
   int a[100];
   memset(a,0,sizeof(a));
   return 0;
}

9.关于常量的使用
·宏定义
用 #define 定义标识符的一般形式为:

#define  标识符  常量   //注意, 最后没有分号,标识符常用大写字母组成

·使用const关键字
整型常量定义:如:

const int MAX=1;

实型常量定义:如

//C编译系统对实型常量不分float和double,都作double处理以更精确,也可以在实型常量后面加上字母f或F来指定其为单精度实型(float)
//3.1415(double型实型常量)3.1415f(float型实型常量) .87L(long double型实型常量)
const double FIRST=3.1415926;
const double SECOND=3.1415926f;

10.关于inline关键字的使用 inline关键字的用法详解
·声明内联函数时使用关键字inline
格式为:

inline 返回值类型 函数名(形参表)
{
    函数体
}

声明和函数体需要出现在调用之前,不允许先给出函数原型,在调用之后才给出函数体

posted @ 2020-03-08 20:40  枭魈  阅读(226)  评论(0编辑  收藏  举报