Язык программирования 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;
}
Другие вопросы по тегам