本章练习中,所有通过交互方式获得文件名的过程都采用scanf()函数获取字符串的形式,其实仅仅为了代码简洁,但并不严谨。比如文件名中有空格,将会达不到预期效果。解决方法是:定义一个11章中的s_gets()函数,并用它来获取文件名。函数定义如下:
char* s_gets(char* st, int n)
{
char* ret_val;
int i = 0;
ret_val = fgets(st, n, stdin);
if (ret_val)
{
while (st[i] != '\n' && st[i] != '\0')
i++;
if (st[i] == '\n')
st[i] = '\0';
else
while (getchar() != '\n')
continue;
}
return ret_val;
}
第1题
#include <stdio.h>
#include <stdlib.h>
#define LEN 41
int main(void)
{
int ch;
char file[LEN];
FILE* fp;
unsigned long count = 0;
printf("Enter the filename:\n");
scanf("%40s", file);
if ((fp = fopen(file, "r")) == NULL)
{
fprintf(stderr, "Can't open %s\n", file);
exit(EXIT_FAILURE);
}
while ((ch = getc(fp)) != EOF)
{
putc(ch, stdout);
count++;
}
fclose(fp);
printf("File %s has %lu characters\n", file, count);
return 0;
}
第2题
#include <stdio.h>
#include <stdlib.h>
int main(int argc, char* argv[])
{
int ch;
FILE* source;
FILE* target;
if (argc != 3)
{
printf("Usage: %s sourcefile targetfile\n", argv[0]);
exit(EXIT_FAILURE);
}
if ((source = fopen(argv[1], "rb")) == NULL)
{
printf("Could not open %s for input\n", argv[1]);
exit(EXIT_FAILURE);
}
if ((target = fopen(argv[2], "wb")) == NULL)
{
printf("Could not open %s for output\n", argv[2]);
exit(EXIT_FAILURE);
}
while ((ch = getc(source)) != EOF)
putc(ch, target);
if (fclose(source) != 0)
printf("Could not close file %s\n", argv[1]);
if (fclose(target) != 0)
printf("Could not close file %s\n", argv[2]);
return 0;
}
第3题
#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>
#define LEN 41
#define SIZE 4096
int main(void)
{
char file[LEN];
char temp[SIZE];
int ch;
int i = 0;
int ct;
FILE* fp;
printf("Enter the filename:\n");
scanf("%40s", file);
if ((fp = fopen(file, "r")) == NULL)
{
fprintf(stderr, "Could not open %s for input.\n", file);
exit(EXIT_FAILURE);
}
while ((ch = getc(fp)) != EOF)
temp[i++] = toupper(ch);
ct = i;
fclose(fp);
if ((fp = fopen(file, "w")) == NULL)
{
fprintf(stderr, "Could not open %s for output.\n", file);
exit(EXIT_FAILURE);
}
for (i = 0; i < ct; i++)
putc(temp[i], fp);
fclose(fp);
printf("Done.\n");
return 0;
第4题
#include <stdio.h>
#include <stdlib.h>
int main(int argc, char* argv[])
{
int i;
int ch;
FILE* fp;
if (argc < 2)
{
fprintf(stderr, "Usage: %s file1 file2 ...\n", argv[0]);
exit(EXIT_FAILURE);
}
for (i = 1; i < argc; i++)
{
if ((fp = fopen(argv[i], "r")) == NULL)
{
fprintf(stderr, "Could not open %s\n", argv[i]);
continue;
}
while ((ch = getc(fp)) != EOF)
putchar(ch);
fclose(fp);
}
return 0;
}
第5题
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define BUFSIZE 4096
void append(FILE* source, FILE* dest);
int main(int argc, char* argv[])
{
FILE* fa;
FILE* fs;
int i;
int files = 0;
int ch;
if (argc < 3)
{
fprintf(stderr, "Usage: %s appendfile sourcefile[s]\n", argv[0]);
exit(EXIT_FAILURE);
}
if ((fa = fopen(argv[1], "a+")) == NULL)
{
fprintf(stderr, "Can't open %s\n", argv[1]);
exit(EXIT_FAILURE);
}
if (setvbuf(fa, NULL, _IOFBF, BUFSIZE) != 0)
{
fputs("Can't create output buffer\n", stderr);
exit(EXIT_FAILURE);
}
for (i = 2; i < argc; i++)
{
if (strcmp(argv[i], argv[1]) == 0)
fputs("Can't append file to itself\n", stderr);
else if ((fs = fopen(argv[i], "r")) == NULL)
fprintf(stderr, "Can't open %s\n", argv[i]);
else
{
if (setvbuf(fs, NULL, _IOFBF, BUFSIZE) != 0)
{
fputs("Can't create input buffer\n", stderr);
continue;
}
append(fs, fa);
if (ferror(fs) != 0)
fprintf(stderr, "Error in reading file %s.\n", argv[i]);
if (ferror(fa) != 0)
fprintf(stderr, "Error in writing file %s.\n", argv[1]);
fclose(fs);
files++;
printf("File %s appended.\n", argv[i]);
}
}
printf("Done appending. %d files appended.\n", files);
rewind(fa);
printf("%s contents:\n", argv[1]);
while ((ch = getc(fa)) != EOF)
putchar(ch);
puts("Done displaying.");
fclose(fa);
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);
}
第6题
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define LEN 41
int main(void)
{
FILE* in;
FILE* out;
char in_name[LEN];
char out_name[LEN];
int ch;
int count = 0;
printf("Enter the filename you want to compress: ");
scanf("%40s", in_name);
if ((in = fopen(in_name, "r")) == NULL)
{
fprintf(stderr, "I couldn't open the file \"%s\"\n", in_name);
exit(EXIT_FAILURE);
}
strncpy(out_name, in_name, LEN - 5);
out_name[LEN - 5] = '\0';
strcat(out_name, ".red");
if ((out = fopen(out_name, "w")) == NULL)
{
fprintf(stderr, "Can't create output file.\n");
exit(3);
}
while ((ch = getc(in)) != EOF)
if (count++ % 3 == 0)
putc(ch, out);
if (fclose(in) != 0 || fclose(out) != 0)
fprintf(stderr, "Error in closing files\n");
return 0;
}
第7题
// 7a 方式一:使用命令行参数
#include <stdio.h>
#include <stdlib.h>
int main(int argc, char* argv[])
{
FILE* fp1;
FILE* fp2;
char ch1;
char ch2;
if (argc != 3)
{
fprintf(stderr, "Usage: %s filename1 filename2\n", argv[0]);
exit(EXIT_FAILURE);
}
if ((fp1 = fopen(argv[1], "r")) == NULL)
{
fprintf(stderr, "Can't open %s\n", argv[1]);
exit(EXIT_FAILURE);
}
if ((fp2 = fopen(argv[2], "r")) == NULL)
{
fprintf(stderr, "Can't open %s\n", argv[2]);
exit(EXIT_FAILURE);
}
ch1 = getc(fp1);
ch2 = getc(fp2);
while (ch1 != EOF || ch2 != EOF)
{
while (ch1 != EOF && ch1 != '\n')
{
putchar(ch1);
ch1 = getc(fp1);
}
if (ch1 != EOF)
{
putchar('\n');
ch1 = getc(fp1);
}
while (ch2 != EOF && ch2 != '\n')
{
putchar(ch2);
ch2 = getc(fp2);
}
if (ch2 != EOF)
{
putchar('\n');
ch2 = getc(fp2);
}
}
if (fclose(fp1) != 0 || fclose(fp2) != 0)
fprintf(stderr, "Error closing file\n");
return 0;
}
// 7a 方式二:提示用户输入文件名
#include <stdio.h>
#include <stdlib.h>
#define LEN 41
#define BUF 256 // 假设所有行都不超过256个字符
int main(void)
{
FILE* fp1;
FILE* fp2;
char name1[LEN];
char name2[LEN];
char line[BUF];
printf("Enter the first filename: ");
scanf("%40s", name1);
printf("Enter the second filename: ");
scanf("%40s", name2);
if ((fp1 = fopen(name1, "r")) == NULL)
{
fprintf(stderr, "Can't open %s\n", name1);
exit(EXIT_FAILURE);
}
if ((fp2 = fopen(name2, "r")) == NULL)
{
fprintf(stderr, "Can't open %s\n", name2);
exit(EXIT_FAILURE);
}
while (fgets(line, BUF, fp1) != NULL)
{
fputs(line, stdout);
if (fgets(line, BUF, fp2) != NULL)
fputs(line, stdout);
}
while (fgets(line, BUF, fp2) != NULL) // 若第2个文件行数较多
fputs(line, stdout);
if (fclose(fp1) != 0 || fclose(fp2) != 0)
fprintf(stderr, "Error closing file\n");
return 0;
}
// 7b 方式一:使用命令行参数(方式二不单独列出)
#include <stdio.h>
#include <stdlib.h>
int main(int argc, char* argv[])
{
FILE* fp1;
FILE* fp2;
char ch1;
char ch2;
if (argc != 3)
{
fprintf(stderr, "Usage: %s filename1 filename2\n", argv[0]);
exit(EXIT_FAILURE);
}
if ((fp1 = fopen(argv[1], "r")) == NULL)
{
fprintf(stderr, "Can't open %s\n", argv[1]);
exit(EXIT_FAILURE);
}
if ((fp2 = fopen(argv[2], "r")) == NULL)
{
fprintf(stderr, "Can't open %s\n", argv[2]);
exit(EXIT_FAILURE);
}
ch1 = getc(fp1);
ch2 = getc(fp2);
while (ch1 != EOF || ch2 != EOF)
{
while (ch1 != EOF && ch1 != '\n')
{
putchar(ch1);
ch1 = getc(fp1);
}
if (ch1 != EOF)
{
if (ch2 == EOF)
putchar('\n');
else
putchar(' ');
ch1 = getc(fp1);
}
while (ch2 != EOF && ch2 != '\n')
{
putchar(ch2);
ch2 = getc(fp2);
}
if (ch2 != EOF)
{
putchar('\n');
ch2 = getc(fp2);
}
}
if (fclose(fp1) != 0 || fclose(fp2) != 0)
fprintf(stderr, "Error closing file\n");
return 0;
}
第8题
#include <stdio.h>
#include <stdlib.h>
int times_ch(char ch, FILE* fp);
int main(int argc, char* argv[])
{
FILE* fp;
char ch;
int count;
int i;
if (argc < 2)
{
fprintf(stderr, "Usage: %s character (filename)\n", argv[0]);
exit(EXIT_FAILURE);
}
ch = argv[1][0];
if (argc == 2)
{
puts("Enter text to analyze");
puts("(press \"CTRL+Z\" at the beginning of a line to terminate):");
count = times_ch(ch, stdin);
printf("%c appears %d time(s) in the text.\n", ch, count);
}
else
{
for (i = 2; i < argc; i++)
{
if ((fp = fopen(argv[i], "r")) == NULL)
{
fprintf(stderr, "Can't open %s\n", argv[i]);
continue;
}
count = times_ch(ch, fp);
printf("%c appears %d time(s) in %s\n", ch, count, argv[i]);
fclose(fp);
}
}
return 0;
}
int times_ch(char ch, FILE* fp)
{
int c;
int ct = 0;
while ((c = getc(fp)) != EOF)
if (c == ch)
ct++;
return ct;
}
第9题
#include <stdio.h>
#include <stdlib.h>
#define MAX 47
int main(void)
{
FILE* fp;
char words[MAX];
int wordct = 0;
if ((fp = fopen("wordy", "a+")) == NULL)
{
fprintf(stderr, "Can't open \"wordy\" file.\n");
exit(EXIT_FAILURE);
}
rewind(fp);
while (fgets(words, MAX, fp) != NULL)
wordct++;
rewind(fp);
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, "%3d: %s\n", ++wordct, words);
puts("File contents:");
rewind(fp);
while (fgets(words, MAX, fp) != NULL)
fputs(words, stdout);
if (fclose(fp) != 0)
fprintf(stderr, "Error closing file\n");
return 0;
}
第10题
#include <stdio.h>
#include <stdlib.h>
#define LEN 41
int main(void)
{
FILE* fp;
char fname[LEN];
int ch;
long pos;
long range;
printf("Enter the filename: ");
scanf("%40s", fname);
if ((fp = fopen(fname, "rb")) == NULL) // 必须以二进制模式打开文件
{
fprintf(stderr, "Can't open %s\n", fname);
exit(EXIT_FAILURE);
}
printf("Enter the position you want to start reading from?\n");
while (scanf("%d", &pos) == 1 && pos >= 0)
{
// 检查是否超出文件范围
fseek(fp, 0L, SEEK_END);
range = ftell(fp);
if (pos >= range)
{
printf("Out of range, please enter again:\n");
continue;
}
// 定位、输出
fseek(fp, pos, SEEK_SET);
while ((ch = getc(fp)) != '\n')
putchar(ch);
putchar('\n');
printf("Next position:\n");
}
if (fclose(fp) != 0)
fprintf(stderr, "Error closing file\n");
printf("Bye.\n");
return 0;
}
第11题
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define SIZE 256
int main(int argc, char* argv[])
{
FILE* fp;
char line[SIZE];
if (argc != 3)
{
fprintf(stderr, "Usage: %s string filename\n", argv[0]);
exit(EXIT_FAILURE);
}
if ((fp = fopen(argv[2], "r")) == NULL)
{
fprintf(stderr, "Can't open %s\n", argv[2]);
exit(EXIT_FAILURE);
}
while (fgets(line, SIZE, fp) != NULL)
{
if (strstr(line, argv[1]) != NULL)
fputs(line, stdout);
}
if (fclose(fp) != 0)
fprintf(stderr, "Error closing file\n");
return 0;
}
第12题
#include <stdio.h>
#include <stdlib.h>
#define ROWS 20
#define COLS 30
#define LEVELS 10
const char trans[LEVELS] = " .':~*=&%#";
int main(void)
{
FILE* fp;
int picIn[ROWS][COLS];
char picOut[ROWS][COLS + 1];
char fname[41];
int i, j;
printf("Enter the filename: ");
scanf("%40s", fname);
// 打开数据文件
if ((fp = fopen(fname, "r")) == NULL)
{
fprintf(stderr, "Can't open %s\n", fname);
exit(EXIT_FAILURE);
}
// 读取数据
for (i = 0; i < ROWS; i++)
for (j = 0; j < COLS; j++)
fscanf(fp, "%d", &picIn[i][j]);
if (ferror(fp))
{
fprintf(stderr, "Error getting data from file\n");
exit(EXIT_FAILURE);
}
// 将数字转换成字符
for (i = 0; i < ROWS; i++)
for (j = 0; j < COLS; j++)
picOut[i][j] = trans[picIn[i][j]];
for (i = 0; i < ROWS; i++)
picOut[i][COLS] = '\0';
// 显示字符图片
for (i = 0; i < ROWS; i++)
puts(picOut[i]);
// 将字符图片保存在原文件中,并关闭文件
fclose(fp);
if ((fp = fopen(fname, "w")) == NULL)
{
fprintf(stderr, "Can't open %s\n", fname);
exit(EXIT_FAILURE);
}
for (i = 0; i < ROWS; i++)
fprintf(fp, "%s\n", picOut[i]);
fclose(fp);
return 0;
}
第13题
// 本人IDE不支持变长数组,无法编译
#include <stdio.h>
#include <stdlib.h>
#define LEVELS 10
const char trans[LEVELS] = " .':~*=&%#";
int main(void)
{
FILE* fp;
int rows = 20;
int cols = 30;
int picIn[rows][cols];
char picOut[rows][cols + 1];
char fname[41];
int i, j;
printf("Enter the filename: ");
scanf("%40s", fname);
// 打开数据文件
if ((fp = fopen(fname, "r")) == NULL)
{
fprintf(stderr, "Can't open %s\n", fname);
exit(EXIT_FAILURE);
}
// 读取数据
for (i = 0; i < rows; i++)
for (j = 0; j < cols; j++)
fscanf(fp, "%d", &picIn[i][j]);
if (ferror(fp))
{
fprintf(stderr, "Error getting data from file\n");
exit(EXIT_FAILURE);
}
// 将数字转换成字符
for (i = 0; i < rows; i++)
for (j = 0; j < cols; j++)
picOut[i][j] = trans[picIn[i][j]];
for (i = 0; i < rows; i++)
picOut[i][cols] = '\0';
// 显示字符图片
for (i = 0; i < rows; i++)
puts(picOut[i]);
// 将字符图片保存在原文件中,并关闭文件
fclose(fp);
if ((fp = fopen(fname, "w")) == NULL)
{
fprintf(stderr, "Can't open %s\n", fname);
exit(EXIT_FAILURE);
}
for (i = 0; i < rows; i++)
fprintf(fp, "%s\n", picOut[i]);
fclose(fp);
return 0;
}
第14题
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#define ROWS 20
#define COLS 30
#define LEVELS 10
const char trans[LEVELS] = " .':~*=&%#";
void eli_distortion(int data[][COLS], int row);
int main(void)
{
FILE* fp;
int picIn[ROWS][COLS];
char picOut[ROWS][COLS + 1];
char fname[41];
int i, j;
printf("Enter the filename: ");
scanf("%40s", fname);
// 打开数据文件
if ((fp = fopen(fname, "r")) == NULL)
{
fprintf(stderr, "Can't open %s\n", fname);
exit(EXIT_FAILURE);
}
// 读取数据
for (i = 0; i < ROWS; i++)
for (j = 0; j < COLS; j++)
fscanf(fp, "%d", &picIn[i][j]);
if (ferror(fp))
{
fprintf(stderr, "Error getting data from file\n");
exit(EXIT_FAILURE);
}
// 消除失真
eli_distortion(picIn, ROWS);
// 将数字转换成字符
for (i = 0; i < ROWS; i++)
for (j = 0; j < COLS; j++)
picOut[i][j] = trans[picIn[i][j]];
for (i = 0; i < ROWS; i++)
picOut[i][COLS] = '\0';
// 显示字符图片
for (i = 0; i < ROWS; i++)
puts(picOut[i]);
// 将字符图片保存在原文件中,并关闭文件
fclose(fp);
if ((fp = fopen(fname, "w")) == NULL)
{
fprintf(stderr, "Can't open %s\n", fname);
exit(EXIT_FAILURE);
}
for (i = 0; i < ROWS; i++)
fprintf(fp, "%s\n", picOut[i]);
fclose(fp);
return 0;
}
void eli_distortion(int data[][COLS], int row)
{
int i, j;
int up, down, left, right;
int sum;
int ct;
for (i = 0; i < row; i++)
for (j = 0; j < COLS; j++)
{
sum = ct = 0;
up = down = left = right = 1;
if (i > 0) // 上有相邻
{
up = abs(data[i][j] - data[i - 1][j]) > 1 ? 1 : 0;
sum += data[i - 1][j];
ct++;
}
if (i < row - 1) // 下有相邻
{
down = abs(data[i][j] - data[i + 1][j]) > 1 ? 1 : 0;
sum += data[i + 1][j];
ct++;
}
if (j > 0) // 左有相邻
{
left = abs(data[i][j] - data[i][j - 1]) > 1 ? 1 : 0;
sum += data[i][j - 1];
ct++;
}
if (j < COLS - 1) // 右有相邻
{
right = abs(data[i][j] - data[i][j + 1]) > 1 ? 1 : 0;
sum += data[i][j + 1];
ct++;
}
if (up && down && left && right)
data[i][j] = (int)(1.0 * sum / ct + 0.5); // 四舍五入为整数
}
}