PTA - C程式設計 NoD - 陣列-指標-字串 (10道題)
6-1 | 使用函式實現字串部分複製 |
6-2 | 刪除字元 |
6-3 | 字串的連線 |
6-4 | 函式實現字串逆序 |
6-5 | 指定位置輸出字串 |
6-6 | 查詢子串 |
7-1 | 找最小的字串 |
7-2 | 字串排序 |
7-3 | 找最長的字串 |
7-4 | A-B |
6-1 使用函式實現字串部分複製
本題要求編寫函式,將輸入字串 t 中從第 m 個字元開始的全部字元複製到字串 s 中。
函式介面定義:
void strmcpy( char *t, int m, char *s );
函式strmcpy
將輸入字串char *t
中從第 m
個字元開始的全部字元複製到字串char *s
中。若 m
超過輸入字串的長度,則結果字串應為空串。
void strmcpy(char *t, int m, char *s) { // 因為s本來就是空的,所以直接返回,s就是空字串 if (!t) return; // t 如果是空的,直接返回 while (m > 1) // 從 1 開始 { if (*t == '\0') return; // m 大於 t 的長度了,直接返回 --m; ++t; } while (*t != '\0') *(s++) = *(t++); *s = '\0'; }
6-2 刪除字元
本題要求實現一個刪除字串中的指定字元的簡單函式。
函式介面定義:
void delchar( char *str, char c );
其中char *str
是傳入的字串,c
是待刪除的字元。函式delchar
的功能是將字串str
中出現的所有c
字元刪除。
解:
常規做法有兩種:
- 從前往後遍歷字串,如果是要刪除的就把後邊所有的前移一位
- 從前往後遍歷字串,把要保留的部分放到一個新的字串陣列中,再賦值會給 str
第一個方法不需要額外的空間,但是如果要刪除的字元出現的次數很多的話,會非常非常慢
void delchar(char *str, char c)
{
if (!str) return;
char tmp[201]; // 21不夠長
char *tHead = tmp, *tStr = str;
int foundc = 0;
while (*tStr != '\0')
{
if (*tStr == c)
{
++tStr;
foundc = 1;
}
else
*(tHead++) = *(tStr++);
}
if(foundc == 0) return ; // 沒有要刪除的就直接返回
if(tHead == tmp) // 字串中全都是字元 c,也就是刪除之後都沒了
{
*str = '\0';
return;
}
tStr = str;
tHead = tmp;
while (*tHead != '\0')
*tStr++ = *tHead++;
*tStr = '\0';
}
6-3 字串的連線
本題要求實現一個函式,將兩個字串連線起來。
函式介面定義:
char *str_cat( char *s, char *t );
函式str_cat
應將字串t
複製到字串s
的末端,並且返回字串s
的首地址。
char* str_cat(char* s, char* t)
{
char* tmps = s;
while(*tmps != '\0') ++tmps;
while(*t != '\0') *tmps++ = *t++;
*tmps = '\0';
return s; // 最後要返回 s 的首地址
}
6-4 函式實現字串逆序
函式介面定義:
void f( char *p );
函式f
對p
指向的字串進行逆序操作。要求函式 f
中不能定義任何陣列,不能呼叫任何字串處理函式。
解:
既然不讓定義陣列,那肯定就是要在 p 這個字串陣列自身中交換元素,達到逆序效果,所以需要先得到字串長度,然後對著交換對應元素就行。
void f(char *p)
{
char* tmp = p;
int len = 0;
while(*tmp != '\0') // 得到的 len 是不包括 '\0' 的長度
{
++tmp;
++len;
}
for(int i = 0; i < len / 2; i++) // 不需要 <=
{
char t = p[i];
p[i] = p[len - 1 - i];
p[len - 1 - i] = t;
}
p[len] = '\0';
}
6-5 指定位置輸出字串
本題要求實現一個函式,對給定的一個字串和兩個字元,打印出給定字串中從與第一個字元匹配的位置開始到與第二個字元匹配的位置之間的所有字元。
函式介面定義:
char *match( char *s, char ch1, char ch2 );
函式match
應列印s
中從ch1
到ch2
之間的所有字元,並且返回ch1
的地址。
char* match(char* s, char ch1, char ch2)
{
char *tmps1 = s;
while (*tmps1 != ch1)
{
if (*tmps1 == '\0') // 沒有找到ch1,直接返回
{
printf("\n");
char* ret = "\0";
return ret; // 必須這樣才能過第二個測試點
}
++tmps1;
}
// 迴圈結束 tmps1 就是 ch1 的位置
char *tmps1res = tmps1;
while (*tmps1 != '\0')
{
printf("%c", *tmps1++);
if (*tmps1 == ch2)
{
printf("%c\n", ch2);
return tmps1res;
}
}
printf("\n");
return tmps1res;
}
6-6 查詢子串
本題要求實現一個字串查詢的簡單函式。
函式介面定義:
char *search( char *s, char *t );
函式search
在字串s
中查詢子串t
,返回子串t在s
中的首地址。若未找到,則返回NULL。
char* search(char *s, char *t)
{
char* tmps = s;
while(1)
{
if(*tmps == '\0') return NULL;
if(*tmps == *t)
{
char *res = tmps, *tmpt = t;
while(1)
{
++tmps;
++tmpt;
if(*tmpt == '\0') return res; // 把t匹配完了都是對的,那就是找到了
if(*tmps == '\0' || *tmpt == '\0' || *tmps != *tmpt) break;
}
}
++tmps;
}
}
7-1 找最小的字串
本題要求編寫程式,針對輸入的N個字串,輸出其中最小的字串。
輸入格式:
輸入第一行給出正整數N;隨後N行,每行給出一個長度小於80的非空字串,其中不會出現換行符,空格,製表符。
輸出格式:
在一行中用以下格式輸出最小的字串:
Min is: 最小字串
輸入樣例:
5
Li
Wang
Zha
Jin
Xian
輸出樣例:
Min is: Jin
#include <stdio.h>
int main()
{
int n;
scanf("%d", &n);
char ch[n][81];
for(int i = 0; i < n; i++) scanf("%s", ch[i]);
int min_idx = 0;
for(int i = 1; i < n; i++)
for(int j = 0; j < 81; j++)
{
if(ch[i][j] > ch[min_idx][j])
break;
if(ch[i][j] < ch[min_idx][j] || (ch[i][j] == '\0' && ch[min_idx][j] != '\0'))
{
min_idx = i;
break;
}
}
printf("Min is: %s\n", ch[min_idx]);
return 0;
}
7-2 字串排序
本題要求編寫程式,讀入5個字串,按由小到大的順序輸出。
輸入格式:
輸入為由空格分隔的5個非空字串,每個字串不包括空格、製表符、換行符等空白字元,長度小於80。
輸出格式:
After sorted:
每行一個字串
輸入樣例:
red yellow blue green white
輸出樣例:
After sorted:
blue
green
red
white
yellow
解:
下面這個是沒有用 strlen、strcmp、strcpy 的方法。
#include <stdio.h>
int main()
{
char ch[5][81];
char c;
// 讀取五個字串 (scanf("%s") 遇空格停止)
for(int i = 0; i < 5; i++)
scanf("%s", ch[i]);
int flag[5] = { 1, 1, 1, 1, 1 }; // 1表示沒有輸出過,0表示輸出過了
printf("After sorted:\n");
for(int i = 0; i < 5; i++) // 共輸出5次,每次選最小的,並讓對應flag為0
{
int min_idx = -1;
for(int j = 0; j < 5; j++)
{
if (flag[j] == 0) continue;
if (min_idx == -1)
{
min_idx = j;
continue;
}
for (int t = 0; t < 81; t++)
{
if (ch[min_idx][t] == '\0')
break;
if(ch[j][t] == '\0' || ch[j][t] < ch[min_idx][t])
{
min_idx = j;
break;
}
if (ch[j][t] > ch[min_idx][t])
break;
}
}
printf("%s\n", ch[min_idx]); // 輸出最小的字串
flag[min_idx] = 0;
}
return 0;
}
用string.h中的函式就會簡單一些。
#include <stdio.h>
#include <string.h>
int main()
{
char ch[5][81];
char c;
// 讀取五個字串
for(int i = 0; i < 5; i++)
scanf("%s", ch[i]);
int flag[5] = { 1, 1, 1, 1, 1 }; // 1表示沒有輸出過,0表示輸出過了
printf("After sorted:\n");
for(int i = 0; i < 5; i++) // 共輸出5次,每次選最小的,並讓對應flag為0
{
int min_idx = -1;
for(int j = 0; j < 5; j++)
{
if (flag[j] == 0) continue;
if (min_idx == -1)
{
min_idx = j;
continue;
}
// 比較兩個字串大小
if(strcmp(ch[j], ch[min_idx]) < 0)
min_idx = j;
}
printf("%s\n", ch[min_idx]); // 輸出最小的字串
flag[min_idx] = 0;
}
return 0;
}
7-3 找最長的字串
本題要求編寫程式,針對輸入的N個字串,輸出其中最長的字串。
輸入格式:
輸入第一行給出正整數N;隨後N行,每行給出一個長度小於80的非空字串,其中不會出現換行符,空格,製表符。
輸出格式:
在一行中用以下格式輸出最長的字串:
The longest is: 最長的字串
如果字串的長度相同,則輸出先輸入的字串。
輸入樣例:
5
li
wang
zhang
jin
xiang
輸出樣例:
The longest is: zhang
#include <stdio.h>
#include <string.h>
int main()
{
int n, max_len = 0, max_idx = -1;
scanf("%d", &n);
char ch[n][81];
for(int i = 0; i < n; i++)
{
scanf("%s", ch[i]);
if(strlen(ch[i]) > max_len)
{
max_len = strlen(ch[i]);
max_idx = i;
}
}
printf("The longest is: %s\n", ch[max_idx]);
return 0;
}
7-4 A-B
本題要求你計算A−B。不過麻煩的是,A和B都是字串 —— 即從字串A中把字串B所包含的字元全刪掉,剩下的字元組成的就是字串A−B。
輸入格式:
輸入在2行中先後給出字串A和B。兩字串的長度都不超過104,並且保證每個字串都是由可見的ASCII碼和空白字元組成,最後以換行符結束。
輸出格式:
在一行中打印出A−B的結果字串。
輸入樣例:
I love GPLT! It's a fun game!
aeiou
輸出樣例:
I lv GPLT! It's fn gm!
#include <stdio.h>
#include <string.h>
int main()
{
int i= 0;
char a[10001], b[10001], res[10001], ch;
while((a[i] = getchar()) != '\n')
++i;
a[i] = '\0';
i = 0;
while((b[i] = getchar()) != '\n')
++i;
b[i] = '\0';
int cur = 0;
for(i = 0; a[i] != '\0'; i++)
{
int isfound = 0;
for(int j = 0; b[j] != '\0'; j++)
if(a[i] == b[j])
{
isfound = 1;
break;
}
if(isfound == 0)
res[cur++] = a[i];
}
res[cur] = '\0';
printf("%s\n", res);
return 0;
}