C Primer Plus 第13章 练习题

1.修改程序清单13.1中的程序,要求提示用户输入文件名,并读取用户输入的信息,不使用命令行参数。

#include 
#include                              // 提供exit() 的原型
#define BUF 256

char *s_gets(char *st, int n);

int main(int argc, char *argv[])
{
    int ch;                                     // 读取文件时,存储每个字符的地方
    FILE *fp;                                   // "文件指针"
    unsigned long count = 0;
    char filename[BUF];

    fprintf(stdout, "Input file name:");
    
    if ( s_gets(filename, BUF) )                // 也可写个循环,这里为了测试才写if
    {
        if ( (fp = fopen(filename, "r")) == NULL )
        {
            printf("Can't open %s\n", filename);
            exit(EXIT_FAILURE);
        }
        while ( (ch = getc(fp)) != EOF )
        {
            putc(ch, stdout);                       // 与putchar(ch);相同
            count++;
        }
        putc('\n', stdout);
        fclose(fp);
        printf("File %s has %lu characters\n", filename, count);
    }
    
    return 0;
}

char *s_gets(char *st, int n)
{
    char *ret_val;

    ret_val = fgets(st, n, stdin);
    if ( ret_val )
    {
        while ( *st != '\n' && *st != '\0' )
            st++;
        if ( *st == '\n' )
            *st = '\0';
        else
            while ( getchar() != '\n' )
            continue;
    }

    return ret_val;
}

/*
输出结果:
Input file name:Hello
Hello World!
File Hello has 12 characters
*/

2.编写一个文件拷贝程序,该程序通过命令行获取原始文件名和拷贝文件名。尽量使用标准I\O和二进制模式。

自行预先创建两个文件,在命令函中输入两个文件名即可拷贝

#include 
#include 
#include 
#define BUF 4096                                            // 创建512字节倍数的buffer

void cype_file(FILE *source, FILE *dest);                   // 使用二进制模式的读/写函数进行拷贝

int main(int argc, char *argv[])
{
    FILE *fs, *fa;                                          // fs(源文件),fa(目标拷贝文件)

    if ( argc != 3 )
    {
        fprintf(stderr, "Usage: %s filename\n", argv[0]);
        exit(EXIT_FAILURE);
    }else if ( strcmp(argv[1], argv[2]) == 0 )              // 限定条件(无法拷贝自身)
    {
        fputs("Can't cype file to itself\n", stderr);
        exit(EXIT_FAILURE);
    }

    if ( (fs = fopen(argv[1], "rb")) == NULL )              // 创建源文件
    {
        fprintf(stderr, "Can't open %s\n", argv[1]);
        exit(EXIT_FAILURE);
    }else if ( (fa = fopen(argv[2], "wb")) == NULL )        // 创建目标文件
    {
        fprintf(stderr, "Can't open %s\n", argv[2]);
        exit(EXIT_FAILURE);
    }else if ( setvbuf(fs, NULL, _IOFBF, BUF) != 0 )        // 创建源文件的完全缓冲区
    {
        fputs("Can't create output buffer\n", stderr);
        exit(EXIT_FAILURE);
    }else if ( setvbuf(fa, NULL, _IOFBF, BUF) != 0 )        // 创建目标文件的完全缓冲区
    {
        fputs("Can't create input buffer\n", stderr);
        exit(EXIT_FAILURE);
    }
    cype_file(fs, fa);                                      // 拷贝完成

    fprintf(stdout, "Copy successfully!\n");               // 没有输出是因为,文件可能是二进制
    fclose(fs);
    fclose(fa);

    return 0;
}

void cype_file(FILE *source, FILE *dest)
{
    static char temp[BUF];                                  // 只分配一次
    size_t bytes = 0L;

    while ( (bytes = fread(temp, sizeof(char), BUF, source)) > 0 )
    {
        fwrite(temp, sizeof(char), bytes, dest);
    }
}

3.编写一个文件拷贝程序,该程序通过用户输入文本文件名,并以该文件名和输出文件名。

#include 
#include 
#include 
#include 
#define BUF 512                                            // 创建512字节倍数的buffer

void cype_file(FILE *fp);                                   // 使用二进制模式的读/写函数进行拷贝

int main(int argc, char *argv[])
{
    FILE *fp;
    char ch;

    if ( argc != 2 )
    {
        fprintf(stderr, "Usage: %s filename\n", argv[0]);
        exit(EXIT_FAILURE);
    }

    if ( (fp = fopen(argv[1], "rb+")) == NULL )              // 创建源文件
    {
        fprintf(stderr, "Can't open %s\n", argv[1]);
        exit(EXIT_FAILURE);
    }else if ( setvbuf(fp, NULL, _IOFBF, BUF) != 0 )        // 创建文件输入/输出的完全缓冲区
    {
        fputs("Unable to create output/output buffer\n", stderr);
        exit(EXIT_FAILURE);
    }
    cype_file(fp);                                          // 拷贝完成

    fputs("Done.\n", stdout);
    fclose(fp);

    return 0;
}

void cype_file(FILE *fp)
{
    static char temp[BUF];                                  // 只分配一次
    size_t bytes = 0L;
    char *st;

    while ( (bytes = fread(temp, sizeof(char), BUF, fp)) > 0 )
    {
        st = temp;
        while ( *st )
        {
            *st = toupper(*st);
            st++;
        }
        rewind(fp);                                         // 返回到文件开始处           
        fwrite(temp, sizeof(char), bytes, fp);
    }
}
/*
输出结果(以下结果使用测试代码得出的结果):
./Copy Hello
--------------------------测试【拷贝前】
HELLO WORLD!
--------------------------测试【拷贝后】
HELLO WORLD!
--------------------------
Done.
*/

4.编写一个程序,按顺序在屏幕上显示命令行中列出的所有文件。使用argc控制语句。

#include 
#include 

int main(int argc, char *argv[])
{
    FILE *fp;
    char ch;
    int i;

    if ( argc < 2 )                                         //限定条件
    {
        fprintf(stderr, "Usage: %s filename\n", argv[0]);
        exit(EXIT_FAILURE);
    }

    for ( i = 1; i < argc ; i++ )
    {
        if ( (fp = fopen(argv[i], "r")) == NULL )           //每次循环都打开一个文件
        {
            fprintf(stderr, "Can't open %s\n", argv[i]);
            exit(EXIT_FAILURE);
        }

        fprintf(stdout, "File name %s:  ",argv[i]);         // 输出到屏幕
        while ( (ch = getc(fp)) != EOF )
        {
            putc(ch, stdout);
        }
        putc('\n',stdout);
        fclose(fp);                                         // 关闭流
    }

    puts("Bye!");

    return 0;
}
/*
输出结果:
./print_file Hello world
File name Hello:  Hello
File name world:  World!
Bye!
*/

5.修改程序清单13.5中的程序,用命令行界面代替交互界面。

/* append.c -- 把文件附加到另一个文件末尾 */
#include 
#include 
#include 
#define BUFSIZE 4096
#define SLEN 81

void append(FILE *source, FILE *dest);
char *s_gets(char *st, int n);

int main(int argc, char const *argv[])
{
    FILE *fa, *fs;                      // fa指向目标文件, fs指向源文件
    int ch;

    if ( argc != 3 )                    // 限定条件
    {
        fprintf(stderr, "Usage: %s filename\n", argv[0]);
        exit(EXIT_FAILURE);
    }else if ( strcmp(argv[1], argv[2]) == 0 )
    {
        fputs("Can't append file to itself\n", stderr);
        exit(EXIT_FAILURE);
    }

    if ( (fa = fopen(argv[2], "a+")) == NULL )          // 打开目标文件
    {
        fprintf(stderr, "Can't open %s\n", argv[2]);
        exit(EXIT_FAILURE);
    }
    if ( setvbuf(fa, NULL, _IOFBF, BUFSIZE) != 0 )      // 创建目标文件缓冲区4096字节大小
    {
        fputs("Can't create output buffer\n", stderr);
        exit(EXIT_FAILURE);
    }
    if ( (fs = fopen(argv[1], "r")) == NULL )           // 打开源文件
    {
        fprintf(stderr, "Can't open %s.\n", argv[1]);
        exit(EXIT_FAILURE);
    }
    if ( setvbuf(fs, NULL, _IOFBF, BUFSIZE) != 0 )      // 创建源文件缓冲区4096大小
    {
        fputs("Can't create input buffer\n", stderr);
    }

    append(fs, fa);                                     // 拷贝源文件内容到目标文件
    if ( ferror(fs) != 0 )
    {
        fprintf(stderr, "Error in reading file %s.\n", argv[1]);
    }
    if ( ferror(fa) != 0 )
    {
        fprintf(stderr, "Error in writing file %s.\n", argv[2]);
    }

    printf("File %s append.\n", argv[1]);
    rewind(fa);                                         // 将指针指向文件起始处
    printf("%s contents:\n", argv[2]);

    while ( (ch = getc(fa)) != EOF )                    // 输出
    {
        putc(ch, stdout);
    }
    puts("\nDone displaying");
    fclose(fa);                                         // 关闭流
    fclose(fs);

    
    return 0;
}

void append(FILE *source, FILE *dest)
{
    size_t bytes;
    static char *temp[BUFSIZE];                         // 只创建一次

    while ( (bytes = fread(temp, sizeof(char), BUFSIZE, source)) > 0 )
    {
        fwrite(temp, sizeof(char), bytes, dest);
    }
}

/*
输出结果:
./append world Hello
File world append.
Hello contents:
HelloWorld!
Done displaying
*/

6.使用命令行参数的程序依赖于用户的内存如何正确的使用它们。重写程序清单13.2中的程序,不使用命令行参数,而是提示用户输入所需的信息。

// reducto.c - 把文件压缩成原来的1/3!
#include 
#include                      // 提供exit()的原型
#include                      // 提供 strcpy()、strcat()的原型
#define LEN 40

char *s_gets(char *st, int n);

int main(int argc, char const *argv[])
{
    FILE *in, *out;                     // 声明两个指向 FILE 的指针
    char source[LEN];                       // source 源文件文件名
    char dest[LEN];                       // dest 目标文件文件名
    int ch;
    int count = 0;


    printf("Enter the compressed file name:");
    s_gets(source, LEN);
    // 设置输入
    if ( (in = fopen(source, "r")) == NULL )
    {
        fprintf(stderr, "can't open %s.\n", source);
        exit(EXIT_FAILURE);
    }

    // 设置输出
    strncpy(dest, source, LEN - 5);                    // 拷贝文件名;
    dest[LEN - 5] = '\0';                               // strncpy源字符可能大于最大限定个数时,将最后一个添为‘\0’
    strcat(dest, ".red");                               // 在文件名后添加.red
    if ( (out = fopen(dest, "w+")) == NULL )
    {
        fprintf(stderr, "Can't create output file.\n");
        exit(3);
    }

    //拷贝数据
    while ( (ch = getc(in)) != EOF )
    {
        if ( count++ % 3 == 0 )
        {
            putc(ch, out);                              // 写3个字符中的第1个字符
        }
    }

    // 收尾工作
    if ( fclose(in) != 0 || fclose(out) != 0 )
    {
        fprintf(stderr, "Error in closing files\n");
    }
    puts("Done.");
    
    return 0;
}

char *s_gets(char *st, int n)
{
    char *ret_val;

    ret_val = fgets(st, n , stdin);
    if ( ret_val )
    {
        while ( *st != '\n' && *st != '\0' )
        {
            st++;
        }
        if ( *st == '\n' )
        {
            *st = '\0';
        }else
        {
            while ( getchar() != '\n' )
            {
                continue;
            }
        }
    }

    return ret_val;
}

7.编写一个程序打开两个文件。可以使用命令行参数或提示用户输入文件名。

a

#include 
#include 
#define LEN 81

char *s_gets(char *st, int n);

int main(int argc, char const *argv[])
{
    FILE *fp_one, *fp_two;                                      // fp_one 指向第一个文件, fp_two指向第二个文件
    char file_one[LEN];                                         // file_one第一个文件文件名
    char file_two[LEN];                                         // file_two第二个文件文件名
    char ch;

    int mark_one = 1, mark_two = 1;                             // 标记,当读到文件末尾则置为0

    printf("Enter the first file name:");                       // 输入第一个文件名
    s_gets(file_one, LEN);
    if ( (fp_one = fopen(file_one, "r")) == NULL )              // 以读模式打开文件
    {
        fprintf(stderr, "Can't open %s.\n", file_one);
        exit(EXIT_FAILURE);
    }

    printf("Enter the second file name:");                      // 输入第二个文件名
    s_gets(file_two, LEN);
    if ( (fp_two = fopen(file_two, "r")) == NULL )              // 以读模式打开文件
    {
        fprintf(stderr, "Can't open %s.\n", file_two);
        exit(EXIT_FAILURE);
    }

    do
    {
        if ( mark_one )                                         // 标记入口
        {
            while ( (ch = getc(fp_one)) != EOF )                // 从当前指针指向的数据开始读
            {
                putc(ch, stdout);
                if ( ch == '\n' )
                {
                    break;                                      // 只要读取到换行符则退出循环
                }
            }
            if ( ch == EOF )                                    // 当读取到EOF时换行,且关闭入口
            {
                putchar('\n');
                mark_one = 0;
            }
        }
        
        if ( mark_two )                                         // 标记入口
        {
            while ( (ch = getc(fp_two)) != EOF )
            {
                putc(ch, stdout);
                if ( ch == '\n' )                               // 只要读取到换行符则退出循环
                {
                    break;
                }
            }
            if ( ch == EOF )                                    // 当读取到EOF时换行,且关闭入口
            {
                putchar('\n');
                mark_two = 0;
            }
        }    
        
    } while (mark_one || mark_two);
    
    // 收尾工作
    fclose(fp_one);
    fclose(fp_two);
    printf("Done!\n");
    
    return 0;
}

char *s_gets(char *st, int n)
{
    char *ret_val;
    
    ret_val = fgets(st, n, stdin);
    if ( ret_val )
    {
        while ( *st != '\n' && *st != '\0' )
        {
            st++;
        }
        if ( *st == '\n' )
        {
            *st = '\0';
        }else
        {
            while (getchar() != '\n' )
            {
                continue;
            }
        }    
    }

    return ret_val;
}

b

#include 
#include 
#define LEN 81

char *s_gets(char *st, int n);

int main(int argc, char const *argv[])
{
    FILE *fp_one, *fp_two;                                      // fp_one 指向第一个文件, fp_two指向第二个文件
    char file_one[LEN];                                         // file_one第一个文件文件名
    char file_two[LEN];                                         // file_two第二个文件文件名
    char ch;

    int mark_one = 1, mark_two = 1;                             // 标记,当读到文件末尾则置为0

    printf("Enter the first file name:");                       // 输入第一个文件名
    s_gets(file_one, LEN);
    if ( (fp_one = fopen(file_one, "r")) == NULL )              // 以读模式打开文件
    {
        fprintf(stderr, "Can't open %s.\n", file_one);
        exit(EXIT_FAILURE);
    }

    printf("Enter the second file name:");                      // 输入第二个文件名
    s_gets(file_two, LEN);
    if ( (fp_two = fopen(file_two, "r")) == NULL )              // 以读模式打开文件
    {
        fprintf(stderr, "Can't open %s.\n", file_two);
        exit(EXIT_FAILURE);
    }

    do
    {
        if ( mark_one )                                         // 标记入口
        {
            while ( (ch = getc(fp_one)) != EOF )                // 从当前指针指向的数据开始读
            {

                if ( ch == '\n' && mark_two != 0 )              // 读取到换行符,如果第二个文件还没EOF则不输出\n
                {
                    break;
                }
                putc(ch, stdout);
            }
            if ( ch == EOF )                                    // 当读取到EOF时换行,且关闭入口
            {
                if ( !mark_two )                                // 当文件2还在的话,就不输出结束的\n
                {
                    putchar('\n');
                }
                mark_one = 0;
            }
        }
        
        if ( mark_two )                                         // 标记入口
        {
            while ( (ch = getc(fp_two)) != EOF )
            {
                putc(ch, stdout);
                if ( ch == '\n' )                               // 只要读取到换行符则退出循环
                {
                    break;
                }
            }
            if ( ch == EOF )                                    // 当读取到EOF时换行,且关闭入口
            {
                putchar('\n');
                mark_two = 0;
            }
        }    
        
    } while (mark_one || mark_two);
    
    // 收尾工作
    fclose(fp_one);
    fclose(fp_two);
    printf("Done!\n");
    
    return 0;
}

char *s_gets(char *st, int n)
{
    char *ret_val;
    
    ret_val = fgets(st, n, stdin);
    if ( ret_val )
    {
        while ( *st != '\n' && *st != '\0' )
        {
            st++;
        }
        if ( *st == '\n' )
        {
            *st = '\0';
        }else
        {
            while (getchar() != '\n' )
            {
                continue;
            }
        }    
    }

    return ret_val;
}

8.编写一个程序,以一个字符和任意文件名作为命令行参数。如果字符后面没有参数,该程序读取标准输入;否则,程序依次打开每个文件并报告每个文件中该字符出现的次数。文件名和字符本身也要一同报告。程序应包含错误检查,以确定参数数量是否正确和是否能打开文件。如果无法打开文件,程序应报告这一情况,然后继续处理下一个文件。

#include 
#include 
#include 
#define SLEN 20

char *s_gets(char *st, int n);                  // 标准输入获取文件名
void find_char(char *file_name, char c);        // 打开文件及打印

int main(int argc, char *argv[])
{
    char ch;
    char file_name[20];                         // 当参数只有一个字符时:使用标准输入获取filename
    int i;

    if ( argc < 2 || strlen(argv[1]) > 1 )      // 当参数小于2或者第一个参数不是字符时,结束
    {
        fprintf(stderr, "Usage: %s A character filename\n", argv[0]);
        exit(EXIT_FAILURE);
    }
    ch = argv[1][0];                            // 将第一个参数使用char类型保存
    if ( argc == 2 )                            // 如果只有一个参数时【标准输入】
    {
        printf("To stop, press the Enter key at a line's start.\n");
        while ( s_gets(file_name, SLEN) && file_name[0] != '\0' )
        {
            find_char(file_name, ch);
            printf("To stop, press the Enter key at a line's start.\n");
        }
    }else                                       // 否则直接使用命令行参数的文件名
    {
        for ( i = 2; i < argc; i++ )
        {
            find_char(argv[i], ch);
        }
    }
    puts("Done!");

    return 0;
}

char *s_gets(char *st, int n)
{
    char *find;
    char *ret_val;

    ret_val = fgets(st, n ,stdin);
    
    if ( ret_val )
    {
        find = strchr(st, '\n');
        if ( find )
        {
            *find = '\0';
        }else
        {
            while ( getchar() != '\n' )
            {
                continue;
            }
        }
    }

    return ret_val;
}

void find_char(char *file_name, char c)
{
    FILE *fp;
    char temp;
    int index = 0;
    
    if ( (fp = fopen(file_name, "r")) == NULL )
    {
        fprintf(stderr, "Can't open %s\n", file_name);
        return;
    }
    
    while ( (temp = getc(fp)) != EOF )
    {
        if ( temp == c )
        {
            index++;
        }
    }
    printf("filename: %s ; character: %c ; index: %d\n", file_name, c, index);
    fclose(fp);
}

/*
输出结果:
./find a Hello world
filename: Hello ; character: a ; index: 7
filename: world ; character: a ; index: 1
Done!

./find a
To stop, press the Enter key at a line's start.
Hello
filename: Hello ; character: a ; index: 7
To stop, press the Enter key at a line's start.

Done!
*/

9.修改程序清单13.3中的程序,从1开始,根据加入列表的顺序为每个单词编号。当程序下次运行时,确保新的单词编号接着上次的编号开始。

// 修改程序清单13.3中的程序,从1开始,根据加入列表的顺序为每个单词编号.
// 当程序下次运行时,确保新的单词编号接着上次的编号开始.
#include 
#include 
 
#define MAX 41
 
int main(void)
{
	FILE * fp ;
	char words[MAX] ;
    int index = 0;
 
	if ((fp = fopen("wordy" , "a+")) == NULL)				// 创建一个存储单词的文件
	{
		fprintf(stderr , "Can't open \"wordy\" file.\n");
		exit(EXIT_FAILURE);
	}
 
	//读出原数据
    rewind(fp);
	while ( fscanf(fp, "%d %s", &index, words) == 2 );		//从头开始读,最后index的值为最后编号的值
 
	puts("Enter words to add to the file; press the #");
	puts("key at the beginning of a line to terminate.");
	while ((fscanf(stdin , "%40s" , words)) == 1 && (words[0] != '#'))
	{
		fprintf(fp , "%d %s\n" , ++index , words); //将编号自增后也写入文件内	
	}

	puts("File contents:");
	rewind(fp);
	while ( fscanf(fp, "%d %s", &index, words) == 2 )		//固定格式输出
	{
		fprintf(stdout, "%d %s\n", index, words);
	}
	puts("Done!");
	if (fclose(fp) != 0)
	{
		fprintf(stderr , "Error closing file.\n");
	}

	return 0 ;
}

/*
输出结果:
Enter words to add to the file; press the #
key at the beginning of a line to terminate.
Hello
world
#
File contents:
1 Hello
2 world
Done!
*/

10.编写一个程序打开一个文本文件,通过交互方式获取文件名。通过一个循环,提示用户输入一个文件位置。然后该程序打印从该位置到下一个换行符之前的内容。用户输入负数或非数值字符可以结束输入循环。

#include 
#include 
#define SLEN 40

char *s_gets(char *st, int n);

int main(void)
{
	FILE *fp;
	char file_name[SLEN];
	long offset;								// 偏移量
	int ch;

	printf("Enter file name:");
	s_gets(file_name, SLEN);

	if ( (fp = fopen(file_name, "r")) == NULL )		// 文件以读模式打开
	{
		fprintf(stderr, "Can't open %s file.", file_name);
		exit(EXIT_FAILURE);
	}
	printf("Enter an integer:");
	while ( scanf("%ld", &offset) == 1 && offset > 0 )
	{
		fseek(fp, offset, SEEK_SET);				// SEEK_SET从文件起始处
		
		while ( (ch = getc(fp)) != '\n' )
		{
			putc(ch, stdout);
		}
		putchar('\n');

		printf("Enter an integer(q to quit):");
	}

	if (fclose(fp) != 0)
	{
		fprintf(stderr , "Error closing file.\n");
	}
	puts("Done!");
	
	return 0;
}

char *s_gets(char *st, int n)
{
	char *ret_val;

	ret_val = fgets(st, n, stdin);
	if ( ret_val )
	{
		while ( *st != '\n' && *st != '\0' )
		{
			st++;
		}
		if ( *st == '\n' )
		{
			*st = '\0';
		}else
		{
			while ( getchar() != '\n' )
			{
				continue;
			}
		}
	}

	return ret_val;
}

11.编写一个程序,接受两个命令行参数。第一个参数是一个字符串,第2个参数是一个文件名。然后该程序查找该文件,打印文件中包含该字符串的所有行。因为该任务是面向行而不面向字符的,所以要使用fgets()而不是getc()。使用标准C库函数strstr()在每行中查找指定字符串。假设文件中的所有行都不超过255个字符。

#include 
#include 
#include 						// 提供strstr()原型
#define MAX 255

int main(int argc, char const *argv[])
{
	FILE *fp;
	char row[MAX];						// 将一行的数据存储到临时的数组中

	if ( argc < 3 )						// 参数少于2个时结束
	{
		fprintf(stderr, "Usaga: %s Sring filename.\n", argv[0]);
		exit(EXIT_FAILURE);
	}
	if ( (fp = fopen(argv[2], "r")) == NULL )	// 以读模式打开文件
	{
		fprintf(stderr, "Can't open %s file.\n", argv[2]);
		exit(EXIT_FAILURE);
	}

	while ( 1 )
	{
		fgets(row, MAX, fp);				// 读到最后一行时,它的文件指针并没有指向文件尾,而是指向’\r'处
		if ( strstr(row, argv[1]) != NULL )
		{
			fputs(row, stdout);
		}
		if ( feof(fp) )						// 当文件读到末尾,就不能再执行以下代码。
		{
			break;
		}
	}
	putchar('\n');

	if ( fclose(fp) != 0 )
	{
		fprintf(stderr, "Error closing file.\n");
		exit(EXIT_FAILURE);
	}
	
	puts("Done!");
	
	return 0;
}

12.创建一个文本文件,内含20行,每行30个整数。这些整数都在0~9之间,用空格分开。该文件使用数字表示一张图片,0-9表示逐渐添加的灰度。

0 0 9 0 0 0 0 0 0 0 0 0 5 8 9 9 8 5 2 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 9 0 0 0 0 0 0 0 5 8 9 9 8 5 5 2 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 5 8 1 9 8 5 4 5 2 0 0 0 0 0 0 0 0 0
0 0 0 0 9 0 0 0 0 0 0 0 5 8 9 9 8 5 0 4 5 2 0 0 0 0 0 0 0 0
0 0 9 0 0 0 0 0 0 0 0 0 5 8 9 9 8 5 0 0 4 5 2 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 5 8 9 1 8 5 0 0 0 4 5 2 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 5 8 9 9 8 5 0 0 0 0 4 5 2 0 0 0 0 0
5 5 5 5 5 5 5 5 5 5 5 5 5 8 9 9 8 5 5 5 5 5 5 5 5 5 5 5 5 5
8 8 8 8 8 8 8 8 8 8 8 8 5 8 9 9 8 5 8 8 8 8 8 8 8 8 8 8 8 8
9 9 9 9 0 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 3 9 9 9 9 9 9 9
8 8 8 8 8 8 8 8 8 8 8 8 5 8 9 9 8 9 9 8 5 8 8 8 8 8 8 8 8 8
5 5 5 5 5 5 5 5 5 5 5 5 5 8 9 9 8 5 5 5 5 5 5 5 5 5 5 5 5 5
0 0 0 0 0 0 0 0 0 0 0 0 5 8 9 9 8 5 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 5 8 9 9 8 5 0 0 0 0 6 6 0 0 0 0 0 0
0 0 0 0 2 2 0 0 0 0 0 0 5 8 9 9 8 5 0 0 5 6 0 0 6 5 0 0 0 0
0 0 0 0 3 3 0 0 0 0 0 0 5 8 9 9 8 5 0 5 6 1 1 1 1 6 5 0 0 0
0 0 0 0 4 4 0 0 0 0 0 0 5 8 9 9 8 5 0 0 5 6 0 0 6 5 0 0 0 0
0 0 0 0 5 5 0 0 0 0 0 0 5 8 9 9 8 5 0 0 0 0 6 6 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 5 8 9 9 8 5 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 5 8 9 9 8 5 0 0 0 0 0 0 0 0 0 0 0 0

#include 
#include 
#define ROW 20
#define COLUMN 31
#define SLEN 10
// 以下参数为:文件指针,二维数组
void file_append(FILE *f, char (*st)[COLUMN]);        //功能:将二维数组中的内容附加给文件末尾
void change(FILE *f, char (*st)[COLUMN]);               //功能:将文件中的“数字字符”转换成“字符符号”
//使用命令行读取文件名【参数:文件名】
int main(int argc, char const *argv[])
{
    FILE *fp;
    char picture[ROW][COLUMN] = {0};            // 20X31的二维数组

    if ( argc < 2 )
    {
        fprintf(stderr, "Usaga: %s", argv[0]);
        exit(EXIT_FAILURE);
    }
    if ( (fp = fopen(argv[1], "rb+")) == NULL )
    {
        fprintf(stderr, "Can't open %s file.", argv[1]);
        exit(EXIT_FAILURE);
    }
    change(fp, picture);                        // 将文本文件中的数字以“字符符号”打印
    fprintf(fp, "\nOutput result:\n");          // 输出结果
    file_append(fp, picture);                   // 附加

    
    fclose(fp);
    puts("Done!");
    
    return 0;
}

void change(FILE *f, char (*st)[COLUMN])
{
    char char_arr[SLEN] = { ' ', '.', '\'', ':', '~', '*', '=', '$','%','#' };        //用于存储符号字符
    int i, j;
    int ch;

    for ( i = 0; i < ROW; i++ )
    {
        for ( j = 0; j < COLUMN - 1; j++ )
        {
            if ( fscanf(f, "%d", &ch) == 1 )
            {
                st[i][j] = char_arr[ch];               //数字对应着字符数组下标的符号
            }
        }
        puts(st[i]);

        if ( ch == EOF )                                    // 当ch提前到末尾时结束
        {
            break;
        }
    }
}

void file_append(FILE *f, char (*st)[COLUMN])
{
    int i;

    for ( i = 0; i < ROW; i++ )
    {
        fwrite(st[i], sizeof(char), COLUMN - 1, f);         // 将二维数组中的数据写到文件中
        if ( i != ROW - 1 )                                 // 当到文件末尾时不换行
        {
            putc('\n', f);
        }
    }
}

13.用可变长数组(VAL)代替标准数组,完成编程练习12。

#include 
#include 
#define SLEN 10

// 以下参数为:行个数,列个数,二维数组, 文件指针
void file_append(int rows, int cols, char ar_VAL[rows][cols],FILE *f);//功能:将二维数组中的内容附加给文件末尾
void change(int rows, int cols, char ar_VAL[rows][cols],FILE *f);//功能:将文件中的“数字字符”转换成“字符符号”

int main(int argc, char const *argv[])
{
    FILE *fp;
    int row = 20;
    int column = 31;
    char picture[row][column];            // 20X31的二维数组的可变长数组

    if ( argc < 2 )
    {
        fprintf(stderr, "Usaga: %s", argv[0]);
        exit(EXIT_FAILURE);
    }
    if ( (fp = fopen(argv[1], "rb+")) == NULL )
    {
        fprintf(stderr, "Can't open %s file.", argv[1]);
        exit(EXIT_FAILURE);
    }
    change(row, column, picture, fp);                        // 将文本文件中的数字以“字符符号”打印
    fprintf(fp, "\nOutput result:\n");                       // 输出结果
    file_append(row, column, picture, fp);                   // 附加

    
    fclose(fp);
    puts("Done!");
    
    return 0;
}

void change(int rows, int cols, char ar_VAL[rows][cols],FILE *f)
{
    char char_arr[SLEN] = { ' ', '.', '\'', ':', '~', '*', '=', '$','%','#' };        //用于存储符号字符
    int i, j;
    int ch;

    for ( i = 0; i < rows; i++ )
    {
        for ( j = 0; j < cols - 1; j++ )
        {
            if ( fscanf(f, "%d", &ch) == 1 )
            {
                ar_VAL[i][j] = char_arr[ch];               //数字对应着字符数组下标的符号
            }
        }
        puts(ar_VAL[i]);

        if ( ch == EOF )                                    // 当ch提前到末尾时结束
        {
            break;
        }
    }
}

void file_append(int rows, int cols, char ar_VAL[rows][cols],FILE *f)
{
    int i;

    for ( i = 0; i < rows; i++ )
    {
        fwrite(ar_VAL[i], sizeof(char), cols - 1, f);         // 将二维数组中的数据写到文件中
        if ( i != rows - 1 )                                 // 当到文件末尾时不换行
        {
            putc('\n', f);
        }
    }
}

你可能感兴趣的:(C,Primer,Plus,c语言)