Язык программирования C (K&R) ex1-20 . Я сталкиваюсь с некоторыми проблемами
/*
* 1-20. Write a program detab that replaces tabs in the input with the proper number
* of blanks to space to the next tab stop. Assume a fixed set of tab stops, say every n columns.
* Should n be a variable or a symbolic parameter?
*
*/
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#define N 4
void detab(char **str);
int main(){
char *line=NULL;
char *newline;
int len;
while(getline(&line,&len,stdin)!=-1){
detab(&line);
printf("%s",line);
}
free(line);
return 0;
}
void detab(char **str){
int len=0,num=0;
int i=0;
char c;
while((c=(*str)[i])!='\0'){
if(c=='\t'){ // get the number of tab
num++;
}
len++; // get length of string
i++;
}
char *newline;
newline=(char *)malloc(len+(N-1)*num+1); //use four blank replace one tab
if(newline==NULL){
fprintf(stderr,"can't malloc space\n");
}
i=0;
int j=0; //index of newline
while((c=(*str)[i])!='\0'){
if(c=='\t'){
int k;
for(k=0;k<N;k++){
newline[j]=' ';
++j;
}
}
else{
newline[j]=c;
++j;
}
++i;
}
newline[j]='\0';
free(*str);
*str=newline;
}
Когда я ввожу короткую строку, она работает правильно, но если я ввожу длинную строку, возможно, из 50 символов, она говорит это:
*** Error in `./a.out': free(): invalid next size (fast): 0x0961b068 ***
Aborted (core dumped)
Я застрял здесь почти три часа. Пожалуйста, помогите мне.
Это работает хорошо, если я пытаюсь использовать один указатель, например так:
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#define N 4
char* detab(char *str);
int main(){
char *line=NULL;
char *newline;
int len;
while(getline(&line,&len,stdin)!=-1){
newline = detab(line);
printf("%s",newline);
free(newline);
}
free(line);
return 0;
}
char* detab(char *str){
int len=0,num=0;
int i=0;
char c;
while((c=str[i])!='\0'){
if(c=='\t'){
num++;
}
len++;
i++;
}
char *newline;
newline=(char *)malloc(len+(N-1)*num+1); //use four blank replace one tab
if(newline==NULL){
fprintf(stderr,"can't malloc space\n");
}
i=0;
int j=0; //index of newline
while((c=str[i])!='\0'){
if(c=='\t'){
int k;
for(k=0;k<N;k++){
newline[j]=' ';
++j;
}
}
else{
newline[j]=str[i];
++j;
}
++i;
}
newline[j]='\0';
return newline;
}
2 ответа
Я решил проблему 1_20, прочитав каждую строку ввода в двусвязный список. Каждый узел в списке представляет один символ строки в последовательности.
После создания связанного списка я удаляю пробел в конце списка, т.е. в конце строки.
Затем я прохожу связанный список, сканирую вкладки, сохраняя количество столбцов на ходу.
Когда я сталкиваюсь с вкладкой, я отмечаю номер ее столбца и вычисляю, сколько пробелов мне нужно до следующей остановки табуляции. Формула:
tabstop = ((col + (m-1)) / m) * m;
где:
tabstop
это следующая вкладкаm
это расстояние между вкладкамиcol
столбец, в котором находится вкладка
Я заменяю вкладку пробелом и вставляю новые узлы с единичными пробелами в связанный список, пока не достигну следующей остановки табуляции.
Я продолжаю идти по связанному списку из столбца табуляции, ищу следующий символ табуляции и повторяю процесс конвертации.
Как только я достигаю конца связанного списка, я распечатываю его как строку вывода.
Использование двусвязного списка может показаться утомительным, но это значительно упрощает логику main()
функция в программе.
main()
функция говорит:
while (not end of file)
{
getline()
remove_final_white_space()
convert_tabs_to_spaces()
putline()
}
getline()
Функция создает связанный список с символами табуляции.
putline()
Функция очищает связанный список, печатая по одному символу за раз.
Хорошо, во-первых:
Подумайте о том, что вы прочитали до сих пор можно использовать только
Вы не можете использовать указатели и функции вне области видимости, такие как
malloc()
Этот ex1-20 предназначен для использования только того, что вы уже изучили, поэтому не усложняйте вещи.
ex1-20:
#include <stdio.h>
#define MAXLINE 1000
void getendtab(char s[],int lim,int n){
int c, i;
i=0;
while((c = getchar()) != EOF){
if( c == '\t'){
while( n != 0){
s[i] = ' ';
i++;
n--;
}
n = 3;
}else{s[i] = c; i++;}
}
}
int main(){
int n = 3;
int len;
char bytes[MAXLINE] = {0};
getendtab(bytes,MAXLINE,n);
printf("%s",bytes);
return 0;
}