《C程序设计语言第二版》第三章-控制流(3.1-3.8)

3.3 else-if语句

binsearch函数:在V[0] <= V[1] <= V[2] <= …<=V[n-1]中查找x

#include<stdio.h>

#define MAXLIMIT 1024

int binsearch(int x,char v[],int n)
{
    int low, high, mid;

    low = 0;
    high = n - 1;
    while (low <= high)
    {
        mid = (low + high) / 2;

        if (x < v[mid])
            high = mid - 1;
        else if (x > v[mid])
            low = mid + 1;
        else
            return mid;
    }

    return  -1;
}

int main()
{
	int m;
    int x;
    x = 'h';  //字母可以是int型,但是必须加单引号(打印时用%c与%d区别打印的是字符char,还是十进制整数)。不能不加;加双引号也不行。

    int n;
    n = 10;  //字符串长度

    char v[] = "abcdefghij"; //多个字母的字符串,v必须以升序排列

    m = binsearch(x, v, n);
    printf("%d", m);

    return 0;
}

在这里插入图片描述

【注意int型整数数组的正确定义和使用方法:int x[长度] = {0,5,1,2,……,15}

储存单个字符的变量,用char和int定义均可,一定是单引号,并在输出时用printf函数中的%d和%c区别。

储存多个字符的变量,不要用int型整形数组定义字符串和char型数组,且定义时char型数组和字符串在形式上没有区别:

(本版本的课本中经常用int型整数数组定义字符串,但实际在编译器中通不过。)
字符串要用char型字符数组,且双引号(即使内容中只包含一个字符,也是双引号) 如char x[] = “h” 再如char x[] = “hello”,计算机系统会自动补充’\0’,输出时在printf函数中用%s占位符;

char型数组,即用char x[10] = {‘a’,‘b’,‘c’,‘d’,‘e’,‘f’,……} ,输出时也可在printf函数中用%s占位符,计算机系统会自动补充’\0’,输出字符串。】

#include<stdio.h>

#define MAXLIMIT 1024

int binsearch(int x,int v[],int n)
{
    int low, high, mid;

    low = 0;
    high = n - 1;

    while (low <= high)
    {
        mid = (low + high) / 2;

        if (x < v[mid])
            high = mid - 1;
        else if (x > v[mid])
            low = mid + 1;
        else
            return mid;
    }

    return  -1;
}

int main()
{

    int x;
    x = 1;  //字母可以是int型,但是必须加单引号(打印时用%c与%d区别打印的是字符char,还是十进制整数)。不能不加;加双引号也不行。

    int v[10] = {0,1,2,3,4,5,6,7,8,9}; //多个字母必须是char型数组(打印时用%c与%s区别打印的是char型数组中的字符char,还是整个字符串string,定义时char型数组和字符串没有区别),且为双引号

    n = binsearch(x, v, 10);
    printf("%d", n);

    return 0;
}

在这里插入图片描述

练习3-1

在上面有关折半查找的例子中,while循环语句内共执行了两次测试,其实只要一次就足够(代价是将更多的测试在循环外执行)。重写该函数,使得在循环内部只执行一次测试。

mticket 练习3-1

(C语言)clock()函数的基本使用

#include <stdio.h>
#include <time.h>

int binsearch(int x, int v[], int n);     /*  Original K&R function  */
int binsearch2(int x, int v[], int n);    /*  Our new function       */

#define MAX_ELEMENT 20000


/*  Outputs approximation of processor time required
    for our two binary search functions. We search for
    the element -1, to time the functions' worst case
    performance (i.e. element not found in test data)   */

int main(void) {
    int testdata[MAX_ELEMENT];
    int index;                  /*  Index of found element in test data  */
    int n = 10;                 /*  Element to search for  */
    int i;
    clock_t time_taken;

    /*  Initialize test data  */

    for (i = 0; i < MAX_ELEMENT; ++i)
        testdata[i] = i;


    /*  Output approximation of time taken for 100,0000 iterations of binsearch()       */

    for (i = 0, time_taken = clock(); i < 1000000; ++i) {
        index = binsearch(n, testdata, MAX_ELEMENT);
    }
    time_taken = clock() - time_taken;   //差值为这段代码运行的时间

    /* clock()函数的返回值就是你程序当前运行的时间(毫秒为单位)*/

    if (index < 0)
        printf("Element %d not found.\n", n);
    else
        printf("Element %d found at index %d.\n", n, index);

    printf("binsearch() took %lu clocks (%lu seconds)\n",
        (unsigned long)time_taken,
        (unsigned long)time_taken / CLOCKS_PER_SEC);   //CLOCK_PER_SEC本质上是一个长整型的1000,相当于转化成以秒为单位了


    /*  Output approximation of time taken for 100,000 iterations of binsearch2()        */

    for (i = 0, time_taken = clock(); i < 1000000; ++i) {
        index = binsearch2(n, testdata, MAX_ELEMENT);
    }
    time_taken = clock() - time_taken;

    if (index < 0)
        printf("Element %d not found.\n", n);
    else
        printf("Element %d found at index %d.\n", n, index);

    printf("binsearch2() took %lu clocks (%lu seconds)\n",
        (unsigned long)time_taken,
        (unsigned long)time_taken / CLOCKS_PER_SEC);

    return 0;
}


/*  Performs a binary search for element x in array v[], which has n elements */

int binsearch(int x, int v[], int n) {
    int low, mid, high;

    low = 0;
    high = n - 1;
    while (low <= high) {
        mid = (low + high) / 2;
        if (x < v[mid])
            high = mid - 1;
        else if (x > v[mid])
            low = mid + 1;
        else                //此处会执行x == v[mid]的测试
            return mid;
    }
    return -1;
}


/*  改进后的binsearch2函数:在while循环中只进行一次测试low <= high && x != v[mid];x == v[mid]在循环外执行

Implementation of binsearch() using
    only one test inside the loop        */

int binsearch2(int x, int v[], int n) {
    int low, high, mid;

    low = 0;
    high = n - 1;
    mid = (low + high) / 2;
    while (low <= high && x != v[mid]) {
        if (x < v[mid])
            high = mid - 1;
        else
            low = mid + 1;
        mid = (low + high) / 2;
    }
    if (x == v[mid])
        return mid;
    else        //x始终没有等于一个v[mid],则说明x在v中不存在。
        return -1;
}

在这里插入图片描述

3.4 switch语句

#include <stdio.h>

/* 统计数字、空白字符及其他字符  */

int main()
{
	int c, i, nwhite, nother, ndigit[10];  //整数型数组的正确定义方式,此处字母会被归为other类字符

	nwhite = nother = 0;
	for (i = 0; i < 10; i++)   //初始化整数型数组
		ndigit[i] = 0;         

	while ((c = getchar()) != EOF)
	{
		switch (c) {
		case '0': case '1': case '2': case '3': case '4':
		case '5': case '6': case '7': case '8': case '9':
			ndigit[c - '0']++;    //字母被归为other类字符,数字出现的频数与ndigit中的下标数相对应
			break;
		case ' ':
		case '\n':
		case '\t':
			nwhite++;
			break;
		default:
			nother++;
			break;
		}
	}

	printf("digits =");
	for (i = 0; i < 10; i++)
		printf(" %d", ndigit[i]);

	printf(", white space = %d,other = %d\n", nwhite, nother);
	
	return 0;
}

在这里插入图片描述

练习3-2

编写一个函数escape(s,t),将字符串t复制到字符串s中,并在复制过程中将换行符、制表符等不可见字符转换为\n、\t等相应的可见的转义字符序列。要求使用switch语句。

int getlines(char x[], int limit);
void escape(char s[], char t[]);

#include <stdio.h>

#define MAXLIMIT 1024


int main()
{
	char s[MAXLIMIT];
	char t[MAXLIMIT];

	escape(s, t);
	printf("%s", s);
	return 0;
}


int getlines(char x[], int limit)   \\只能保存一行
{
	int c, i;
	c = 0;
	i = 0;

	for (i = 0; i < limit - 1 && (c = getchar()) != EOF && c != '\n'; ++i)
	{
		x[i] = c;
	}

	if (c == '\n')
	{
		x[i] = c;    //x[i++] = c;
		i++;
	}

	x[i] = '\0';

	return i;
}


void escape(char s[], char t[])
{
	int i = 0;  //字符串s中的下标
	int j = 0;  //字符串t中的下标
	int length_s;
	int length_t;

	length_s = getlines(s, MAXLIMIT);  	//将s中的指针移到最后
	length_t = getlines(t, MAXLIMIT);

	for (i = 0; i < length_s; i++)   //不算s中的结束符(字符串中的结束符必须要加,但讨论字符串中的元素该忽略的时候要忽略)
	{
		switch (s[i])
		{
		case '\t':
			s[i] = '\\t';
			break;
		case '\n':
			s[i] = '\\n';
			break;
		default:
			break;
		}
	}

	for (i = length_s, j = 0; j < length_t; j++)  //不算j中的结束符(字符串中的结束符必须要加,但讨论字符串中的元素该忽略的时候要忽略)
	{
		switch (t[j])
		{
		case '\t':  
			s[i] = '\\t';    //s[i++] = '\\t';
			i++;
			break;
		case '\n':
			s[i] = '\\n';   //s[i++] = '\\n';
			i++;
			break;
		default:
			s[i] = t[j];   //s[i++] = t[j];
			i++;
			break;
		}
	}

	s[i] = '\0';
}

在这里插入图片描述

3.5 while循环和for循环

atoi 函数

atoi 函数:将s转换为十进制整型,版本2
【函数说明】atoi() 函数会扫描参数 str 字符串,跳过前面的空白字符(例如空格,tab缩进等,可以通过 isspace() 函数来检测),直到遇上数字或正负符号才开始做转换,而再遇到非数字或字符串结束时(‘\0’)才结束转换,并将结果返回。
【返回值】返回转换后的整型数;如果 str 不能转换成 int 或者 str 为空字符串,那么将返回 0。
C语言atoi()函数:将字符串转换成int(整数)——JANYI2018

版本1为2.7 类型转换 中的 练习2-3 函数
htoi(s),把由十六进制数字组成的字符串(包含可选的前缀0x或0X)转换为与之等价的整型值。字符串中允许包含的数字包括:0~9、a~f以及A~F。
2.7 类型转换 —— 练习2-3 函数 htoi(s)

# include <stdio.h>
# include <ctype.h>


/* atoi 函数:将s转换为十进制整型,版本2 */

int atoi(char s[]);

int main()
{
	int num;

	char s[] ="   -798a";

	num = atoi(s);

	printf("%d", num);
	
	return 0;
}

int atoi(char s[])
{
	int i,n,sign;

	for (i = 0; isspace(s[i]); i++)  /* 跳过第一个非空字符前面的空白符,非空格的时候,isspace()返回值为0(flase),会跳出循环;空格时,isspace()返回值非零(True),则会一直在循环中,指针往前移动。  */
		;
	sign = (s[i] == '-') ? -1 :  1;

	if (s[i] == '+' || s[i] == '-')   /* 跳过符号 */
		i++;

	for (n = 0; isdigit(s[i]); i++)   /* 循环求s中的十进制对应的十进制的值 */
		n = 10 * n + (s[i] - '0');

	return sign * n;
}

在这里插入图片描述

插入排序insertionSort函数

插入排序:即gap值为1的shellsort函数
【学习笔记】最容易理解的希尔排序(shell sort)讲解

// 变量命名便于代码理解
void insertionSort(int arr[], int size) 
{
    int i, j, temp;

    for(i = 1; i < size; i++)
        for(j = i-1; j >= 0 && arr[j] > arr[j+1]; j--) {
            temp = arr[j];
            arr[j] = arr[j+1];
            arr[j+1] = temp;
    }
}
插入排序的要点:
①将数组中前面的部分作为有序部分,后面的部分作为无序部分;
②每次都只将无序部分的第一个元素arr[i]放入前面有序部分,直到无序部分为空;
③数组中无序部分第一个arr[i]的前面一个,即为有序部分的最后一个arr[j]【j的初始值为i-1】;
③每次都是以 有序部分的最后一个arr[j] 与  无序部分的第一个arr[j+1] 的比较为首次比较;
④对于内层for循环遵循 “严进严出” 的原则:
如果该 有序部分的最后一个arr[j] 比 无序部分的第一个arr[j+1] 更小,则可停止比较。
【 arr[j] ≤ arr[j+1]一次内层for循环也不进入,判断之后直接跳出内层for循环。
此时该无序部分的第一个arr[j+1]自动成为下一次有序部分的最后一个。
即从内层for循环跳出后,在i的外层for循环中,i自增1, 代表新的无序部分的第一个为arr[i].
接着再开始进行新的内层for循环时,有序部分的最后一个仍为arr[j] 【j的初始值为i-1.

如果该 有序部分的最后一个arr[j] 比 无序部分的第一个arr[j+1] 更大,就进行交换(swap),
交换一次之后,并不会立即跳出内层for循环,而是将有序部分的元素继续前移j--,
因此若比前面的有序部分arr[j]还小,则继续交换。
直到比有序元素的数值更大(arr[j] ≤ arr[j+1])了,才停止交换,也才能跳出内层for循环。

【“严进” :
只有 有序部分的最后一个arr[j] 比 无序部分的第一个arr[j+1] 更大时,才能进入内层for循环;

“严出” :
在内层for循环中,j一定会往前移动。此时,只要j在往前移动,那么就必须要进行交换。
如果想跳出,就要达到不进行交换的条件(交换至应该处的位置,满足了arr[j] ≤ arr[j+1]),才能跳出;
或者已移动至了有序部分的第一个(j=0),使j也不能再继续往前移动了,才能跳出。 

每执行完一次内层for循环的交换之后,在j自减之前,一定是满足arr[j] ≤ arr[j+1]的。但是在j自减之后,就不一定满足arr[j] ≤ arr[j+1]了。
如果在交换之后,j自减之前,j就已经为0,那么j无法再自减(自减之后就会跳出内层for循环)。
而此时(在交换之后,j自减之前)无序部分的第一个 已经被交换至了arr[j]即arr[0]处,也一定满足arr[0] ≤ arr[1],即无序部分的第一个是处于了有序部分的第一个,但也是最小的了,所以不需要再交换,也是完成了排序的任务。 】

【区别快速排序qsort函数
《C程序设计语言第二版》第四章-函数与程序结构(4.1-4.11)—— 快速排序qsort函数

希尔排序shellsort函数

shellsort函数:按递增顺序对v[0]……v[n-1]进行排序。
【学习笔记】最容易理解的希尔排序(shell sort)讲解

八种排序之三:十分钟明白为什么希尔排序完虐直接插入排序

#include <stdio.h>

void shellsort(int v[], int n);

int main()
{
	int s[5] = { 1,7,4,3,5 };
	int n = 5;
	int i = 0;

	shellsort(s, n);
	
	for(i = 0; i < n; i++)
		printf("%d", s[i]);

	return 0;

}

void shellsort(int v[], int n)
{
	int gap, i, j, temp;

	for (gap = n / 2; gap > 0; gap /= 2)
	{
		for (i = gap; i < n;i++)   
		{
			for (j = i - gap; j >= 0 && v[j] > v[j + gap]; j -= gap) 
			//当此for循环的条件有一个不满足时,就会退出整个for循环,继续进行上面的for循环
			{
				temp = v[j];
				v[j] = v[j + gap];
				v[j + gap] = temp;
			}
		}
	}
}
希尔排序中的插入排序,也是将每组中处于后面位置的无序部分的第一个元素 与 
处于前面位置的有序部分的元素 从后往前依次进行比较的,
因此在最内层进行插入排序的for循环中,对j的赋值语句为 j = j-gap(递减,且以gap为步长),j最小值为0. 


希尔排序首次的gap一定为n/2,所以一定会将全部数据分为 n/2 组,每组中包含两个数据。
每组包含的元素在数组中并不紧挨,每两个元素之间相隔gap-1个位置(即n/2-1个位置,不包含头尾的在同一组的元素)。
对仅包含两个元素的组进行插入排序时,这两个元素逆序时,直接交换即可。
因此gap为n/2时,希尔排序是先对第n/2组进行插入排序(因为i的初始值为gap),再对第n/2-1组进行插入排序,直到第1组。



但当gap值小于n/2时(如等于n/4),会将全部数据分为 n/4 组(取整),每组中包含的数据一定多于两个。
每组包含的元素在数组中仍并不紧挨,每两个元素之间相隔gap-1个位置(即n/4-1个位置,不包含头尾的在同一组的元素)。
此时希尔排序实际执行过程中并不总是 按确定好步长间隔的后的分组,对每组依次从后往前进行插入排序的。
即并不是最后一组插入排序全部完成之后,再排前面一组的。
理解原理时可以这样理解,但实际代码的执行过程不是。
  
此时代码是按数组本身的元素顺序,将其作为本组中无序部分的第一个元素(下标为i = gap的),
依次与本组中有序部分的元素(同一组中每两个元素之间相隔gap-1个位置)从后往前对比,如此交叉进行每组的插入排序。
从整个希尔排序来看,是在第 m 组中进行一次插入排序的某一步后,下一次可能又会在第n组中进行插入排序的某一步……
按数组本身的元素顺序将整个数组遍历完了,对所有小组的插入排序也都完成了。
所以在gap一定且还不为1时,每次快速排序之后,每组之内元素的顺序可能会变,但每组之间的顺序并不变。  

在这里插入图片描述

reverse函数

reverse函数:倒置字符串s中的各个字符的位置

#include <stdio.h>
#include <string.h>

void reverse(char s[]);

int main()
{
	char s[6] = {'a','b','c','d','e','f'};
	int n = 6;
	int i = 0;

	reverse(s);
	
	for(i = 0; i < n; i++)
		printf("%c", s[i]);

	return 0;

}

void reverse(char s[])
{
	int c, i, j;

	for (i = 0, j = strlen(s) - 1; i < j; i++, j--)
	{
		c = s[i]; 
		s[i] = s[j];
		s[j] = c;       //第二种写法:用逗号运算符 c = s[i],s[i] = s[j],s[j] = c;
	}
}

在这里插入图片描述

练习 3-3

编写expand(s1,s2),将字符串s1中类似于a-z类的速记符号在字符串s2中扩展为等价的完整列表abc…xyz。该函数可以处理大小写字母和数字,并可以处理a-b-c,a-z0-9和-a-z等类似的情况。作为前导和尾随的-字符原样排印。
《C程序设计语言》 练习3-3 骑码的佳俊

#include <stdio.h>
#define MAXLEN 100

int getlines(char array[], int limit);
void expand(char s1[],char s2[]);

int main()
{
	int i;
	char s1[100];
	char s2[100];
	int s1_len = 0;


	while ((s1_len = getlines(s1, MAXLEN)) > 0)
	{
		printf("速写字符:");
		for (i = 0; s1[i] != '\0'; i++)
		{
			printf("%c", s1[i]);
		}
		expand(s1, s2);
		printf("展开为:");
		for (i = 0; s2[i] != '\0'; i++)
		{
			printf("%c", s2[i]);
		}
	}
	return 0;
}

int getlines(char array[], int limit)
{
	int n,i,c;

	for (i = 0;i < limit - 1 && (c = getchar()) != EOF && c != '\n'; i++ )
	{
		array[i] = c;
	}

	if (c == '\n')
	{
		array[i] = c;
		i++;
	}

	array[i] = '\0';

	return i;

}


void expand(char s1[], char s2[])
{
	int i, j;
	char state;
	char c1_first, c1_last;
	i = j = 0;

	while (s1[i])
	{
		switch (s1[i])
		{
		case '-':                  
			if (i == 0 || s1[i + 1] == '\0')
			{
				s2[j++] = '-';
			}
			else
			{
				c1_first = s1[i - 1];
				c1_last = s1[i + 1];

				for (state = c1_first; state < c1_last - 1; j++)
				{
					state++;
					s2[j] = state;
				}
			}
			break;
		default:
			s2[j++] = s1[i];
			break;
		}
		i++;
	}
	s2[j] = '\0';
}

在这里插入图片描述

3.6 do-while循环

itoa 函数

itoa 函数 :将数字n转换为字符串并保存在s中.

#include <stdio.h>
#include <string.h>


void reverse(char s[]);
void itoa(int n, char s[]);


int main()
{
	int n = 100;
	char s[10] = {"\0"};

	itoa(n, s);
	printf("%s", s);

	return 0;
}


void reverse(char s[])
{
	int c, i, j;

	for (i = 0, j = strlen(s) - 1; i < j; i++, j--)
	{
		c = s[i];
		s[i] = s[j];
		s[j] = c;
	}
}


void itoa(int n, char s[])
{
	int i, sign;

	if ((sign = n) < 0)  /* 记录符号,与while((c = getchar())!=EOF)类似的用法 */
		n = -n;

	i = 0;

	do
	{
		s[i++] = n % 10 + '0';
	} while ((n /= 10) > 0);   //系统会将n/10的计算结果值取整,小数位全部去掉,因此当结果为0.XXX时,会被自动取整为0.  当条件写为(n /= 10) >= 0时,陷入无限循环,无法跳出while循环。

	if (sign < 0)
		s[i++] = '-';

	s[i] = '\0';
	reverse(s);

}

在这里插入图片描述

练习 3-4

用上面的函数处理32位十进制最大负数-2^31 (-2147483648) 时的输出结果:
在这里插入图片描述
原因:对于整数的对二补码表示中,所能表示的最大正整数值为2^(字长-1) - 1,故不能通过n = -n;
将-(2^(字长-1))
转化为2^(字长-1),而是通过abs宏取绝对值的方法abs(n % 10)得到。
比如最大的负数n = -2147483648(即-(2^(字长-1)),通过abs(n % 10)得到8,这样就绕过了上述的问题。

修改上述itoa函数的代码:
(1):用abs(n % 10)而非n = -n来规避当n为最小整数(-2147483648)时。
(2):do-while循环的判断条件用((n / 10) != 0)而非((n / 10) > 0)来避免当n是个负数时,使itoa函数陷入无限循环汇总。 (这句话没有理解,上面的代码除了最大的负数,也可以处理负数)
原文链接:将军之盾——itoa函数,考虑当待处理整数为-2^(字长-1)的情况

#include <stdio.h>
#include <string.h>
#include <stdlib.h>


void reverse(char s[]);
void itoa(int n, char s[]);


int main()
{
	int n = -2147483648;
	char s[12] = { "\0" };

	itoa(n,s);
	printf("%s", s);

	return 0;
}


void reverse(char s[])
{
	int c, i, j;

	for (i = 0, j = strlen(s) - 1; i < j; i++, j--)
	{
		c = s[i];
		s[i] = s[j];
		s[j] = c;
	}
}


void itoa(int n, char s[])
{
	int i, sign;

	if ((sign = n) < 0)  /* 记录符号,与while((c = getchar())!=EOF)类似的用法 */
		n = -n;

	i = 0;

	do
	{
		s[i++] = abs(n % 10) + '0';
	} while ((n /= 10) != 0);

	if (sign < 0)
		s[i++] = '-';

	s[i] = '\0';
	reverse(s);

}

在这里插入图片描述

练习 3-5

编写函数 itob(n, s, b),将整数n转换为以b为底的数,并将转换结果以字符的形式保存到字符串s中。例如,itob(n, s, 16)把整数n格式化成十六进制整数保存在s中。
骑码的佳俊《C程序设计语言》 练习3-5

#include <stdio.h>
#include <string.h>

void reverse(char s[]);
void itob(int n, char s[], int b);

int main()
{
	char array[100];
	int n, b;

	printf("请输入要转换的十进制数:");
	scanf_s("%d", &n);/* scanf是格式化输入函数, 是c库函数;&n是取变量n的地址的意思。整句的意思是以有符号整形的格式从键盘输入一个值到变量n的地址。*/
	putchar('\n');

	printf("转换为多少进制:");
	scanf_s("%d", &b);   //因为是vs编译器的原因,所以要用scanf_s()替换scanf()
	putchar('\n');

	itob(n, array, b);

	printf("结果为:");
	for (int i = 0; array[i] != '\0'; i++)
	{
		printf("%c", array[i]);
	}
	putchar('\n');

	return 0;

}



void reverse(char s[])
{
	int i, j, t;

	for (i = 0,j = strlen(s) - 1; i < j; i++, j--)
	{
		t = s[i];
		s[i] = s[j];
		s[j] = t;
	}
}

void itob(int n, char s[], int b)
{
	int sign, i;
	static char b_numbers[] = { "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ" };

	if ((sign = n) < 0)
	{
		n = -n;
	}

	i = 0;

	do
	{
		s[i++] = b_numbers[n % b];
	} while ((n /= b) > 0);

	if (sign < 0)
	{
		s[i++] = '-';
	}

	s[i] = '\0';
	reverse(s);
}

在这里插入图片描述
在这里插入图片描述

练习 3-6

修改 itoa 函数,使得该函数可以接收三个参数。其中,第三个参数为最小字段宽度。
为了保证转换后所得的结果至少具有第三个参数指定的最小宽度,在必要时应在所得结果的左边填充一定的空格。

原文链接:mticket

#include <stdio.h>
#include <limits.h>

void itoa(int n, char s[], int m);
void reverse(char s[]);

int main() {
    int n;
    char s[100];
    
    n = INT_MIN;   // n = -2147483648,共11位(连负号);
    itoa(n, s, 15);   //前面需要补四个空格
    for (int i = 0; s[i] != '\0'; ++i) {
        printf("%c", s[i]);
    }
    printf("\n");


    n = 123456789;  //共九位
    itoa(n, s, 15);  //前面需要补六个空格
    for (int i = 0; s[i] != '\0'; ++i) {
        printf("%c", s[i]);
    }
    printf("\n");


    n = 156;  //共三位
    itoa(n, s, 15);  //前面需要补十二个空格
    for (int i = 0; s[i] != '\0'; ++i) {
        printf("%c", s[i]);
    }
    printf("\n");
    
    return 0;
}

void itoa(int n, char s[], int m)
{
    int i = 0;
    int sign = n;

	if ((sign = n) < 0)  /* 记录符号,与while((c = getchar())!=EOF)类似的用法 */
		n = -n;

	i = 0;

    do {
        s[i++] = n % 10 + '0';
    } while ((n /= 10) > 0);

    if (sign < 0)
        s[i++] = '-';

    s[i] = '\0';

    reverse(s);

    if (i < m) {
        for (int j = i; j >= 0; --j) {  
            s[j + m - i] = s[j];    //将字符后移
        }
        for (int j = m - i - 1; j >= 0; --j) {
            s[j] = ' ';   //在最前面添加空格
        }
    }
}


void reverse(char s[]) {
    int i;

    for (i = 0; s[i] != '\0'; ++i) {
        ;
    }

    --i;

    for (int j = 0; i > j; --i, ++j) {
        char temp = s[i];
        s[i] = s[j];
        s[j] = temp;
    }
}

在这里插入图片描述

3.7 break语句与continue语句

trim函数

trim函数:删除字符串尾部的空格符、制表符与换行符。

#include <string.h>
#include <stdio.h>

int trim(char s[]);

int main()
{
	int len = 0;
	char s[] = "123456	";

	len = trim(s);
	printf("%d  %s",len,s);
	
	return 0;
}


int trim(char s[])
{
	int n;

	for (n = strlen(s) - 1; n >= 0; n--)
	{
		if (s[n] != ' ' && s[n] != '\t' && s[n] != '\n')
		{
			break;  //退出整个for循环,指针n不再往前移动
		}

		s[n + 1] = '\0';

		return n;
	}
}

在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值