# C 语言练习题笔记

# 数组练习题

# 计数~~(查询某一字符出现次数)~~ 查询字符在第几个出现

这个题花了我较长时间

主要是卡在了如何获取后面部分用户输入的内容

一开始的想法 (仅展示获取输入的部分)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
/*
index是想要查询的字符
symbol[]是定义的字符型数组 用来存放用户的输入
temp_num是计算输入的数量以用来确定数组大小与下面检测次数
规定数组最大存放80个字符
*/

for (temp_num = 0; temp_num <= 80; temp_num++)
{
scanf("%c",&symbol[temp_num]);

if (symbol[temp_num] == '\n')
{
break;
}
}

用此方法无法正确的进行计数

而且在调试的时候 temp_num 的值为 0 [^ 还不知道原因]

正确写法

1
2
3
4
5
6
7
8
9
10
11
12
13
/*
定义内容与上一致
*/
scanf("%c",&index);
getchar(); //吃掉回车 避免被下面吃掉直接跳过循环

while ((i = getchar()) != '\n')
{
if (index == i)
{
count++;
}
}

使用 getchar () 问题很快就解决了

而且比原来更加轻量 更加具有效率

Tips

这一题里可以看到 scanf () 后面如果还有 getchar () 从键盘缓冲区读入的话 紧挨着 scanf () 先把回车给吃掉 以免到后面留下错误

不管多远 如果上面的回车不吃掉 下面使用 getchar () 就会直接吃回车

遇到了一点问题

image-20201019194030508

如果想要连续输入两行数据的话

单纯的 '\n' 是不行了

得用 EOF

但是 EOF 必须要输入两次 程序才能正常运行

# 为什么要输入两次 EOF ?

原因(点击打开)问学长才知道的 以下是原文 一段文字+ ^Z + 回车之后,在Windows系统上是这样处理的:由于回车的作用,前面的文段被送到输入缓冲区(注意: ^Z 不会产生字符,所以更不会存储到输入缓冲区,缓冲区中没有 ^Z 的存在). 这是,getchar() 检测到输入缓冲区中已经有数据存在(因此不再检查是否有 ^Z 的输入), 于是从缓冲中读取相应的数据. 如果都读取完了, 则输入缓冲区重新变为空, getchar()大恩待新的输入. 可见, 尽管有 ^Z 按下, 但是由于在此之前还有其它的字符(也就是说,不算是新起的一行), 所以流也不会结束. 因此, 输入流结束的条件就是: ^Z 之前不能有任何字符输入(回车除外). 换句话说, 就是要回车(新起一行,打入CTRL + Z) (显示为 ^Z ), 否则 ^Z起不到流结束的作用.

我审错题了!! !

1
2
3
4
5
6
7
8
9
while ((i = getchar()) != '\n')
{
count++;

if (index == i)
{
break;
}
}

原来题目说的是要数出现查询数字的时候是第几个字符😂😂😂


# 冒泡排序

这个题一开始存在几个问题

一个是连续输入数组 中间用空格隔开的问题~~(之前才查的 忘记了)~~

1
2
3
4
5
6
7
8
9
while (1)
{
scanf("%lf",&a);

if (getchar() == '\n')
{
break;
}
}

类似于此种方法就可以连续输入多组数据 中间用空格隔开

但是如果想要输入多排数据 还只能用 EOF

其次就是排序的问题

应该是要两个 for 将前面的与后面所有的进行比较的

可是我只是写了与后面一个数据进行比较 而且数据设计失误 到后面比较的流程完全乱掉了

这里还是把关键的排序算法写出来 (备忘)

1
2
3
4
5
6
7
8
9
10
11
12
for (i = 0; i < n; i++)
{
for (j = i + 1; j < n; j++)
{
if (num[i] <= num[j])
{
temp_num = num[i];
num[i] = num[j];
num[j] = temp_num;
}
}
}

# 交换最小值与最大值

这个题花我的时间算是很多了

主要原因在于寻找最大最小值的算法

我目前的做法是两个 for 双层嵌套 外面的变量是 i 里面是 j 外面的 i 从零开始记起 但是里面的 j 从 i + 1 开始算起 这样就可以避免当内层循环结束一次之后 外层 i 增加一个 再次内循环时 j = 0 造成不必要的比较 ==(另外 我的算法是如果遇到 num [i] 比 num [j] 大的情况 就让 i = j . 如果不设置为 j = i + 1 的话 例如存在 8 1 2 5 1 4 时 i = 2 时 j 又会回去 然后 i 就会与 第二项 交换 i 就一直在 0 1 2 之间死循环)==

伪代码如下

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
//寻找最大值并与数组最后一项进行交换

a: for (i = 0; i < n; i++) //max
{
for (j = i + 1; j < n; j++)
{
if (comprasion(num[i],num[j]) == 0)
{
i = j;
}

if (j == n - 1)
{
k = 0;
k = num[i];
num[i] = num[n - 1];
num[n - 1] = k;
goto b;
}
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
//寻找最小值并与数组最后一项进行交换

for (i = 0; i < n; i++) //min
{
for (j = i + 1; j < n; j++)
{
if (comprasion(num[i],num[j]))
{
i = j;
}

if (j == n - 1)
{
k = 0;
k = num[i];
num[i] = num[0];
num[0] = k;
goto a;
}
}
}

顺便把 comparesion 函数部分贴出来

1
2
3
4
5
6
7
8
9
10
11
12
int comprasion(int m, int n)	//用于比较两数大小
{
if (m > n)
{
return 1;
}

else
{
return 0;
}
}

# 求整数序列中出现次数最多的数

这个题的核心在于如何处理统计的每个字符的个数并且对其进行比较

因为上一个题涉及了两数之间的比较 与寻找最大值 因此 本题只需要统计不同字符出现的次数即可

伪代码如下

1
2
3
4
5
6
7
8
9
10
for (i = 0; i < n; i++)
{
for (j = i + 1; j < n; j++)
{
if (num[i] == num[j])
{
sum[i]++;
}
}
}

# 字符转换

这个题要是只输出数字的话并不难 难的是如何把数组中的单个数字变为一个长整型数字

思路

首先肯定是用一个数组将数字存储进去 然后单独处理 (顺便统计数字位数)

其次需要对不同的数字位数进行加权运算

首先想到了利用 pow 函数

关于位数方面 需要反着来~~(最高位在数组最前面)~~

伪代码如下

1
2
3
4
5
6
7
   for (i = count; i >= 1; i--)
{
temp = pow(10,count - i);
num_1 += (temp * num[i]);
}

printf("%d",num_1);

# 删除重复字符

这个题算是我写出来的有明确 bug~~(我找得到但是解决不了)~~ 的题 我写出来的代码 当重复字符是双数时 (两个除外) 例如 FFFF 执行效果为 FF 单数是就不会存在这种问题

一开始还想写一段进行再次删除 可是写出来的效果不行~~(没效果还很多报错)~~ 所以索性列个选择条件 如果还有重复 直接 goto 语句回到删除重复的片段再走一次 就没有问题了

伪代码如下 [^ 待优化]

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
a:  for (i = 0; i < len; i++)
{
for (j = i + 1; j < len; j++)
{
if (ch[i] == ch[j])
{
while (j < len)
{
ch[j] = ch[j + 1];
j++;
}
}
}
}

len = strlen(ch);

for (i = 0; i < len; i++)
{
for (j = i + 1; j < len; j++)
{
if (ch[i] == ch[j])
{
goto a;
}
}
}

# 指针练习题

# C 语言 设一个函数 process,调用它时,实现不同功能

这个题

更新于 阅读次数