算法
编写一个复制输入到输出的程序,并将其中连连续的多个空格用一个空格代替
思维逻辑:
多个空格用一个空格代替
可以 被理解为只保留一串空格里的第一个空格
使用
getchar()
依次读取输入的每一个字符直到结尾, 考虑哪些字符被保留?答案是:它不是空格
或者它是一串空格里的第一个空格
那么如何判断一串空格里第一个空格? 答案 是判断该空格前一个字符是否为空格, 所以我们需要一个变量存储上一个读取的字符
#include <stdio.h>
#define NONBLANK 'a'
int main( int argc, char *argv[] )
{
int c; // 当前字符
int last_c; // 上一个字符
last_c = NONBLANK;
while( ( c = getchar() ) != EOF )
{
if( c != ' ' || last_c != ' ' )
putchar( c );
last_c = c;
}
return 0;
}
编写程序统计输入的单词个数,这里单词单纯定义为连续输入的字符,中间不包含空白字符
思维逻辑
还是从
getchar()
依次读取输入的每一个字符直到结尾入手,我们考虑下字符的状态,只有两种 :在单词中
与不在单词中
我们对
在单词中
的字符进行计数, 考虑下计数规则 : 我们对多字符单词hello
和单字符单词a
都只计数一次那么我们如何实现这种计数?我们的计数循环是每次读入一个字符,那么这个字符跟单词必须是一对一的关系,即: 单词中只能有这么一个字符,每次读到这个字符时,单词数+1,读取到单词内其他字符时不加
那么单词中有这种字符么?答案是:
首字符
或者是尾字符
, 任意单词只有一个首字符
或尾字符
如何判断
首字符
:首字符
的前一个字符是空白字符
或者 是输入程序读入的第一个
字符,实现上,我们需要一个变量last_c
存储前一个字符,在程序开始时可以设置last_c
为空格,来兼容程序读入的第一个字符是单词首字符
的情况如何判断
尾字符
:尾字符
的后一个字符是空白字符
或者尾字符
后面是EOF
,用一个字符存储后一个字符???这个逻辑比较变扭,不采用综上,对单词计数的逻辑是: 该字符在单词内 并且 是
首字符
#include <stdio.h>
#define BLANK ' '
int main( int argc, char *argv[] )
{
int c; // 当前字符
int last_c; // 上一个字符
int count;
last_c = BLANK;
count = 0;
while( ( c = getchar() ) != EOF )
{
if( c != ' ' && c != '\t' && c != '\n' && ( last_c == ' ' || last_c == '\t' || last_c == '\n' ) )
count ++;
last_c = c;
}
printf("count : %d\n",count);
return 0;
}
根据数组打印一个竖直的直方图
思维逻辑
竖直的概念的理解 : 行数应该是数组中最大的那个数
max = 10
从上到下打印,第一层循环次数是最终要打印的行数,每一行里面,对这个数组每一项进行遍历
以下标为
arr[0]
为例,它在第一层循环下,输出应该是 8 个空格,然后是 2 个*
,arr[0]
的值为 2, 8 个空格可以理解为max - 2
, 每次打印了一个空格, 都应该将max - 2
的值减去1
,当max - 2
随着循环被减为0
时,再进行循环就打印*
号了如果 i 为当前打印的行数,
max - 2 - i
就是剩余需要打印的空格数, 如果该值大于0
的话,那么打印空格,否则打印*
综上,算法的逻辑就是,求出最大行数
max
和数组长度len
, 外层循环max
次,当前次为i
,里循环len
,当前项为j
,判断打印空格
或*
的逻辑是max - arr[j] - i > 0
#include <stdio.h>
int main( int argc, char *argv[] )
{
int arr[] = { 2, 5, 1, 4, 9, 1, 3, 8, 10, 2, 4, 9};
int max = 0;
int len = sizeof(arr) / sizeof(int);
for ( int i = 0; i < len; i++ )
{
if( arr[i] > max )
max = arr[i];
}
for( int i = 0; i < max; i++ )
{
for( int j = 0; j < len; j++ )
{
if( max - arr[j] - i > 0 )
printf(" ");
else
printf("*");
}
printf("\n");
}
return 0;
}
// 打印效果:
// *
// * * *
// * ** *
// * ** *
// * ** *
// * * ** *
// * ** ** **
// * ** *** **
// ** ** ******
// ************
素数 / 质数
只能被 1 和 自身整除的数
八皇后问题
8 x 8 的国际象棋上放置八个皇后,任意两个皇后都不能处于同一横行,纵行,斜线上。下图是一种解法,总共有92种解法。
- - - x - - - -
- - - - - - x -
- - x - - - - -
- - - - - - - x
- x - - - - - -
- - - - x - - -
x - - - - - - -
- - - - - x - -
数独问题
9 x 9 的大九宫格中有9个 3 x 3 的小九宫格。默认在其中填写一些数字,在其他空格处填入1到9的数字,使得每个数字在每个小九宫格内只出现一次,并且在大九宫格中,每横行,纵行只出现一次。比如下面这个数组就有51965种解
- 9 - - - 2 - - 1
- - - - 6 - - - 2
- - - - - - 4 - -
6 - - - 8 - - - -
- 2 - - - - - - -
- - 1 7 - 4 - - -
3 6 - - - - - - -
- - 7 - - - 5 - -
9 5 - - - 7 - - 8
字符串转数字 数字转字符串
#include <stdio.h>
void toString(int number, char *str);
void toInt(char *str, int *number);
void main()
{
char str1[20],str2[20];
int number;
toString(123,str1);
toString(-123,str2);
toInt("500",&number);
printf("%s\n",str1);
printf("%s\n",str2);
printf("%d\n",number);
getchar();
}
void toString(int number,char *str)//数字转字符串算法实现
{
int isNegative = 0;//默认为非负数
int i,j;
char temp;
isNegative = number < 0 ? (number*=-1,1) :0;//判断是否为负数,巧用逗号表达式,可以省一行(哈哈)
for (i = 0; number != 0; i++)//反向逐一取得字符,最后反转
{
str[i] = (char)(number % 10+48);
number /= 10;
}
if (isNegative)//负数处理
{
str[i++] = '-';
str[i--] = 0;
}
else//正数处理
str[i--] = 0;//i++,可以使得i正好等于字符个数,又省了三行(低调)
for (j = 0; j <= i / 2; j++)//字符数组反转,3个字符换两次,4个换两次,奇偶通用(数组反转算法)
{
temp = str[j];
str[j] = str[i - j];
str[i - j] = temp;
}
}
void toInt(char *str,int *number)//字符串转数字算法实现
{
int i;
*number = 0;//强制初始化
for (i = 0; str[i] != 0; i++)
*number = (int)(str[i] - 48) + *number * 10;//逐一取字符转换为数字,并升权放入number
}