1. 程式人生 > 其它 >gzip C#/.NET EnhancedSoapHttpClientProtocol.cs

gzip C#/.NET EnhancedSoapHttpClientProtocol.cs

一、結構的定義

結構是有struct關鍵字和結構模板以及結構中的成員組成:

struct names 
{
	int ma;
	double line;
	char file[30];
	char sie;
}; 

在上面面的程式碼中,names叫做結構模板的名稱,整個所表示的就是結構模板,ma,line,file[30],sie叫做這個結構的成員。

二、宣告結構模板

1.宣告結構模板一般放在主函式的外部進行定義宣告,結構模板中的成員之間要用分號分隔開。

2.並且,在宣告結構模板的時候,每一個成員都不能進行初始化。

3.宣告結構模板不需要在模板名稱後面加等於號。

重點:

在結構模板中定義宣告字串的時候,用陣列形式,而不用字串形式,原因是陣列形式宣告的字串會儲存在結構變數所在的記憶體中,而用指標形式宣告的字串不會儲存在結構變數記憶體中,結構變數記憶體中儲存的只是字串的地址。

三、宣告結構變數

宣告結構變數的前提是要有結構模板,通過結構模板來進行結構變數的宣告。

#include	<stdio.h>

struct names 
{
	int ma;
	double line;
	char file[30];
	char sie;
}; 

int	main(void)
{
	struct names hold=
	{
		3,
		2.3,
		"I love Micy very much!",
		'A',
	};
}

在上面程式碼中,首先在主函式外面定義聲明瞭names結構模板,然後在主函式裡面定義聲明瞭以names為結構模板的結構變數hold,因此hold在進行初始化的時候要遵循names結構模板,並且每個成員之間用逗號隔開,這和定義宣告結構模板不相同。

由於結構變數也是變數,因此結構變數也遵循前面講的儲存方式。

宣告結構變數,要在結構變數後面加等於號。

四、初始化結構變數以及對結構變數賦值

初始化結構變數有三種方式:

1)對各成員都進行初始化
struct names 
{
	int ma;
	double line;
	char file[30];
	char sie;
}; 

int	main(void)
{
	struct names hold=
	{
		3,
		2.3,
		"I love Micy very much!",
		'A',
	};
}

按照個成員之間的順序,分別對每個成員都進行初始化,並且初始化後個成員之間用逗號隔開。

2)用相同結構模板的結構變數進行初始化
struct names 
{
	int ma;
	double line;
	char file[30];
	char sie;
}; 

int	main(void)
{
	struct names hold= 
	{
		3,
		2.3,
		"I love Micy very much!",
		'A',
	};
	struct names buge=hold;

此時,結構變數buge和結構變數hold的內容就完全一樣了。

3)指定初始化
//隨機
#include	<stdio.h>

struct names 
{
	int ma;
	double line;
	char file[30];
	char sie;
	char games[20];
}; 

int	main(void)
{
	struct names hold=
	{
		.line=23.45,
		.file="I love Micy very much!",
		'S',
	};
	printf("print hold.line :%.2f\nprint hold.file :%s\n",hold.line,hold.file);
	printf("print hold.sie :%c\nprint hold.ma :%d\n",hold.sie,hold.ma);
	printf("print hold.games :%s\n",hold.games);
	return 0;
}

列印結果:

print hold.line :23.45
print hold.file :I love Micy very much!
print hold.sie :S
print hold.ma :0
print hold.games :

在hold的初始化中,指定了line,file這兩個成員的初始化,(注意指定初始化要在指定的成員前面加上點運算子),因此在列印這兩個成員的值的時候,打印出來的就是初始化的值,而在初始化中有'A'這個值,這個值會被初始化給file成員後面的成員(按順序),未被初始化的成員會自動被初始化成0或者空字元。

4)對結構變數進行賦值
1.用相同結構模板的變數進行賦值
//用相同結構模板的結構變數進行賦值
#include	<stdio.h>

struct names
{
	int ma;
	double games;
	char datas[30];	
};

int main(void)
{
	struct names holds=
	{
		3,
		4.3,
		"I love Micy very much!",	
	};
	struct names memb=holds;
	
	printf("print ma in memb :%d\n",memb.ma);
	printf("print games in memb :%.2f\n",memb.games);
	printf("print datas in memb :%s\n",memb.datas);
	
	return 0;	
} 

列印結果:

print ma in memb :3
print games in memb :4.30
print datas in memb :I love Micy very much!

2.用結構常量進行賦值
//使用結構常量進行賦值操作
#include	<stdio.h>

struct names 
{
	int ma;
	double games;
	char datas[30];
};

int main(void)
{
	struct names hold=(struct names){
		3,
		4.5,
		"I love Micy very much!",
	};
	
	printf("print ma in hold :%d\n",hold.ma);
	printf("print games in hold :%.2f\n",hold.games);
	printf("print datas in hold :%s\n",hold.datas);
	
	return 0;	
} 

列印結果:

print ma in hold :3
print games in hold :4.50
print datas in hold :I love Micy very much!

3.指定成員進行賦值
//指定結構成員進行賦值操作
#include	<stdio.h>

struct names
{
	int ma;
	double games;
	char datas[30];	
};

int main(void)
{
	struct names hold;
	printf("enter ma in hold:\n");
	scanf("%d",&hold.ma);
	printf("print the ma in hold :%d\n",hold.ma);
	printf("print the games in hold :%.2f",hold.games);
	
	return 0; 
} 

列印結果:

enter ma in hold:
3
print the ma in hold :3
print the games in hold :0.00

可以發現,賦值操作和初始化有類似的地方,指定賦值之後,沒有值的成員就會初始化成0或者空字元,指定初始化也是如此。

五、訪問結構成員和指向結構變數的指標

1)指向結構變數的指標:

1.宣告結構模板,系統並不會為結構模板分配記憶體,也就是說不佔據記憶體。(由於結構模板相當於資料型別,因此使用sizeof()運算子能夠知道這個結構模板的大小),而宣告結構變數後,這個變數會佔據記憶體,這個記憶體的大小就是結構模板的大小,這塊記憶體是由各個成員的記憶體按順序組成的。(可以理解為各個成員都分配在結構變數這塊記憶體上)

2.由於這個變數擁有記憶體,也就擁有地址,因此可以宣告一個指標,去指向這塊記憶體(指標所儲存的一般都是這塊記憶體首位元組的地址)

如果要用指標指向他的成員,就用間接成員運算子->進行連線。

//隨機
#include	<stdio.h>

struct names 
{
	int ma;
	double line;
	char file[30];
	char sie;
	char games[40];
}; 

int	main(void)
{
	struct names hold=
	{
		.line=23.45,
		.file="I love Micy very much!",
		'S',
		"Love is a wonderful thing!",
	};
	struct names *ptst=&hold;
	printf("print the hold.ma:%d\nprint the hold.line:%.2f\n",ptst->ma,ptst->line);
	printf("print the hold.file:%s\nprint the hold.sie:%c\n",ptst->file,ptst->sie);
	printf("print the hold.games:%s\n",ptst->games);
	
	return 0;
}

列印結果:

print the hold.ma:0
print the hold.line:23.45
print the hold.file:I love Micy very much!
print the hold.sie:S
print the hold.games:Love is a wonderful thing!

*重點:

1.需要注意的是:ptst->ma代表的是變數名稱,即結構成員ma的名稱,變數名稱通過相應的轉換說明能直接打印出內容。

ptst->file代表的是陣列名稱(結構成員file[30]這個字串陣列的名稱),因此ptst->file表示的是陣列中首字元的地址,使用%s轉換說明能夠打印出整個字串。

2.hold是變數名稱,必須進行取地址操作才能夠賦值給ptst。

2)訪問結構成員

訪問結構有兩種方式,第一種是通過間接成員運算子->,這個運算子只能用在指標上面;第二種是通過點運算子,不能用在指標上面。

//
#include	<stdio.h>

struct names
{
	int ma;
	char games;
	double jir;
	char dates[30];
};
int main(void)
{
	struct names hold=
	{
		1,
		'a',
		2.3,
		"I love yoga very much!",
	};
	struct names *ptstruct=&hold;
	printf("print the  members in the name of struct:\n");
	printf("ma=%d\n",hold.ma);
	printf("games=%c\n",hold.games);
	printf("jir=%.1f\n",hold.jir);//上面這三個都表示的是結構中的變數。 
	printf("datas=%s\n\n",hold.dates);//在這裡hold.datas表示的是這個結構中陣列首元素的地址。
	
	printf("print the members in point:\n");
	printf("ma=%d\n",ptstruct->ma);
	printf("games=%c\n",ptstruct->games);
	printf("jir=%.1f\n",ptstruct->jir);
	printf("datas=%s\n",ptstruct->dates);
	
	return	0;
}

列印結果如下:

print the members in the name of struct:
ma=1
games=a
jir=2.3
datas=I love yoga very much!

print the members in point:
ma=1
games=a
jir=2.3
datas=I love yoga very much!

1.使用結構變數名稱

使用結構變數名稱必須使用點運算子,訪問哪個成員,就在點後面加上哪個成員的名稱。如果是陣列名稱,代表的是陣列首元素的地址。

2.使用指向結構變數的指標

使用指向結構變數的指標必須使用間接成員運算子,訪問那個成員就在->後面加上哪個成員的名稱。如果是陣列名稱,代表陣列首元素的地址。

六、結構常量

對一個結構變數進行賦值操作的時候,可以將結構常量賦值給這個變數(避免另建立新的結構變數)

#include	<stdio.h>

struct names
{
	int ma;
	double games;
	char datas[30];
};

int main(void)
{
	struct names hold;
	hold=(struct names){
		2,
		3.4,
		"I love Micy very much!",
	};
	
	printf("ma=%d\n",hold.ma);
	printf("games=%.1f\n",hold.games);
	printf("datas=%s\n",hold.datas);
	
	return 0;
}

列印結果:

ma=2
games=3.4
datas=I love Micy very much!

結構常量的寫法:不需要設定出結構名稱,只需要把結構模板名稱加上括號即可,這樣可以避免再設定一個結構變數來進行賦值。

七、結構陣列

結構陣列就是多個擁有同一結構模板的變數組合。

//定義宣告結構陣列
#include	<stdio.h>

struct names
{
	int ma;
	double games;
	char datas[30];	
};

int main(void)
{
	struct names trains[5];
	trains[0]=(struct names){
		2,
		3.4,
		"I love Micy very much!",
	};
	printf("ma=%d\n",trains[0].ma);
	printf("games=%.1f\n",trains[0].games);
	printf("datas=%s\n",trains[0].datas);
	
	return 0;
} 

列印結果如下:

ma=2
games=3.4
datas=I love Micy very much!

在上面的程式碼中,聲明瞭一個具有names結構模板的結構陣列,這個陣列中擁有五個元素(結構變數),每個元素都是names的結構模板。

八、結構與函式之間聯絡方式

1)通過結構指標進行聯絡

把指標作為被調函式的形參,通過指標把原始結構的地址傳遞給被調函式。

//結構指標與被調函式
#include	<stdio.h>

struct names
{
	int ma;
	double games;
	char datas[30];	
};

void sum_123(struct names *pts);//由於引數中使用了結構模板,所以要把結構模板的宣告放在上面,這是易出錯的地方。 
void read_(struct names *pts);

int main(void)
{
	struct names hold;
	hold=(struct names){
		2,
		3.4,
		"I love Micy very much!",
	};
	struct names *pts=&hold;
	
	sum_123(pts);
	read_(&hold);
	
	return 0;
}

void sum_123(struct names *pts)//這裡表示的是隻能傳遞指向擁有names結構模板的變數的指標(或地址) 
{
	double sum=(pts->ma)+(double)(pts->games);
	printf("print the sum is :%.2f\n",sum);
	
	return;
}

void read_(struct names *pts)//可以傳遞結構變數指標,或者結構變數地址 
{
	printf("The characters is :%s\n",pts->datas);
	
	return;
}

列印結果:

print the sum is :5.40
The characters is :I love Micy very much!

被調函式中的形參接受的是結構變數的指標或者結構變數的地址,這是呼叫原始資料。

2)通過結構變數(常量)進行聯絡

除了結構變數的指標或者地址能夠作為實際引數傳遞,結構變數本身(結構常量)也能夠作為實際引數進行傳遞。

//結構變數(結構常量)本身作為實際引數傳遞
#include	<stdio.h>

struct names
{
	int ma;
	double games;
	char datas[30];	
};

void sum_(struct names data);
void read_(struct names data);

int main(void)
{
	struct names hold=
	{
		2,
		3.4,
		"I love Micy very much!",
	};
	
	sum_(hold);
	read_(hold);
	
	return 0;
} 

void sum_(struct names data)//這個引數表示接受一個以names為結構模板的結構變數作為實際引數 
{
	double sum=(double)data.ma+data.games;
	
	printf("%.2f\n",sum);
	
	return;
}
void read_(struct names data)
{
	printf("%s\n",data.datas);
	
	return;
}

列印結果如下:

5.40
I love Micy very much!

分析一下:指標作為實際引數進行傳遞的時候,被調函式通過這個地址直接訪問原始資料,而直接將結構變數本身作為實際引數的話,會複製一個副本傳遞給被調函式,被調函式無法修改原始結構變數(因為被調函式中接受的只是一個副本)。

3)直接將結構成員傳遞給被調函式

注意:這個結構成員不能是陣列,但可以是單一的資料型別,比如int、double、char或者指標或者陣列中的一個元素。

//傳遞結構成員
#include	<stdio.h>

struct names
{
	int ma;
	double games;
	char datas[30];	
};
void sum_(int n);
void read_(double n);
void check_(char n);

int main(void)
{
	struct names hold=
	{
		2,
		3.4,
		"I love Micy very much!",
	};
	
	sum_(hold.ma);
	read_(hold.games);
	check_(hold.datas[0]);
	return 0;
} 
void sum_(int n)
{
	n++;
	printf("print the value of the member :%d\n",n);
	
	return;
}
void read_(double n)
{
	n++;
	printf("print the value of the member :%.2f\n",n);
	
	return;
}
void check_(char n)
{
	printf("print the value of the value :%c\n",n);
	
	return;	
} 

列印結果:

print the value of the member :3
print the value of the member :4.40
print the value of the value :I

如果成員作為實際引數傳遞的話,被調函式的形參應該符合成員的相應資料型別,並且只能傳遞具有單個值的資料型別。

4)總結

1.單一的傳遞結構成員不常用到

2.一般不直接傳遞結構變數本身,因為這樣會建立副本,佔據記憶體。

3.一般採用傳遞指標的方法,因為指標訪問的是原始資料本身,如果不希望指標更改資料,最好加上const關鍵字,const直接放在struct關鍵字之前就好。

九、結構陣列與函式之間的聯絡方式

結構陣列與函式的聯絡方式和普通陣列與函式的聯絡相同,都是通過指標進行聯絡,同樣可以寫成陣列形式和指標形式(本質上都是指標)。

1)陣列形式

//結構陣列和字串之間的聯絡
#include	<stdio.h>
#include	<string.h>

#define SIZE 5

struct names
{
	int ma;
	double games;
	char datas[30];	
};
struct names hold[SIZE];//在這裡面,陣列名稱代表的就是陣列首元素的地址,也就是指向結構的指標。 

void input_starray(struct names array[]);
void read_starray(struct names array[]);

int main(void)
{	
	input_starray(hold);
	read_starray(hold);
	
	return 0;	
}

void input_starray(struct names array[])//以陣列形式呈現形參,這個形參表示的是接受指向names為模板的結構變數的指標。 
{
	for (int i=0;i<SIZE;i++)
	{
		puts("Please enter a int value :");
		scanf("%d",&array[i].ma);
		puts("Please enter a double value :");
		scanf("%lf",&array[i].games)//需要注意的是,使用scanf()函式輸入double型別時,轉換說明使用%lf
		getchar();
		puts("Please enter a characters :");
		fgets(array[i].datas,30,stdin);
		{
			int length=strlen(array[i].datas);
			if (array[i].datas[length-1] == '\n')
			{
				array[i].datas[length-1] = '\0';
			}
			else
			{
				while (getchar() != '\n')
				{
					continue;
				}
			}
		}
	}
	
	return;
}

void read_starray(struct names array[])
{
	for (int i=0;i<SIZE;i++)
	{
		printf("\nThe %d group's value:\n",i+1);
		printf("%d\n",array[i].ma);
		printf("%.2f\n",array[i].games);
		puts(array[i].datas);	
	}
	
	return;	
} 

列印結果如下:

Please enter a int value :
1
Please enter a double value :
1.1
Please enter a characters :
qqq
Please enter a int value :
2
Please enter a double value :
2.2
Please enter a characters :
www
Please enter a int value :
3
Please enter a double value :
3.3
Please enter a characters :
eee
Please enter a int value :
4
Please enter a double value :
4.4
Please enter a characters :
rrr
Please enter a int value :
5
Please enter a double value :
5.5
Please enter a characters :
ttt

The 1 group's value:
1
1.10
qqq

The 2 group's value:
2
2.20
www

The 3 group's value:
3
3.30
eee

The 4 group's value:
4
4.40
rrr

The 5 group's value:
5
5.50
ttt

2)指標形式

//結構陣列指標形式引數
#include	<stdio.h>
#include	<string.h>

#define SIZE 5

struct names
{
	int ma;
	double games;
	char datas[30];	
};

struct names hold[SIZE];//在這裡面,陣列名稱代表的就是陣列首元素的地址,也就是指向結構的指標。
 
void input_starray(struct names *pts);
void read_starray(struct names *pts);

int main(void)
{
	struct names *pts=hold;//注意,在這裡,hold是陣列名,所以就是一個指標,儲存的是首元素的地址。
	input_starray(pts);
	read_starray(pts);
	
	return 0;	
}

void input_starray(struct names *pts)//以陣列形式呈現形參,這個形參表示的是接受指向names為模板的結構變數的指標。 
{
	for (int i=0;i<SIZE;i++)
	{
		puts("Please enter a int value :");
		scanf("%d",&(pts+i)->ma);//雖然用的是指標,但是指標訪問成員相當於還是成為一個成員對應的變數,因此要加取地址。 
		puts("Please enter a double value :");
		scanf("%lf",&(pts+i)->games);
		getchar();
		puts("Please enter a characters :");
		fgets((pts+i)->datas,30,stdin);//在這裡,指標訪問datas,所以表示的是陣列的陣列名,也就代表著陣列首元素地止。 
		{
			int length=strlen((pts+i)->datas);
			if ((pts+i)->datas[length-1] == '\n')
			{
				(pts+i)->datas[length-1] = '\0';
			}
			else
			{
				while (getchar() != '\n')
				{
					continue;
				}
			}
		}
	}
	
	return;
}

void read_starray(struct names *pts)
{
	for (int i=0;i<SIZE;i++)
	{
		printf("\nThe %d group's value:\n",i+1);
		printf("%d\n",(pts+i)->ma);
		printf("%.2f\n",(pts+i)->games);
		puts((pts+i)->datas);	
	}
	
	return;	
}  

列印結果如下:

Please enter a int value :
1
Please enter a double value :
1.1
Please enter a characters :
qqq
Please enter a int value :
2
Please enter a double value :
2.2
Please enter a characters :
www
Please enter a int value :
3
Please enter a double value :
3.3
Please enter a characters :
eee
Please enter a int value :
4
Please enter a double value :
4.4
Please enter a characters :
rrr
Please enter a int value :
5
Please enter a double value :
5.5
Please enter a characters :
ttt

The 1 group's value:
1
1.10
qqq

The 2 group's value:
2
2.20
www

The 3 group's value:
3
3.30
eee

The 4 group's value:
4
4.40
rrr

The 5 group's value:
5
5.50
ttt

3)總結

在上面的兩段程式碼中:

1.為什麼把陣列定義宣告放在外面:

原因是主函式在執行的時候所用的記憶體叫棧(zhan),棧的大小是有限制的,由於結構陣列是一種比較大的陣列,因此宣告在外部是一種比較常見的做法,這樣陣列就不會佔用主程式中的棧。

2.用指標訪問成員:

指標是訪問成員的一種方式,比如pts->names表示訪問的是結構中的names成員,如果names是個變數,那麼pts->names整體就表示這個變數,如果names是一個數組,那麼pts->names整體就表示陣列首元素的地址。

十、伸縮型陣列成員

在結構中,我們有一種特殊形式可以使用,那就是伸縮型陣列成員,在宣告結構模板的時候可以不去宣告陣列的大小。

1)使用伸縮型陣列成員的要求:

1.結構中只能使用一個伸縮型陣列成員;

2.結構中的伸縮型陣列成員必須位於結構的最末尾;

3.使用malloc()函式。

2)為什麼使用伸縮型陣列成員

1.首先,使用伸縮型陣列成員要用malloc()函式,該函式建立的是動態記憶體,不在棧中,對於成員非常多的結構,我們可以使用malloc函式(不具有伸縮型陣列成員的結構同樣能用malloc()函式)。

2.其次:可以自定義成員陣列的大小。(最重要的)

3)程式:

//伸縮型陣列成員的使用
#include	<stdio.h>
#include	<string.h>
#include	<stdlib.h>
 
struct names
{
	int ma;
	double games;
	char datas[];//由於要使用伸縮型結構成員,因此方括號中什麼也不加。	
};

void input_st(struct names *pt,int size);
void read_st(struct names *pt);

int main(void)
{
	int size;
	puts("Please enter the array's size you want:");
	scanf("%d",&size);
	
	struct names *pts;
	pts=malloc(sizeof(struct names)+size*sizeof(char));
	//在這裡,由於結構模板中的陣列沒有大小,所以struct names的大小不包含陣列,因此再加上想要的陣列大小,就是所需結構變數的大小
	//雖然使用malloc()建立的結構,pts是這個結構變數唯一的訪問方式,但是這個結構和普通結構完全一樣,訪問方式也完全一樣。
	input_st(pts,size);
	read_st(pts);
	
	free(pts);//養成好習慣,用完動態記憶體記得釋放掉。 
	
	return 0; 
}

void input_st(struct names *pt,int size)
{
	puts("Enter the value of a int:");
	scanf("%d",&pt->ma);
	puts("Enter the value of a double:");
	scanf("%lf",&pt->games);
	getchar();
	puts("Enter a characters you want:");
	fgets(pt->datas,size,stdin);
	
	int length=strlen(pt->datas);
	if (pt->datas[length-1] == '\n')
	{
		pt->datas[length-1]='\0';
	}
	else
	{
		while (getchar() != '\n')
		{
			continue;
		}
	}
	return;
}

void read_st(struct names *pt)
{
	puts("The contents are:");
	printf("ma=%d\n",pt->ma);
	printf("games=%.2f\n",pt->games);
	puts(pt->datas);
	
	return;	
} 

列印結果:

Please enter the array's size you want:
30
Enter the value of a int:
3
Enter the value of a double:
3.3
Enter a characters you want:
I love Micy very much!
The contents are:
ma=3
games=3.30
I love Micy very much!

4)注意事項

1.使用malloc()函式來建立結構,創建出來的結構和普通結構相同,訪問方式和指標訪問方式相同。

2.使用完malloc()函式來分配動態記憶體,因此在最後需要使用free()函式釋放掉動態記憶體。

十一、匿名結構在巢狀結構中的應用

匿名結構用在巢狀結構中比較常見,原因是可以減少結構變數的設定次數。

//匿名結構在巢狀結構中的應用
#include	<stdio.h>

struct names
{
	int ma;
	double games;
};
struct holds
{
	int diy;
	double numbers;
	char datas[30];
	struct//這裡不能加names這個結構模板名稱 
	{
		int ma;
		double games;
	};//避免建立變數,這樣可以直接放進來。現在ma 和games就相當於直接成為holds的成員了。 
	int cch; 
};

int main(void)
{
	struct holds toys=
	{
		2,
		3.4,
		"I love Micy very much!",
		5,
		4.6,//初始化的時候只需要按著順序初始化就可以了。
		7, 
	};
	printf("diy=%d\n",toys.diy);
	printf("ma=%d\n",toys.ma);//由於直接成為了成員,因此可以直接使用一次點運算子。 
	
	return 0; 
}

列印結果:

diy=2
ma=5

一定要注意,在巢狀的時候使用匿名,這樣可以簡化操作,但是需要省略巢狀部分的結構模板名稱,並且巢狀部分的成員就相當於是整個結構的成員了。