算法竞赛入门经典第三章

本文介绍了数组的操作方法,包括内存拷贝、初始化等,并详细讲解了字符串处理的多种应用场景,如字符串复制、比较及字符串匹配等。此外还通过具体实例展示了如何解决实际问题。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

3.1数组

数组较大

比较大的数组尽量声明在main函数外,否则程序可能无法进行。

数组操作

如果要从数组a复制k个元素到数组b,可以这样做:memcpy(b,a,sizeof(int)*k)
如果数组a和b都是浮点型的,复制时要写成memcpy(b,a,sizeof(double)*k)
另外需要注意的是, 使用memcpy函数要包含头文件string.h
如果需要把数组a全部复制到数组b中,可以写得简单 一些:memcpy(b,a,sizeof(a))

开灯问题

有n盏灯,编号为1~n。第1个人把所有灯打开,第2个人按下所有编号为2的倍数的开关(这些灯将被关掉),第3个人按下所有编号为3的倍数的开关(其中关掉的灯将被打开,开着的灯将被关闭),依此类推。一共有k个人,问最后有哪些灯开着?输入n和k,输出开着的灯的编号。k≤n≤1000。
样例输入:
7 3
样例输出:
1 5 6 7

#include<stdio.h> 
#include<string.h>
#define maxn 1010  //在算法竞赛中,难以精确计算出需要的数组大小,数组一般会声明的稍大一些。 
int a[maxn];
int main() 
{  
    int n,k,first=1;  //first变量可以表示当前要输出的变量是否为第一个。第一个变量前不应有空格,但其他变量都有。
    memset(a,0,sizeof(a));  //把数组a清零 
    scanf("%d%d",&n,&k);  //n盏灯,k个人 
    for(int i=1;i<=k;i++)
        for(int j=1;j<=n;j++)
            if(j%i==0)   //判断是k的倍数
                a[j]=!a[j];
    for(int i=1;i<=n;i++)
        if(a[i]){
            if(first)   
                first=0;
            else    
                printf(" ");
            printf("%d",i);
        } 
    printf("\n");
    return 0; 
}

蛇形填数

在n×n方阵里填入1,2,…,n×n,要求填成蛇形。例如,n=4时方阵为:
10 11 12 1
9 16 13 2
8 15 14 3
7 6 5 4
上面的方阵中,多余的空格只是为了便于观察规律,不必严格输出。n≤8。

#include<stdio.h> 
#include<string.h>
#define maxn 20 
int a[maxn][maxn];
int main() 
{  
    int n,x,y,tot=0;
    scanf("%d",&n);
    memset(a,0,sizeof(a));//把数组a清零 
    tot=a[x=0][y=n-1]=1;
    while(tot<n*n)  //判断是否填满 
    {
        while(x+1<n && !a[x+1][y])  
            a[++x][y]=++tot;//判断是否越界 向下 
        while(y-1>=0 && !a[x][y-1]) 
            a[x][--y]=++tot;//判断是否越界 向左 
        while(x-1>=0 && !a[x-1][y]) 
            a[--x][y]=++tot;//判断是否越界 向上 
        while(y+1<n && !a[x][y+1])  
            a[x][++y]=++tot;//判断是否越界 向右 
    }
    for(x=0;x<n;x++)
    {
        for(y=0;y<n;y++)
            printf("%3d",a[x][y]);
        printf("\n");
    }
    return 0; 
}

3.2字符数组

竖式问题

找出所有形如abc*de(三位数乘以两位数)的算式,使得在完整的竖式中, 所有数字都属于一个特定的数字集合。输入数字集合(相邻数字之间没有空格),输出所有竖式。每个竖式前应有编号,之后应有一个空行。最后输出解的总数。具体格式见样例输出 (为了便于观察,竖式中的空格改用小数点显示,但所写程序中应该输出空格,而非小数点)。

样例输入:
2357
样例输出:
<1>
..775
X..33
----
.2325
2325.
----
25575
The number of solutions = 1
#include<stdio.h> 
#include<string.h>
int main() 
{  
    int count=0;
    printf("%d%d%d",count++,count++,count++);
    char s[20],buf[99]; 
    scanf("%s",s);
    for(int abc=111;abc<=999;abc++)
        for(int de=11;de<=99;de++)
        {
            int x=abc*(de%10),y=abc*(de/10),z=abc*de;  //x为abc乘以de的个位,y为abc乘以de的十分位,z为abc乘以de的和 
            sprintf(buf,"%d%d%d%d%d",abc,de,x,y,z); //printf输出到屏幕,fprintf输出到文件,而sprintf输出到字符串 
            int ok=1;
            for(int i=0;i<strlen(buf);i++)//函数strlen(s)的作用是获取字符串s的实际长度
                if(strchr(s,buf[i])==NULL)  //strchr的作用是在一个字符串中查找单个字符
                {
                    ok=0;
                    break;  //跳出循环 
                }    
            if(ok)
            {
                printf("<%d>\n",++count);
                printf("%5d\nX%4d\n-----\n%5d\n%4d\n-----\n%5d\n\n",abc,de,x,y,z);
            }
        } 
    printf("The number of solutions = %d\n",count);
    return 0; 
}

输入字符串

scanf("%s", s)scanf("%d", &n)类似,它会读入一个不含空格、 TAB和回车符的字符串,存入字符数组s。注意,不是scanf("%s", &s),s前面没有“&”符 号。
scanf("%s", s)中,不要在s前面加上“&”符号。如果是字符串数组char s[maxn] [maxl],可以用scanf("%s", s[i])读取第i个字符串。注意,scanf("%s", s)遇到空白字符会停下来。

printf,fprintf,sprintf的区别

printf输出到屏幕
fprintf输出到文件
sprintf输出到字符串
可以用sprintf把信息输出到字符串,用法和printf、fprintf类似。但应当保 证字符串足够大,可以容纳输出信息。
多大才算足够大呢?答案是字符个数加1,因为C语言的字符串是以空字符“\0”结尾的。

字符串函数

C语言中的字符串是以“\0”结尾的字符数组,可以用strlen(s)返回字符串s中结束标记之前的字符个数。字符串中的各个字符是s[0], s[1],…,s[strlen(s)-1]
由于字符串的本质是数组,只能用strcpy(a, b), strcmp(a, b), strcat(a, b)来执行“赋值”、“比较”和“连接”操作,而不能用“=”、“==”、 “<=”、“+”等运算符。上述函数都在string.h中声明。
如果输入是“2357”,那么实际上s只保存了5个字符(不 忘记了还有一个结束标记“\0”),后面15个字符是不确定的(还记得吗?变量在赋值之前是不确定的)。strlen(s)返回的就是结束标记之前的字符个数。因此这个字符串中的各个字符依次是s[0], s[1],…, s[strlen(s)-1],而s[strlen(s)]正是结束标记\0

3.3竞赛题目选讲

例题3-1 TeX中的引号(Tex Quotes, UVa 272)

在TeX中,左双引号是““”,右双引号是“””。输入一篇包含双引号的文章,你的任务是把它转换成TeX的格式。
样例输入:

"To be or not to be," quoth the Bard, "that is the question".

样例输出:

``To be or not to be,'' quoth the Bard, ``that is the question''.
#include<stdio.h> 
int main() 
{  
    int c,q=1;
    while((c=getchar())!=EOF) //用getchar()可以边读边处理,而不需要把输入字符串完整地存下来
    {
        if(c=='"')
        {
            printf("%s",q?"``":"''");
            q=!q;
        }
        else
            printf("%c",c);
    }
    return 0; 
}

例题3-2 WERTYU(WERTYU, UVa10082)

把手放在键盘上时,稍不注意就会往右错一位。这样,输入Q会变成输入W,输入J会变成输入K等。
输入一个错位后敲出的字符串(所有字母均大写),输出打字员本来想打出的句子。输入保证合法,即一定是错位之后的字符串。例如输入中不会出现大写字母A。
样例输入:
O S, GOMR YPFSU/
样例输出:
I AM FINE TODAY.
这里写图片描述

#include<stdio.h> 
char s[]="`1234567890-=QWERTYUIOP[]\\ASDFGHJKL;'ZXCVBNM,./"; //输入保证合法,所以可以使用这个方法,否则还要判断
int main() 
{  
    int i,c;
    while((c=getchar())!=EOF)
    {
        for(i=1;s[i]&&s[i]!=c;i++); //找错位之后的字符在常量表中的位置
        if(s[i])    
            putchar(s[i-1]); //如果找到,则输出它的前一个字符
        else putchar(c); 
    }
    return 0; 
}

例题3-3 回文词(Palindromes, UVa401)

输入一个字符串,判断它是否为回文串以及镜像串。输入字符串保证不含数字0。所谓回文串,就是反转以后和原串相同,如abba和madam。所有镜像串,就是左右镜像之后和原串相同,如2S和3AIAE。注意,并不是每个字符在镜像之后都能得到一个合法字符。在本题中,每个字符的镜像如图3-3所示(空白项表示该字符镜像后不能得到一个合法字符)。
这里写图片描述
输入的每行包含一个字符串(保证只有上述字符。不含空白字符),判断它是否为回文串和镜像串(共4种组合)。每组数据之后输出一个空行。

样例输入:
NOTAPALINDROME
ISAPALINILAPASI
2A3MEAS
ATOYOTA
样例输出:
NOTAPALINDROME -- is not a palindrome.
ISAPALINILAPASI -- is a regular palindrome.
2A3MEAS -- is a mirrored string.
ATOYOTA -- is a mirrored palindrome.
#include<stdio.h> 
#include<string.h>
#include<ctype.h>
const char* rev="A   3  HIL JM O   2TUVWXY51SE Z  8 ";
const char* msg[]={"not a palindrome","a regular palindrome",
"a mirrored string","a mirrored palindrome"};

char r(char ch)
{
    if(isalpha(ch))  //判断字符是否为字母,需要添加头文件#include<ctype.h>
        return rev[ch - 'A'];
    return rev[ch - '0' + 25];
}
int main() 
{  
    char s[30];
    while(scanf("%s",s)==1)
    {
        int len=strlen(s);
        int p=1,m=1;
        for(int i=0;i<(len+1)/2;i++)
        {
            if(s[i]!=s[len-1-i])
                p=0;//不是回文串
            if(r(s[i])!=s[len-1-i])
                m=0;//不是镜像串 
        }
        printf("%s -- is %s.\n\n",s,msg[m*2+p]); 
    }
    return 0; 
}

头文件ctype.h

头文件ctype.h中定义的isalpha、isdigit、isprint等工具可以用来判断字符的属性,而toupper、tolower等工具可以用来转换大小写。如果ch是大写字母,则ch-‘A’就是它在字母表中的序号(A的序号是0,B的序号是1,依此类推);类似地,如果ch是数字, 则ch-‘0’就是这个数字的数值本身。

例题3-4 猜数字游戏的提示(Master-Mind Hints, UVa 340)

实现一个经典”猜数字”游戏。给定答案序列和用户猜的序列,统计有多少数字位置正确 (A),有多少数字在两个序列都出现过但位置不对(B)。
输入包含多组数据。每组输入第一行为序列长度n,第二行是答案序列,接下来是若干猜测序列。猜测序列全0时该组数据结束。n=0时输入结束。

样例输入:
4
1 3 5 5
1 1 2 3
4 3 3 5
6 5 5 1
6 1 3 5
1 3 5 5
0 0 0 0
10
1 2 2 2 4 5 6 6 6 9
1 2 3 4 5 6 7 8 9 1
1 1 2 2 3 3 4 4 5 5
1 2 1 3 1 5 1 6 1 9
1 2 2 5 5 5 6 6 6 7
0 0 0 0 0 0 0 0 0 0
0
样例输出:
Game 1:  
  (1,1)    
  (2,0)    
  (1,2)    
  (1,2)    
  (4,0) 
Game 2:    
  (2,4)
  (3,2)    
  (5,0)    
  (7,0)
#include<stdio.h> 
#define maxn 1010 
int main() 
{  
    int n,a[maxn],b[maxn];
    int kase=0;
    while(scanf("%d",&n)==1&&n)  //n=0时输入结束 ,n为序列长度 
    {
        printf("Game %d:\n",++kase);
        for(int i=0;i<n;i++)   //答案序列a 
            scanf("%d",&a[i]);
        for(;;) 
        {
            int A=0,B=0;
            for(int i=0;i<n;i++) //猜测序列b 
            {
                scanf("%d",&b[i]);
                if(a[i]==b[i]) //数字和位置都正确的个数A 
                    A++;
            }
            if(b[0]==0)
                break;//正常的猜测序列中不会有0,所以只判断第一个数是否为0即可
            for(int d=1;d<=9;d++)  //为了求B,对于每个数字(1~9),统计二者出现的次数c1和c2,则 min(c1,c2)就是该数字对B的贡献,最后要减去A的部分
            {
                int c1=0,c2=0;//统计数字d在答案序列和猜测序列中各出现多少次
                for(int i=0;i<n;i++) 
                {
                    if(a[i]==d)
                        c1++;
                    if(b[i]==d)
                        c2++;
                } 
                if(c1<c2)
                    B+=c1;
                else
                    B+=c2;
            } 
            printf("   (%d,%d)\n",A,B-A);
        }
    }
    return 0; 
}

例题3-5 生成元(Digit Generator, ACM/ICPC Seoul 2005, UVa1583)

如果x加上x的各个数字之和得到y,就说x是y的生成元。给出n(1≤n≤100000),求最小生成元。无解输出0。例如,n=3,输入216,121,2005时的解分别为198,0,1979。

#include<stdio.h>
#include<string.h> 
#define maxn 100005
int ans[maxn];
int main() 
{  
    int T,n;
    memset(ans,0,sizeof(ans));
    for(int m=1;m<maxn;m++)
    {
        int x=m,y=m;
        while(x>0)
        {
            y+=x%10; //y为生成元 
            x/=10;
        }
        if(ans[y]==0||m<ans[y]) 
            ans[y]=m; //m加上m的各个数字之和得到的数有一个生成元是y 
    }
    scanf("%d",&T);  //没有特别理解这句话的含义,感觉就是可以重复输入三个n值 
    while(T--)
    {
        scanf("%d",&n);
        printf("%d\n",ans[n]);
    }
    return 0; 
}

例题3-6 环状序列(Circular Sequence, ACM/ICPC Seoul 2004, UVa1584)

长度为n的环状串有n种表示法,分别为从某个位置开始顺时针得到。例如,图3-4的环状串有10种表示:
CGAGTCAGCT,GAGTCAGCTC,AGTCAGCTCG等。在这些表示法中,字典序最小的称 为”最小表示”。
这里写图片描述
输入一个长度为n(n≤100)的环状DNA串(只包含A、C、G、T这4种字符)的一种表示法,你的任务是输出该环状串的最小表示。例如,CTCC的最小表示是 CCCT,CGAGTCAGCT的最小表示为AGCTCGAGTC。

#include<stdio.h>
#include<string.h> 
#define maxn 105
//环状串s的表示法p是否比表示法q的字典序小
int less(const char *s,int p, int q)
{
    int n=strlen(s);
    for(int i=0;i<n;i++)
    {
        if(s[(p+i)%n]!=s[(q+i)%n])
            return s[(p+i)%n]<s[(q+i)%n];
    }
    return 0;//相等 
} 
int main() 
{  
    int T;
    char s[maxn];
    scanf("%d",&T);  //可循环输入的次数 
    while(T--)
    {
        scanf("%s",s);   //环状串 
        int ans=0;
        int n=strlen(s);
        for(int i=1;i<n;i++) 
            if(less(s,i,ans)) 
                ans=i;
        for(int i=0;i<n;i++)
            putchar(s[(i+ans)%n]);
        putchar('\n');
    } 
    return 0; 
}

字典序

所谓字典序,就是字符串在字典中的顺序。一般地, 对于两个字符串,从第一个字符开始比较,当某一个位置的字符不同时,该位置字符较小的串,字典序较小(例如,abc比bcd小);如果其中一个字符串已经没有更多字符,但另一个字符串还没结束,则较短的字符串的字典序较小(例如,hi比history小)。字典序的概念可以推广到任意序列,例如,序列1, 2, 4, 7比1, 2, 5小。

3.4注解与习题

习题3-1 得分(Score, ACM/ICPC Seoul 2005, UVa1585)

给出一个由O和X组成的串(长度为1~80),统计得分。每个O的得分为目前连续出现的O的个数,X的得分为0。例如,OOXXOXXOOO的得分为1+2+0+0+1+0+0+1+2+3。

#include<stdio.h> 
#include<string.h>
char s[81];
int main() 
{     
    scanf("%s", s);  
    int countO = 0;  
    for(int i = 0; i < strlen(s); i++) 
    {
        if(s[i] == 'X') 
        {
            printf("0");
            countO=0;   
        }
        else
        {
            printf("%d",++countO);
        }
        if(i!=strlen(s)-1)
            printf("+");
    }   
    return 0;
} 

习题3-2 分子量(Molar Mass, ACM/ICPC Seoul 2007, UVa1586)

给出一种物质的分子式(不带括号),求分子量。本题中的分子式只包含4种原子,分 别为C, H, O, N,原子量分别为12.01, 1.008, 16.00, 14.01(单位:g/mol)。例如,C6H5OH的 分子量为94.108g/mol。

输入: 
4 
C 
C6H5OH 
NH2CH2COOH 
C12H22O11

输出: 
12.010 
94.108 
75.070 
342.296
#include<stdio.h> 
#include<ctype.h>
#define maxn 85
const double d[] = {0,0,12.01,0,0,0,0,1.008,0,0,0,0,0,14.01,16.00};
char s[maxn];
int main() 
{  
    int t;    
    scanf("%d", &t); 
    while(t--)
    {
        double sum=0;
        int i,n;
        scanf("%s",s);
        char x=s[0];
        for(i=0;s[i]!='\0';++i)
        {
            if(isalpha(s[i]))  //如果是字母 
            {
                x=s[i];//将s中的字母赋值给x
                sum+=d[x-'A'];//sum加上d[]中对应位置上的原子量 
            }
            else  //如果是数字 
            {
                n=s[i]-'0';//将数字赋值给n
                while(isdigit(s[i+1]))  //s下一个也是数字 
                {
                    n=n*10+(s[i+1]-'0');
                    i++; 
                } //一直到不是数字位置 
                sum+=d[x-'A']*(n-1);//x在if已经被赋值,-1是因为if里加了一个 
            } 
        }
        printf("%.3f\n",sum); 
    } 

    return 0;
} 

习题3-3 数数字(Digit Counting , ACM/ICPC Danang 2007, UVa1225)

把前n(n≤10000)个整数顺次写在一起:123456789101112…数一数0~9各出现多少次 (输出10个整数,分别是0,1,…,9出现的次数)。

#include<stdio.h> 
#include<string.h>
#define maxn 85
char s[maxn];
int main() 
{ 
    int a[10]={0,0,0,0,0,0,0,0,0,0};      
    scanf("%s", s); 
    for(int i=0;i<strlen(s);i++)
    {
        switch(s[i]) 
        {
            case '0':   a[0]++;break;
            case '1':   a[1]++;break;
            case '2':   a[2]++;break;
            case '3':   a[3]++;break;
            case '4':   a[4]++;break;
            case '5':   a[5]++;break;
            case '6':   a[6]++;break;
            case '7':   a[7]++;break;
            case '8':   a[8]++;break;
            case '9':   a[9]++;break;
            default:    break;
        }
    }
    for(int i=0;i<10;i++)
        printf("%d\n",a[i]);
    return 0;
} 

习题3-4 周期串(Periodic Strings, UVa455)

如果一个字符串可以由某个长度为k的字符串重复多次得到,则称该串以k为周期。例 如,abcabcabcabc以3为周期(注意,它也以6和12为周期)。
输入一个长度不超过80的字符串,输出其最小周期。

输入: 
3 
haha 
hellohellohello 
hehehihehehihehehi

输出: 
2 
5 
6
#include<stdio.h> 
#include<string.h>
#define maxn 85
char s[maxn];
int main() 
{ 
    int n;
    scanf("%d",&n);
    while(n--)
    {
        scanf("%s",s);  
        int l=strlen(s);
        int k,i;
        for(int i=1;i<l;i++)
        {
            if(l%i==0)  //l可以被i整除 
            {
                for(k=i;k<l;k++)
                {
                    if(s[k]!=s[k%i])//注意算法!后k个位置上的字母都与k%i(就是前i个字母)比较
                        break;
                }
                if(k==l)
                {
                    printf("%d\n",i);
                    break;//最小的周期 
                }
            }
        }
        if(n)   printf("\n"); 
    }
    return 0;
} 

习题3-5 谜题(Puzzle, ACM/ICPC World Finals 1993, UVa227)

有一个5*5的网格,其中恰好有一个格子是空的,其他格子各有一个字母。一共有4种指令:A, B, L, R,分别表示把空格上、下、左、右的相邻字母移到空格中。输入初始网格和指令序列(以数字0结束),输出指令执行完毕后的网格。如果有非法指令,应输出“This puzzle has no final configuration.”,例如,图3-5中执行ARRBBL0后,效果如图3-6所示。
这里写图片描述

输入: 
TRGSJ 
XDOKI 
M_VLN 
WPABE 
UQHCF 

ARRBBL0 

ABCDE 
FGHIJ 
KLMNO 
PQRS_ 
TUVWX 

AAA 
LLLL0 

ABCDE 
FGHIJ 
KLMNO 
PQRS_ 
TUVWX 

AAAAABBRRRLL0 
Z

输出: 
Puzzle #1: 
T R G S J 
X O K L I 
M D V B N 
W P _ A E 
U Q H C F

Puzzle #2: 
_ A B C D 
F G H I E 
K L M N J 
P Q R S O 
T U V W X

Puzzle #3: 
This puzzle has no final configuration.
#include<stdio.h>
#include<string.h>
#include <cctype>
#define maxn 5

const int dir[4][2] = {{-1, 0}, {1, 0}, {0, 1}, {0, -1}};
const char s[] = "ABRL";
char a[maxn][maxn];

int main() {
    int t = 0;
    while(gets(a[0])) {//注意读的是第一行!
        //读入
        if(a[0][0] == 'Z') break;//判断的是第一个字母
        if (t) 
        {
            puts("");
        }
        int m = 0, n = 0;  //记录标记字符位置 
        for(int i = 0; i < maxn; i++) 
        {
            if (i) 
            {//不是第一行
                gets(a[i]);
            }
            for(int j = 0; j < maxn; j++) 
            {
                if(a[i][j]  == '_' || a[i][j] == 0) 
                {//注意 前四个位置是否有空,或第五个位置(字符串尾)为空不显示!且若||前面的成立不读后面的!
                    a[i][j] = '_';
                    m = i; n = j;//将空的位置记下来
                }
            }
        }

        //移动
        bool ok = true;  //判断是否移动了
        for (;;) 
        {
            char c = getchar();
            if (c == '0') 
            {
                break;
            }
            bool q = isspace(c);//isspace(c):检查参数c是否为空白字符,是为真,否为假
            for (int i = 0; i < 4 && ok; i++) 
            {
                if (c == s[i]) 
                {//c为R,L,A,B中的一个
                    q = true;
                    int x = m + dir[i][0], y = n + dir[i][1];//将新的位置算出(方法巧不用写那么多)
                    if (x < 0 || x > 4 || y < 0 || y > 4) 
                    {
                        ok = false;
                        break;
                    }
                    a[m][n] = a[x][y];//将移动位置上的字母给空的位置
                    a[x][y] = '_';//将新位置为空
                    m = x, n = y;//重新记新的位置
                }
            }
            if (!q) {// q 是为了判断是否是空白字符的时候
                ok = false;
            }
        }

        //输出
        printf("Puzzle #%d:\n", ++t);
        if (ok) 
        {
            for(int i = 0; i <= 4; ++i) 
            {
                for(int j = 0; j <= 4; ++j) 
                {
                    if (j) 
                    {
                        printf(" ");//输空格用的,最后字母后没空格
                    }
                    printf("%c", a[i][j]);
                }
                printf("\n");
            }
        }
        else {
            printf("This puzzle has no final configuration.\n");
        }
    }
    return 0;
}

C语言 gets()和scanf()函数的区别

scanf( )函数和gets( )函数都可用于输入字符串,但在功能上有区别。若想从键盘上输入字符串”hi hello”,则应该使用gets函数。
gets可以接收空格;而scanf遇到空格、回车和Tab键都会认为输入结束,所有它不能接收空格。
char string[15]; gets(string); /遇到回车认为输入结束/
scanf("%s",string); /遇到空格认为输入结束/
所以在输入的字符串中包含空格时,应该使用gets输入。
在C语言中,能构获取字符串的函数至少有两个:
1.scanf()
所在头文件:stdio.h
语法:scanf(“格式控制字符串”,变量地址列表);
接受字符串时:scanf(“%s”,字符数组名或指针);
2.gets()
所在头文件:stdio.h
语法:gets(字符数组名或指针);
两者在接受字符串时:
1.不同点:
scanf不能接受空格、制表符Tab、回车等;
而gets能够接受空格、制表符Tab和回车等;
2.相同点:
字符串接受结束后自动加’\0’。
例1:

#include <stdio.h>
main()
{
    char ch1[10],ch2[10];
    scanf("%s",ch1);
    gets(ch2);
}

依次键入asd空格fg回车,asd空格fg回车,则ch1=”asd\0”,ch2=”asd fg\0”。

例2:

#include <stdio.h>
main()
{
    char ch1[10],ch2[10],c1,c2;
    scanf("%s",ch1);
    c1=getchar();
    gets(ch2);
    c2=getchar();
}

依次键入asdfg回车,asdfg回车,则ch1=”asdfg\0”,c1=’\n’,ch2=”asdfg\0”,c2需输入。

scanf :当遇到回车,空格和tab键会自动在字符串后面添加'\0',但是回车,空格和tab键仍会留在输入的缓冲区中。
gets:可接受回车键之前输入的所有字符,并用'\n'替代 '\0',回车键不会留在输入缓冲区中。
gets()用到读取字符串,用回车结束输入。 
scanf()可以读取所有类型的变量。

C语言puts()函数:将一个字符串放入标准输出流(stdout)中

头文件:#include<stdio.h>
puts()函数用于将一字符串放到标准输出流(stdout)中,并在最后增加换行符 ‘\n’,其函数原型如下:
int puts(char *string);
【参数】string为要输出的字符串。
【返回值】输出成功返回非0值,否则返回0。
puts()从string的开头往stdout中输出字符,直到遇见结束标志 ‘\0’,’\0’不会被输出到stdout。

习题3-6  纵横字谜的答案(Crossword Answers, ACM/ICPC World Finals 1994, UVa232)

输入一个r行c列(1≤r,c≤10)的网格,黑格用“*”表示,每个白格都填有一个字母。如果一个白格的左边相邻位置或者上边相邻位置没有白格(可能是黑格,也可能出了网格边界),则称这个白格是一个起始格。
首先把所有起始格按照从上到下、从左到右的顺序编号为1, 2, 3,…,如图3-7所示。
这里写图片描述
接下来要找出所有横向单词(Across)。这些单词必须从一个起始格开始,向右延伸到 一个黑格的左边或者整个网格的最右列。最后找出所有竖向单词(Down)。这些单词必须从一个起始格开始,向下延伸到一个黑格的上边或者整个网格的最下行。

Sample Input
2 2
AT
*O
6 7
AIM*DEN
*ME*ONE
UPON*TO
SO*ERIN
*SA*OR*
IES*DEA
0
Sample Output
puzzle #1:
Across
  1.AT
  3.O
Down
  1.A
  2.TO

puzzle #2:
Across
  1.AIM
  4.DEN
  7.ME
  8.ONE
  9.UPON
 11.TO
 12.SO
 13.ERIN
 15.SA
 17.OR
 18.IES
 19.DEA
Down
  1.A
  2.IMPOSE
  3.MEO
  4.DO
  5.ENTIRE
  6.NEON
  9.US
 10.NE
 14.ROD
 16.AS
 18.I
 20.A
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值