K&R 练习 1.21
K&R Exercise 1.21
目前正在努力解决 ex 1.21。任务是:编写一个程序entab,用最少的数字替换空白字符串
制表符和空格以达到相同的间距。使用与 detab 相同的制表位。什么时候
制表符或单个空白足以到达制表位,应该给出
偏好?
以下是我到目前为止编写的代码。我输入小于 tabsize 的空格没有问题,但是当它大于 tabsize 时,我会遇到分段错误。有谁能帮帮我吗?
#include <stdio.h>
#include <ctype.h>
#define TAB 8
#define MAXLINE 1000
int getmine(char s[], int lim);
int entab(char output[], int pos, int space);
int main()
{
char line[MAXLINE], output[MAXLINE];
int i;
while ((i = getmine(line, MAXLINE)) > 0)
{
int space = 0;
int pos = 0;
int count = 0;
while (line[count] != '\n')
{
if (line[count] != ' ')
{
space = 0;
output[count] = line[count];
}
else if (line[count] == ' ')
{
pos = count - space;
space++;
if (line[count + 1] != ' ')
{
if (space > TAB)
{
int z = entab(output, pos, space);
count = z;
}
else
{
for (int a = 0; a < space; a++)
output[pos + a] = ' ';
}
}
}
count++;
}
if (line[count] == '\n')
{
output[count] = line[count];
count++;
}
output[count] = '[=10=]';
printf("%s", output);
}
}
int getmine(char s[],int lim)
{
int c, i;
for (i=0; i < lim-1 && (c=getchar())!=EOF && c!='\n'; ++i)
s[i] = c;
if (c == '\n')
{
s[i] = c;
++i;
}
s[i] = '[=10=]';
return i;
}
int entab(char output[], int pos, int space)
{
int nTabs = 0;
int nSpaces = 0;
int x = TAB - (pos % TAB);
if (x > 0)
{
output[pos] = '\t';
space = space - x;
nTabs = space / TAB;
nSpaces = space % TAB;
for (int a = 0; a < nTabs; a++)
output[pos + 1 + a] = '\t';
for (int b = 0; b < nSpaces; b++)
output[pos + 1 + nTabs + b] = ' ';
return pos + nTabs + nSpaces + 1;
}
else if (x == 0)
{
nTabs = space / TAB;
nSpaces = space % TAB;
for (int a = 0; a < nTabs; a++)
output[pos + a] = '\t';
for (int b = 0; b < nSpaces; b++)
output[pos + nTabs + b] = ' ';
return pos + nTabs + nSpaces;
}
}
因为 8 个字符的空白序列被单个字符(制表符)替换,所以从输入中读取的字节数与输出中写入的字节数不匹配。一个简单的解决方案是简单地跟踪两个变量,一个用于从输入读取的字节,一个用于写入输出的字节。你可以用指针来做一些更整洁的事情,但如果你以线性方式阅读这本书,稍后会介绍 IIRC 指针。
下面的代码未经测试(即用于演示目的)。
注意:为简洁起见,我在重新格式化您的代码时采取了一些自由。
#include <stdio.h>
#include <ctype.h>
#define TAB 8
#define MAXLINE 1000
int getmine(char s[], int lim);
int entab(char output[], int pos, int space);
int main()
{
char line[MAXLINE], output[MAXLINE];
int i;
while ((i = getmine(line, MAXLINE)) > 0) {
int space = 0;
int pos = 0;
int read_bytes = 0;
int write_bytes = 0;
while(read_bytes < i) {
if (line[read_bytes] != ' ') {
space = 0;
output[write_bytes++] = line[read_bytes];
}
else if (line[read_bytes] == ' ') {
space++;
if (line[read_bytes + 1] != ' ') {
if (space > TAB) {
write_bytes += entab(output, write_bytes, space);
} else {
for (int i = 0; i < space; i++)
output[write_bytes++] = ' ';
}
}
}
read_bytes++;
}
if (line[read_bytes] == '\n') {
output[write_bytes++] = line[read_bytes];
}
output[write_bytes] = '[=10=]';
printf("%s", output);
}
}
int getmine(char s[],int lim)
{
int c, i;
for (i=0; i < lim-1 && (c=getchar())!=EOF && c!='\n'; ++i)
s[i] = c;
if (c == '\n') {
s[i] = c;
++i;
}
s[i] = '[=10=]';
return i;
}
int entab(char output[], int pos, int space)
{
int nTabs = 0;
int nSpaces = 0;
int x = TAB - (pos % TAB);
if (x > 0) {
output[pos] = '\t';
space = space - x;
nTabs = space / TAB;
nSpaces = space % TAB;
for (int i = 0; i < nTabs; i++)
output[pos + 1 + i] = '\t';
for (int i = 0; i < nSpaces; i++)
output[pos + 1 + nTabs + i] = ' ';
return nTabs + nSpaces + 1;
} else if (x == 0) {
nTabs = space / TAB;
nSpaces = space % TAB;
for (int i = 0; i < nTabs; i++)
output[pos + i] = '\t';
for (int i = 0; i < nSpaces; i++)
output[pos + nTabs + i] = ' ';
}
return nTabs + nSpaces;
}
在我的解决方案中,我使用外部变量作为输出行的索引计数器。
我制作了用于将输入数组转换为输出数组的分离函数。
#include <stdio.h>
#define TAB 8
#define MAX 100;
int j; //counter of newline
char line[MAX];
char newline[MAX];
int getter(void);
void converter(void);
int entab(int space_counter, int line_index);
int main()
{
extern char line[];
extern char newline[];
int len;
while ((len = getter()) > 0) {
converter();
printf("%s", newline);
}
}
int getter()
{
int c;
int i;
i = 0;
while ((c = getchar()) != EOF && c != '\n' && i < 30-1) {
line[i] = c;
++i;
}
if (c == '\n') {
line[i] = c;
++i;
}
line[i] = '[=10=]';
return i;
}
void converter(void)
{
extern int j;
extern char line[];
extern char newline[];
int space_counter;
int i;
i = j = 0;
space_counter = 0;
while (line[i] != '[=10=]') {
while (line[i] == ' ') {
space_counter++;
i++;
}
if (space_counter > 0) {
j = entab(space_counter, i);
space_counter = 0;
}
else {
newline[j] = line[i];
j++;
i++;
}
}
newline[j] = '[=10=]';
}
int entab(int space_counter, int end_point)
{
extern int j;
extern char newline[];
int new_index;
int start_point;
int tab_qty;
int space_qty;
start_point = end_point - space_counter;
tab_qty = end_point / TAB - start_point / TAB;
if (TAB > start_point)
space_qty = space_counter;
else
space_qty = end_point % TAB;
for (tab_qty; tab_qty > 0; tab_qty--) {
newline[j] = '\t';
j++;
}
for (space_qty; space_qty > 0; space_qty--) {
newline[j] = '|';
j++;
}
return new_index = j;
}
目前正在努力解决 ex 1.21。任务是:编写一个程序entab,用最少的数字替换空白字符串 制表符和空格以达到相同的间距。使用与 detab 相同的制表位。什么时候 制表符或单个空白足以到达制表位,应该给出 偏好?
以下是我到目前为止编写的代码。我输入小于 tabsize 的空格没有问题,但是当它大于 tabsize 时,我会遇到分段错误。有谁能帮帮我吗?
#include <stdio.h>
#include <ctype.h>
#define TAB 8
#define MAXLINE 1000
int getmine(char s[], int lim);
int entab(char output[], int pos, int space);
int main()
{
char line[MAXLINE], output[MAXLINE];
int i;
while ((i = getmine(line, MAXLINE)) > 0)
{
int space = 0;
int pos = 0;
int count = 0;
while (line[count] != '\n')
{
if (line[count] != ' ')
{
space = 0;
output[count] = line[count];
}
else if (line[count] == ' ')
{
pos = count - space;
space++;
if (line[count + 1] != ' ')
{
if (space > TAB)
{
int z = entab(output, pos, space);
count = z;
}
else
{
for (int a = 0; a < space; a++)
output[pos + a] = ' ';
}
}
}
count++;
}
if (line[count] == '\n')
{
output[count] = line[count];
count++;
}
output[count] = '[=10=]';
printf("%s", output);
}
}
int getmine(char s[],int lim)
{
int c, i;
for (i=0; i < lim-1 && (c=getchar())!=EOF && c!='\n'; ++i)
s[i] = c;
if (c == '\n')
{
s[i] = c;
++i;
}
s[i] = '[=10=]';
return i;
}
int entab(char output[], int pos, int space)
{
int nTabs = 0;
int nSpaces = 0;
int x = TAB - (pos % TAB);
if (x > 0)
{
output[pos] = '\t';
space = space - x;
nTabs = space / TAB;
nSpaces = space % TAB;
for (int a = 0; a < nTabs; a++)
output[pos + 1 + a] = '\t';
for (int b = 0; b < nSpaces; b++)
output[pos + 1 + nTabs + b] = ' ';
return pos + nTabs + nSpaces + 1;
}
else if (x == 0)
{
nTabs = space / TAB;
nSpaces = space % TAB;
for (int a = 0; a < nTabs; a++)
output[pos + a] = '\t';
for (int b = 0; b < nSpaces; b++)
output[pos + nTabs + b] = ' ';
return pos + nTabs + nSpaces;
}
}
因为 8 个字符的空白序列被单个字符(制表符)替换,所以从输入中读取的字节数与输出中写入的字节数不匹配。一个简单的解决方案是简单地跟踪两个变量,一个用于从输入读取的字节,一个用于写入输出的字节。你可以用指针来做一些更整洁的事情,但如果你以线性方式阅读这本书,稍后会介绍 IIRC 指针。
下面的代码未经测试(即用于演示目的)。 注意:为简洁起见,我在重新格式化您的代码时采取了一些自由。
#include <stdio.h>
#include <ctype.h>
#define TAB 8
#define MAXLINE 1000
int getmine(char s[], int lim);
int entab(char output[], int pos, int space);
int main()
{
char line[MAXLINE], output[MAXLINE];
int i;
while ((i = getmine(line, MAXLINE)) > 0) {
int space = 0;
int pos = 0;
int read_bytes = 0;
int write_bytes = 0;
while(read_bytes < i) {
if (line[read_bytes] != ' ') {
space = 0;
output[write_bytes++] = line[read_bytes];
}
else if (line[read_bytes] == ' ') {
space++;
if (line[read_bytes + 1] != ' ') {
if (space > TAB) {
write_bytes += entab(output, write_bytes, space);
} else {
for (int i = 0; i < space; i++)
output[write_bytes++] = ' ';
}
}
}
read_bytes++;
}
if (line[read_bytes] == '\n') {
output[write_bytes++] = line[read_bytes];
}
output[write_bytes] = '[=10=]';
printf("%s", output);
}
}
int getmine(char s[],int lim)
{
int c, i;
for (i=0; i < lim-1 && (c=getchar())!=EOF && c!='\n'; ++i)
s[i] = c;
if (c == '\n') {
s[i] = c;
++i;
}
s[i] = '[=10=]';
return i;
}
int entab(char output[], int pos, int space)
{
int nTabs = 0;
int nSpaces = 0;
int x = TAB - (pos % TAB);
if (x > 0) {
output[pos] = '\t';
space = space - x;
nTabs = space / TAB;
nSpaces = space % TAB;
for (int i = 0; i < nTabs; i++)
output[pos + 1 + i] = '\t';
for (int i = 0; i < nSpaces; i++)
output[pos + 1 + nTabs + i] = ' ';
return nTabs + nSpaces + 1;
} else if (x == 0) {
nTabs = space / TAB;
nSpaces = space % TAB;
for (int i = 0; i < nTabs; i++)
output[pos + i] = '\t';
for (int i = 0; i < nSpaces; i++)
output[pos + nTabs + i] = ' ';
}
return nTabs + nSpaces;
}
在我的解决方案中,我使用外部变量作为输出行的索引计数器。 我制作了用于将输入数组转换为输出数组的分离函数。
#include <stdio.h>
#define TAB 8
#define MAX 100;
int j; //counter of newline
char line[MAX];
char newline[MAX];
int getter(void);
void converter(void);
int entab(int space_counter, int line_index);
int main()
{
extern char line[];
extern char newline[];
int len;
while ((len = getter()) > 0) {
converter();
printf("%s", newline);
}
}
int getter()
{
int c;
int i;
i = 0;
while ((c = getchar()) != EOF && c != '\n' && i < 30-1) {
line[i] = c;
++i;
}
if (c == '\n') {
line[i] = c;
++i;
}
line[i] = '[=10=]';
return i;
}
void converter(void)
{
extern int j;
extern char line[];
extern char newline[];
int space_counter;
int i;
i = j = 0;
space_counter = 0;
while (line[i] != '[=10=]') {
while (line[i] == ' ') {
space_counter++;
i++;
}
if (space_counter > 0) {
j = entab(space_counter, i);
space_counter = 0;
}
else {
newline[j] = line[i];
j++;
i++;
}
}
newline[j] = '[=10=]';
}
int entab(int space_counter, int end_point)
{
extern int j;
extern char newline[];
int new_index;
int start_point;
int tab_qty;
int space_qty;
start_point = end_point - space_counter;
tab_qty = end_point / TAB - start_point / TAB;
if (TAB > start_point)
space_qty = space_counter;
else
space_qty = end_point % TAB;
for (tab_qty; tab_qty > 0; tab_qty--) {
newline[j] = '\t';
j++;
}
for (space_qty; space_qty > 0; space_qty--) {
newline[j] = '|';
j++;
}
return new_index = j;
}