C Primer Plus 第六版---编程练习11

1.设计并测试一个函数,从输入中获取下n个字符(包括空白、制表符、换行符),把结果储存在一个数组里,它的地址被传递作为一个参数。

#include<stdio.h>
#define LEN 80

char *getch(char a[], int n);
int main(void)
{
	char a[LEN];
	if (getch(a, 4))
		puts(a);
	else
		printf("没有读取\n");
	return 0;
}
char* getch(char a[], int n)
{
	int i;
	for (i = 0; i < n; i++)
	{
		a[i] = getchar();
		if (EOF == a[i])
		{
			a[i] = '\0';
			break;
		}
	}
	a[i] = '\0';
	if (!a[0])
		return a;
}

2.修改并编程练习1的函数,在n个字符后停止,或在读到第1个空白、制表符或换行符时停止,哪个先遇到哪个停止。不能只使用scanf()。

#include<stdio.h>
#include<ctype.h>

#define LEN 80

char * getch(char a[], int n);
int main()
{
	char a[LEN];
	if (getch(a, 6))
		puts(a);
	else
		printf("没有读取\n");
	return 0;
}
char* getch(char a[], int n)
{
	int i;
	for (i = 0; i < n; i++)
	{
		a[i] = getchar();
		if (EOF == a[i] || isspace(a[i]))
		{
			a[i] = '\0';
			break;
		}
	}
	a[i] = '\0';
	if ('\0' == a[0])
		return NULL;
	return a;
}

3.设计并测试一个函数,从一行输入中把一个单词读入一个数组中,并丢弃输入行中的其余字符。该函数应该跳过第1个非空白字符前面的所有空白。将一个单词定义为没有空白、制表符或换行符的字符序列。

#include<stdio.h>
#include<ctype.h>
#include<stdbool.h>  

bool getword(char*);
int main(void)
{
	char array[20];
	if (getword(array))
		puts(array);
	else
		puts("没有读取到单词");
	return 0;
}
bool getword(char* array)
{
	char ch;
	int a = 0;
	char *p = array;
	while ((ch = getchar()) != '\n')
	{
		if (a == 0 && isspace(ch))
			continue;
		else
			a = 1;
		if (!isspace(ch))
			*array++ = ch;
		else
			break;
	}
	*array = '\0';
	if (*p == '\0')
		return false;
	return true;
}

4.设计并测试一个函数,它类似编程练习3的描述,只不过它接受第2个参数指明可读取的最大字符数。

#include<stdio.h>
#define LEN 80

char* search(char* str, char ch);  //声明

int main(void)
{
	char ch;
	char target[LEN];
	char * pstr;
	puts("请输入字符串(在一行的开始输入回车结束):");  //输出字符串
	while (gets(target) && target[0] != '\n')  //读取一行字符串,当第一个字符不为换行符时
	{
		puts("请输入字符:");
		ch = getchar();  //读取一个字符
		while (getchar() != '\n')  //当字符不为换行符时
			;  //
		pstr = search(target, ch);
		if (pstr == NULL)
			printf("字符%c不在字符串中\n", ch);
		else
			printf("找到字符%c,它的地址为%p\n", ch, pstr);
		puts("请输入下一个字符串(在一行的开始输入回车结束):");
	}
	return 0;
}
char* search(char* str, char ch)
{
	while (*str != '\0')  //指针变量不为\0即字符结尾进入比较判断
	{
		if (*str++ == ch)  //比较若相等返回str
			return str;
	}
	return NULL;  //字符结尾时返回NULL
}

5.设计并测试一个函数,搜索第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() != ar[0]) 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;
}

6.编写一个名为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;
}

7.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)
	{
		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)
	{
		target[i] = source[i];
		i++;
	}
	if (i < n - 1)
		target[i] = '\0';
}

8.编写一个名为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;

}

9.编写一个函数,把字符串中的内容用其反序字符串代替。在一个完整的程序中测试该函数,使用一个循环给函数提供输入值。

#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;
    }

}

10.编写一个函数接受一个字符串作为参数,并删除字符串中的空格。在一个程序中测试该函数,使用循环读取输入行,直到用户输入一行空行。该程序应该应用该函数只每个输入的字符串,并显示处理后的字符串。

#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];
    }
}

11.编写一个函数,读入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]);
                
 }     

12.编写一个程序,读取输入,直至读到 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;
}

13.编写一个程序,反序显示命令行参数的单词。例如,命令行参数是 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;
}

14.编写一个通过命令行运行的程序计算幂。第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;
}

15.使用字符分类函数实现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;
}

16.编写一个程序读取输入,直至读到文件结尾,然后把字符串打印出来。该程序识别和实现下面的命令行参数:

-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;
}


  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
《C Primer Plus第六版》是一本面向初学者的C语言教材,由Stephen Prata撰写。这本书深入浅出地介绍了C语言的基本概念、语法和应用,给读者提供了扎实的编程基础。 该书共分为27章,每章都有清晰的目标、易于理解的示例和练习题。从第一章的入门介绍开始,到最后一章的高级主题讨论,书中的内容依次递进,系统完整地覆盖了C语言的方方面面。本书有助于读者逐步掌握C语言的基础知识,从简单的输出语句到复杂的函数调用和指针使用。 《C Primer Plus第六版》的特点是其清晰的讲解风格和丰富的实例。作者通过通俗易懂的语言和生动形象的例子,帮助读者理解和掌握C语言的各种概念和语法。此外,书中还提供了许多练习题和编程项目,供读者巩固所学知识和提高编程能力。 作为一本经典的C语言教材,《C Primer Plus第六版》被广泛用于学校和个人学习。它不仅适用于初学者,也对有一定编程基础的读者有所帮助。读者通过学习本书,可以建立起对C语言编程的扎实基础,为深入学习其他编程语言打下坚实的基础。 综上所述,《C Primer Plus第六版》是一本权威、经典的C语言教材,通过清晰的讲解和丰富多样的示例帮助读者深入理解C语言的基本概念和应用。无论是初学者还是有一定编程基础的读者,都可以从中获益,打下良好的编程基础。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值