C Prime Plus中文第六版编程题——第十一章练习

  1. 设计并测试一个函数,从输入中获取下n个字符(包括空白、制表 符、换行符),把结果储存在一个数组里,它的地址被传递作为一个参数。
#include <stdio.h>
#include <stdlib.h>
#define N 20
void * string_getn(char *str,int n);
int main()
{           
     char a[N];
     string_getn(a,5);
     puts(a);
     return 0;
}
void * string_getn(char *str,int n){
        for(int i=0;i<n;i++)
         {   scanf("%c",  (str+i)  );}
         *(str+n)='\0';
}

在这里插入图片描述


  1. 修改并编程练习1的函数,在n个字符后停止,或在读到第1个空白、 制表符或换行符时停止,哪个先遇到哪个停止。不能只使用scanf()
#include <stdio.h>
#include <stdlib.h>
#define N 50
void * string_getn(char *str,int n);
int main()
{           
     char a[N];
     string_getn(a,15);
     puts(a);
     return 0;
}
void * string_getn(char *str,int n){
          int i=0;
          while(i<n&& ( str[i]=getchar() )!=' '&& str[i]!='\n'&& str[i]!="\t")
                   i++;
         *(str+i)='\0';
}

在这里插入图片描述


  1. 设计并测试一个函数,从一行输入中把一个单词读入一个数组中,并丢弃输入行中的其余字符。该函数应该跳过第1个非空白字符前面的所有空白。将一个单词定义为没有空白、制表符或换行符的字符序列。
#include <stdio.h>
#include <stdlib.h>
void word(char * str);

int main(){
        char ar[50];
             word(ar);
             puts(ar);
                 word(ar);//检测是否有缓冲区输入干扰
                 puts(ar);
           return 0;
}

void word(char * str){
    char ch;
          while( (  ch=getchar() )==' ')//如果单纯的while(getchar==''){ continue;}
                              //会导致第一个非空格的getchar被略过,因为:getchar(非空格);
            str[0]=ch;                 //str[i]=getchar得到的是第二个非空格数了
           int i=1;
           while( ( str[i]=getchar() )!='\t'&& str[i]!='\n' && str[i]!=' ')
            i++;
            str[i]='\0';
            while(getchar()!='\n')//清除缓冲区
            continue;
}

在这里插入图片描述


  1. 设计并测试一个函数,它类似编程练习3的描述,只不过它接受第2个参数指明可读取的最大字符数。
#include <stdio.h>
#include <stdlib.h>
void word(char * str,int n);

int main(){
        char ar[50];
           word(ar,5);
           puts(ar);
          
           return 0;
}

void word(char * str,int n){
    char ch;
          while( (  ch=getchar() )==' ')//如果单纯的while(getchar==''){}
                     continue;          //会导致第一个非空格的getchar被略过,因为:getchar(非空格);
            str[0]=ch;                 //str[i]=getchar;
           int i=1;
           while( ( str[i]=getchar() )!='\t'&& str[i]!='\n' && str[i]!=' '&&i<n)
            i++;
            str[i]='\0';
            while(getchar()!='\n')
            continue;
}

在这里插入图片描述


  1. 设计并测试一个函数,搜索第1个函数形参指定的字符串,在其中查 找第2个函数形参指定的字符首次出现的位置。如果成功,该函数返指向该 字符的指针,如果在字符串中未找到指定字符,则返回空指针(该函数的功 能与 strchr()函数相同)。在一个完整的程序中测试该函数,使用一个循环 给函数提供输入值
#include <stdio.h>
#include <stdlib.h>
char *find_ch(char * str, char ch);

int main(){
   
        char ar[200];
        char ch;
     
        printf("请输入查找字符:\n");
        scanf("%c",&ch);
                      while (getchar()!='\n') continue;
                      //滤掉scanf的回车,因为puts遇到回车直接结束输入
        printf("请输入字符串:\n");
         gets(ar);
               while( '\0'!=ar[0]){//若为空输入则结束字符串输入循环
                    
                      char *judge=find_ch(ar,ch);//判断是否返回空指针
                    if  ( judge  )
                     puts(judge);//验证:从找到的地方开始输出
                     else
                     printf("none\n");
               
               printf("请输入字符串:\n");
               gets(ar);}
               printf("done!\n");
               
              return 0;
  
}

char *find_ch(char * str, char ch){
         while( *str!='\0'&& *str!=ch){
             str++;}
             if (ch==*str)
              return str;
              if('\0'==*str)
              return NULL;
                            } }

在这里插入图片描述


  1. 编写一个名为is_within()的函数,接受一个字符和一个指向字符串的 指针作为两个函数形参。如果指定字符在字符串中,该函数返回一个非零值 (即为真)。否则,返回0(即为假)。在一个完整的程序中测试该函数, 使用一个循环给函数提供输入值。
#include <stdio.h>
#include <stdlib.h>
int is_within(char ch,char *ptr);
int main()
{
    char input[100];
     char ch;
     int judge;
     printf("请输入字符串(回车结束):\n");
     gets(input);
     while( input[0]!=0){
         printf("请输入查找的字符:\n");
          scanf("%c",&ch);
          judge=is_within(ch,input);
              printf("\n%s%c\n\n",(judge==0)?"没有找到":"找到",ch);
              while (getchar() != '\n')
                       continue;
                            printf("请输入字符串(回车结束):\n");
                            gets(input);
                            
     }
     printf("输入结束");
     
    return 0;
}
int is_within(char ch,char *ptr){
    while( *ptr!='\0'&&*ptr!=ch)
                   ptr++;
         if (*ptr=='\0')
         return 0;
         else
         return 1;
    
}

在这里插入图片描述


  1. strncpy(s1, s2, n)函数把s2中的n个字符拷贝至s1中,截断s2,或者有必要的话在末尾添加空字符。如果s2的长度是n或多于n,目标字符串不能以空字符结尾。该函数返回s1。自己编写一个这样的函数,名为mystrncpy()。在一个完整的程序中测试该函数,使用一个循环给函数提供输入值。
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
void mystrncpy(char *target,char *source,int n);
int main()
{
    char target[100];
    char source[100];
    printf("请输入字符串:\n");
    while  (  gets(source)&&source[0]!=0)            //输入空line结束循环
  {        mystrncpy(target,source,15);
   printf("target输入:");
        fputs(target,stdout);
        printf(" target中有%d个字符\n",strlen(target));//测试末尾是否有换行符
        printf("请输入字符串:\n");
  }printf("输入结束"); 
    return 0;
}
void mystrncpy(char *target,char *source,int n){
          int i=0;
         while(i<n && source[i]!=0){         //copy没满20个字符或者source没全部copy完。
              target[i]=source[i];
               i++;}
               if(i<n-1)       // 从source中copy的数量为i+1,若i+1<n,就可以在最后填上\0。
               target[i]='\0';
}

在这里插入图片描述
对于s2(源字符串)比限定copy的最大长度n小时,会在s2的末尾添加’\0’,所以"I’m real fine"后面跟了一个空字符,字符串长度为13;当s2长度超过限定copy的字符数量时,因为目标字符串没有以空字符串结尾,目标数组s1的n(15)位后被一些奇奇怪怪的东西塞满了,直到第28个位置上被随机塞了一个’\0’字符串才结束


  1. 编写一个名为string_in()的函数,接受两个指向字符串的指针作为参数。如果第2个字符串中包含第1个字符串,该函数将返回第1个字符串开始的地址。例如,string_in(“hats”, “at”)将返回hats中a的地址。否则,该函数返回空指针。在一个完整的程序中测试该函数,使用一个循环给函数提供输入值。
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
char *string_in(char *ptr1,char *ptr2);
int main()
{
    char a[100];
    char b[100];
    char *find;
    printf("please enter the string you are looking for:\n");
        gets(b);
     
    printf("Please enter the string you want to lookup,(enter to quit):\n");
           
          
          while(  gets(a)&&a[0]!='\0'  ){
              
    if(   ( find=string_in(a,b) ) !=NULL    )
        puts(find);
        else
         puts("not find.");
        
          printf("Please enter the string you want to lookup,(enter to quit):\n");
          
         }printf("done");
    
    return 0;
}
char *string_in(char *ptr1,char *ptr2){
    int length2=strlen(ptr2);
    int length1=strlen(ptr1);
    int ch=ptr2[0];
    int i=0;
    char temp[length2+1];
    while(  i<=(length1-length2)  )
    {
        if ( ptr1[i]==ch)
         {
             for(int j=0;j<length2;j++)
             {temp[j]=ptr1[i+j];}
             temp[length2]='\0';
             if( strcmp(temp,ptr2)==0)
                  return (ptr1+i);
         }
        
         i++;  }
         return NULL;
    
}

在这里插入图片描述


  1. 编写一个函数,把字符串中的内容用其反序字符串代替。在一个完整 的程序中测试该函数,使用一个循环给函数提供输入值。
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main()
{
    char source[100];
    
    printf("请输入一条字符串(回车结束输入):\n");
     while( gets(source)&& source[0]!='\0' ){ //gets遇到换行符抛弃并换之为\0
           reverse_line(source);              //第一个元素就为\0意味着空line
             puts(source);
             printf("请继续输入字符串(回车结束输入):\n");
     
     }
             printf("输入结束");
    return 0;
}
void reverse_line(char *str){
        int n=strlen(str);//原字符串有n个字符
           char temp;
           for(int i=0;i<n/2;i++)
           {  temp=str[i]; str[i]=str[n-1-i]; str[n-1-i]=temp;}
        
}

在这里插入图片描述


  1. 编写一个函数接受一个字符串作为参数,并删除字符串中的空格。 在一个程序中测试该函数,使用循环读取输入行,直到用户输入一行空行。 该程序应该应用该函数读取每个输入的字符串,并显示处理后的字符串。
#include <stdio.h>
#include <stdlib.h>
void delete_space(char *source);
int main()
{
    char source[100];
    printf("输入一个字符串:\n");
    while(gets(source)&&source[0]!='\0'){//空line结束
       delete_space(source);
       puts(source);
      printf("请再输入:\n");           }
      printf("输入结束");                                    
           return 0;
}





void delete_space(char *source){
    int index_source=0;
    int index_temp=0; // 建立一个临时数组temp来copy原数组source-
                      //除空格以外的所有元素,并返回给source
      char temp[100];
    while( source[index_source]!='\0')
     {
         if (source[index_source]!=' ')
           {temp[index_temp]=source[index_source];
            index_temp++;}
              index_source++;      //因为只有不为空格才抄写,所以用两组下标
         }
           temp[index_temp]='\0';     //copy结束
           
        for(int i=0;i<=index_temp;i++)  //返回给source数组
            {
                    source[i]=temp[i];
            }
}
     

在这里插入图片描述


  1. 编写一个函数,读入10个字符串或者读到EOF时停止。该程序为用 户提供一个有5个选项的菜单:打印源字符串列表、以ASCII中的顺序打印字符串、按长度递增顺序打印字符串、按字符串中第1个单词的长度打印字符 串、退出。菜单可以循环显示,除非用户选择退出选项。当然,该程序要能真正完成菜单中各选项的功能。
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

void show_menu(void);
char *s_gets(char *str,int n);
int fill_ar(char ar[][50],int n);
void func_a( char a[][50],int n);
void func_b(char a[][50],int n);
void func_c(char a[][50],int n);
void func_d(char a[][50],int n);
int main()                  //参考P359 sort_str.c
{  
    char ar[10][50];
    int ct;
    char ch;
    ct=fill_ar(ar,10);         
      show_menu();
       
       while( ( ch=getchar() ) != 'q'){
       switch (ch){
           case 'a':
           case 'A':
                 func_a(ar,ct);
                    break;
           case 'b':
           case 'B':
                 func_b(ar,ct);
                    break;
           case 'c':
           case 'C':
                 func_c(ar,ct);
                    break;
           case 'd':
           case 'D':
               func_d(ar,ct);
                   break;
              default:
              printf("请输入有效值a,b,c,d,q\n");
                    }
                 show_menu();
            while( getchar()!='\n')
             continue;
                     }   
                printf("输入结束\n");

 
    return 0;
}




void show_menu(void){
     printf("*******************************************************************\n");               
     printf("------------\n");
     printf("请选择功能:|\n");
     printf("------------\n");
     printf("a.打印源字符串列表         b.ASCII顺序打印字符串\n");
     printf("c.长度递增顺序打印字符串   d.第一个单词长度打印字符串    q.结束输入\n");
     printf("*******************************************************************\n");
}
     
char *s_gets(char *str,int n)//str用来收取输入,n提示输入上限
{ 
     char *feedback;
     char *position_enter;
     feedback=fgets(str,n,stdin);
//feedback返回一个指向str的指针,如果str内容为空,返回空指针NULL
     if(feedback){                         
            position_enter=strchr(str,'\n');
                if(position_enter)
                     *position_enter='\0'; 
//对于str,翻遍整个字符串,有回车,则用空字符替换,结束,后面的垃圾字符就不用管了
               else
                     while( getchar()!='\n')
                              ;
/*如果输入阵列输入了很多个字符,超过了str的获取上限n,
直到n+1000才按下回车,则要用getchar()清除输入阵列从n+1到回车的字符*/
     }
     return feedback;//要么为null,要么为str首地址
}

int fill_ar(char ar[][50],int n){
    printf("请输入10行,或途中以enter键结束:\n");
            int ct=0;
            while(ct<n&& s_gets(ar[ct],50)!=NULL&&ar[ct][0]!='\0')
/*假如什么都没输入,则为空line,那么s_gets给出fgets的返回值——NULL,如果一开始
输入了一个回车,再打算输入很多字符,就不是空line,但是在这个while中就默认开头按下
回车(被s_gets)转换为\0 是结束循环*/
                     ct++;
                     return ct;
}

void func_a( char a[][50],int n){    //打印源字符串列表 
 printf("\na.打印源字符串列表\n");
         int i=0;
          while(a[i][0]!='\0'&&i<n){
              puts(a[i]);  i++;
          }
}

void func_b(char a[][50],int n){            //ASCII顺序打印字符串
    printf("\nb.ASCII顺序打印字符串\n");
       char *temp[n];           //定义了一个数组,内含n个指针(不能修改原数组)
       char *exchange;
       
        for(int i=0;i<n;i++)
              temp[i]=a[i];                //顺序标定指针
              
             //排序   指针下标随ASCII顺序递增
             for(int j=0;j<n-1;j++){
                   for(int k=j+1;k<n;k++){
                              if ( strcmp(temp[j],temp[k])>0 )
                              { exchange=temp[j];temp[j]=temp[k];temp[k]=exchange;}
                   }}
              
              for(int i=0;i<n;i++)
                    puts(temp[i]);}

void func_c(char a[][50],int n){            //长度递增顺序打印字符串
    printf("\nc.长度递增顺序打印字符串\n");
       char *temp[n];          
       char *exchange;
        for(int i=0;i<n;i++)   //fun_c照抄fun_b,改掉判定条件if即可
              temp[i]=a[i];              
             for(int j=0;j<n-1;j++){
                   for(int k=j+1;k<n;k++){
                              if (   strlen( temp[j] ) > strlen( temp[k] )  ) 
                                                                        
                  { exchange=temp[j];temp[j]=temp[k];temp[k]=exchange;}
                   }}
                for(int i=0;i<n;i++)
                    puts(temp[i]);}

 void func_d(char a[][50],int n){ //第一个单词长度打印字符串
        printf("\nd.第一个单词长度打印字符串\n");
            
              char *temp[n];           //定义了一个数组,内含n个指针(不能修改原数组)
                char *exchange;        
                  int count;
                  int start,end;//数单词长度
                int first_length[n];   //记单词长度
                  int exchange_count;
        for(int i=0;i<n;i++)
              temp[i]=a[i];                //顺序标定指针
              
              for(int i=0;i<n;i++ ){       //给每个字符串首单词测长度
                           count=0;
                      while( *(temp[i]+count)==' ')   //输入可能为   aaa,即开头可能为空格,要过滤掉
                          {   count++;}    //count相当于一个时钟,记住第一个不为空格的位置,赋给start
                          start=count;
                   while(*(temp[i]+count)!=' '&&*(temp[i]+count)!='\0')
                      { count++;}
                       end=count;         //遇到第一个单词的结尾空格,此时count赋给end
                        first_length[i]=end-start;    //两个空格之间才是真正的首单词长度
                    
              }
               
               for(int j=0;j<n-1;j++){
                   for(int k=j+1;k<n;k++){
                              if (   first_length[j]>first_length[k] ) 
                                                                        
                  { exchange=temp[j];temp[j]=temp[k];temp[k]=exchange;
     exchange_count=first_length[j];first_length[j]=first_length[k];first_length[k]=exchange_count;
                  }//把首单词短的交换到前面来,同时这些字符串各自的单词计数器first_length也要随之交换
                   }}
                for(int i=0;i<n;i++)
                    puts(temp[i]);
                
 }      
                    

输入:
x position
apple tree
banana milk
chocalate and rainy day
simultaneous and instaneous
umbrella and huang feihong
at here
bang bang bang
play game
basketball game
在这里插入图片描述
在这里插入图片描述在这里插入图片描述


  1. 编写一个程序,读取输入,直至读到 EOF,报告读入的单词数、大写字母数、小写字母数、标点符号数和数字字符数。使用ctype.h头文件中的 函数。
#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>
int main()
{  int inword;
    int word=0;
    int a_letter=0;
    int A_letter=0;
    int digit=0;
    int punct=0;
    char getch;
    char ar[2000];
    int i=0;
while(    ( getch=getchar() ) !=   EOF   ){
            ar[i]=getch;i++;
       }
         inword=0;
         for(int j=0;j<i;j++)
         {
             if( isalpha(ar[j])  &&  inword==0 )
                  inword=1;
                 
        if(inword==1  &&  
  (  ispunct(ar[j])  ||  isspace(ar[j])   )                 )
          { word++;
           inword=0;}
          
             if(  islower(ar[j])  )
               a_letter++;
                      
            if( isupper(ar[j]))
                 A_letter++;
                             
                 if(   isdigit(ar[j])     )             
                       digit++;
                       
            if(  ispunct( ar[j] ) )
                 punct++; } 
                 
             printf("%d punctuation , %d lower letter , %d upper letter , %d word and %d digit",
                          punct,a_letter,A_letter,word,digit);
             
             
         
    return 0;
}

在这里插入图片描述


  1. 编写一个程序,反序显示命令行参数的单词。例如,命令行参数是 see you later,该程序应打印later you see。
#include <stdio.h>
#include <stdlib.h>
int main(int argc,char * argv[])
{
    int count;
     
    for(count=argc-1;count>0;count--)
     printf("%s ",argv[count]);
   printf("\n");
    return 0;
}

在这里插入图片描述


  1. 编写一个通过命令行运行的程序计算幂。第1个命令行参数是double 类型的数,作为幂的底数,第2个参数是整数,作为幂的指数。
#include <stdio.h>
#include <stdlib.h>
int main(int argc,char * argv[])
{
     float total=1;
     float base=atof(argv[1]);
      int power=atoi(argv[2]);
      if(base==0)
          {
            if(power==0)
              {printf("It is not defined\n");
               printf("0 power of 0 is 0\n"); }
             else
              { printf("%d power of 0 is 0\n",power);}
          }
        
        else
         {        
               if(power>0)
                       {   for(int i=0;i<power;i++){
                              total*=base;}
                         printf("%d power of %f is %f\n",power,base,total);      
                       }      
               else if(power<0)
                       {   for(int i=0;i<(-1)*power;i++){
                              total*=base;}
                         printf("%d power of %f is %f\n",power,base,1/total);      
                       }      
               else {printf("%d power of %f is 1\n",power,base);  }
            
            
              
         }
    return 0;
}

在这里插入图片描述


  1. 使用字符分类函数实现atoi()函数。如果输入的字符串不是纯数字, 该函数返回0。
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
int go_atoi(char *ptr);
int main()
{
    char a[50];
    printf("字符串输入:\n");
    gets(a);
    printf("数字输出:\n");
    printf("%d\n",go_atoi(a));
    return 0;
}
int go_atoi(char *ptr){
     int i=0;
     int ten_power=1;
     int sum=0;
      while(ptr[i]!='\0'){
          if( !isdigit(ptr[i]) )
          {
              return 0;     //检查从头到尾有没有非数字,记得不要用fget,
                           //fget会录入回车
          }
          i++;
               }
              i--;         //这里的i--是最后一个数字(个位)的下标
      sum=ptr[i]-'0';      //把个位加给sum , 数字字符的ASCII码在48-57之间
       while(--i>=0)
       {ten_power*=10;   // i每次减1都升位
           sum+=(ptr[i]-'0')*ten_power;//百位乘百,千位乘千,加给sum
            }    
       return sum;
}

在这里插入图片描述


  1. 编写一个程序读取输入,直至读到文件结尾,然后把字符串打印出
    来。该程序识别和实现下面的命令行参数:
    -p    按原样打印
    -u    把输入全部转换成大写
    -l     把输入全部转换成小写
    如果没有命令行参数,则让程序像是使用了-p参数那样运行。
#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>
#include <string.h>
int main(int argc,char * argv[])
{ 
    char ch;
    
  if (  strcmp(argv[1],"-u")==0 )
               while( (ch=getchar())!=EOF){
                   if(  isalpha(ch)  )
                   { ch=toupper(ch);
                       putchar(ch);}
                       else
                       putchar(ch);
                                         }
     if(   strcmp(argv[1],"-l")==0   )
         while( (ch=getchar())!=EOF){
                   if(  isalpha(ch)  )
                   { ch=tolower(ch);
                       putchar(ch);}
                       else
                       putchar(ch);
                                         }
            
   if(  strcmp(argv[1],"-p")==0 || argv[1]==NULL)//*直接输入程序名加enter没有实现-p输出
         while( (ch=getchar())!=EOF)
          putchar(ch);
     
    return 0;
}


在这里插入图片描述


  • 4
    点赞
  • 12
    收藏
    觉得还不错? 一键收藏
  • 3
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值