2016-11-04 2 views
3

Я пытаюсь создать программу, которая берет две строки и заполняет матрицу редактирования расстояния для них. Вещь, которая меня отключает, для второго ввода строки пропускает второй вход. Я попытался очистить буфер с помощью getch(), но это не сработало. Я также попытался переключиться на scanf(), но это также привело к некоторым сбоям. Помоги пожалуйста!Редактировать матрицу расстояний

Код:

#include <stdio.h> 
#include <stdlib.h> 

int min(int a, int b, int c){ 
    if(a > b && a > c) 
     return a; 
    else if(b > a && b > c) 
     return b; 
    else 
     return c; 
} 

int main(){ 

    // allocate size for strings 
    int i, j; 
    char *input1 = (char*)malloc(sizeof(char)*100); 
    char *input2 = (char*)malloc(sizeof(char)*100); 

    // ask for input 
    printf("Enter the first string: "); 
    fgets(input1, sizeof(input1), stdin); 
    printf("\nEnter the second string: "); 
    fgets(input2, sizeof(input2), stdin); 

    // make matrix 
    int len1 = sizeof(input1), len2 = sizeof(input2); 
    int c[len1 + 1][len2 + 1]; 

    // set up input 2 length 
    for(i = 0; i < len2 + 1; i++){ 
     c[0][i] = i; 
    } 

    // set up input 1 length 
    for(i = 0; i < len1 + 1; i++){ 
     c[i][0] = i; 
    } 

    // fill in the rest of the matrix 
    for(i = 1; i < len1; i++){ 
     for(j = 1; j < len2; j++){ 
      if(input1[i] == input2[j]) // if the first letters are equal make the diagonal equal to the last 
       c[i][j] = c[i - 1][j - 1]; 
      else 
       c[i][j] = 1 + min(c[i - 1][j - 1], c[i - 1][j], c[i][j - 1]); 
     } 
    } 

    // print the matrix 
    printf("\n"); 
    for(j = 0; j < len2; j++){ 
     for(i = 0; i < len1; i++){ 
      printf("| %d", c[i][j]); 
     } 
     printf("\n"); 
    } 

    return 1; 
} 
+1

символ «\ п» по-прежнему остается в буфере, поэтому ур 2-й fgets не в состоянии захватить 2-й линии ввода. – Mox

+2

Вы пытались использовать char input1 [100] вместо этого? – brijs

+1

использование sizeof (input1) неверно, он не даст u 100, вместо этого он просто даст ua размер 1. – Mox

ответ

1

Палка с fgets.

Как уже отмечалось, использовать char input1[100] вместо char *input1 = malloc(...)

Но даже с этим изменением, что делает sizeof внутри из fgets правильно, используя sizeof при настройке len1 и len2 неправильно. Вы будете обрабатывать весь буфер, даже если в нем всего 10 действительных символов (т. Е. Остальные не определены/случайны).

Что вы [вероятно] хотите, это strlen [и полоса новой полосы], чтобы получить фактическую полезную длину.

Вот измененный код [простите пожалуйста безвозмездную ыборку стиля]:

#include <stdio.h> 
#include <stdlib.h> 
#include <string.h> 

int 
min(int a, int b, int c) 
{ 
    if (a > b && a > c) 
     return a; 
    if (b > a && b > c) 
     return b; 
    return c; 
} 

int 
main(void) 
{ 

    // allocate size for strings 
    int i; 
    int j; 
    char input1[100]; 
    char input2[100]; 

    // ask for input 
    printf("Enter the first string: "); 
    fgets(input1, sizeof(input1), stdin); 
    int len1 = strlen(input1); 
    if (input1[len1 - 1] == '\n') { 
     input1[len1 - 1] = 0; 
     --len1; 
    } 

    printf("\nEnter the second string: "); 
    fgets(input2, sizeof(input2), stdin); 
    int len2 = strlen(input2); 
    if (input2[len2 - 1] == '\n') { 
     input2[len2 - 1] = 0; 
     --len2; 
    } 

    // make matrix 
    int c[len1 + 1][len2 + 1]; 

    // set up input 2 length 
    for (i = 0; i < len2 + 1; i++) { 
     c[0][i] = i; 
    } 

    // set up input 1 length 
    for (i = 0; i < len1 + 1; i++) { 
     c[i][0] = i; 
    } 

    // fill in the rest of the matrix 
    for (i = 1; i < len1; i++) { 
     for (j = 1; j < len2; j++) { 
      // if the 1st letters are equal make the diagonal equal to the last 
      if (input1[i] == input2[j]) 
       c[i][j] = c[i - 1][j - 1]; 
      else 
       c[i][j] = 1 + min(c[i - 1][j - 1], c[i - 1][j], c[i][j - 1]); 
     } 
    } 

    // print the matrix 
    printf("\n"); 
    for (j = 0; j < len2; j++) { 
     for (i = 0; i < len1; i++) { 
      printf("| %d", c[i][j]); 
     } 
     printf("\n"); 
    } 

    return 1; 
} 

UPDATE:

Хорошо сладким Я понимаю, что вы имеете в виду! Причина, по которой я пыталась использовать malloc, заключалась в том, чтобы избежать создания матрицы, которую я должен был напечатать размером в 100x100 пробелов.

При использовании любого фиксированного размера input1 или malloc ред один, fgets будет только заполнить его до размера входного введен [обрезается до второго аргумента, если необходимо]. Но, это не pad/заполнить остаток буфера что-нибудь (например, пробелы справа). Что это такое делает do - это добавить символ EOS [end-of-string] [который является двоичным 0x00] после последнего символа, считанного с ввода [который обычно является символом новой строки].

Таким образом, если входной является строка: abcdef\n, длина [получен из strlen] 7, вход [7] будет 0x00 и input1[8] через input1[99] будут иметь неопределенные/случайные/непредсказуемые значения и не пространства.

Поскольку символ новой строки не очень полезен, его часто удаляют перед дальнейшей обработкой. Например, это не очень важно при вычислении расстояния редактирования для небольшой фразы.

Использует ли strlen() только количество символов внутри массива или включает в себя все пробелы?

Как я уже упоминал выше, fgets делает не пэд струны в конце, так, чтобы не волноваться. Он будет делать то, что вы хотите/ожидаете.

strlen только считает символы до [но не включая символ терминатора EOS (т. Е.) Ноль]. Если некоторые из этих символов представляют собой пробелы, они будут быть учтены strlen - это то, что мы хотим.

Рассмотрим вычисления расстояния редактирования между любыми двумя из следующих фраз:

quick brown fox jumped over the lazy dogs 
the quick brown fox jumped over lazy dogs 
quick brown fox jumps over the lazy dog 

В каждом случае мы хотим strlen включать [внутренние/встроенные] пробелы в расчете длины. Это потому, что он is отлично подходит для вычисления расстояния редактирования фразы.


Существует действительное использование для malloc: когда объем данных слишком велик, чтобы поместиться в стеке. Большинство систем имеют ограничение по умолчанию (например, под Linux, это 8 МБ).

Предположим, что мы вычисления расстояния редактирования для двух глав книги [читать из файлов], мы должны были бы (например):

char input1[50000]; 
char input2[50000]; 

выше будет соответствовать, но c матрица может вызвать переполнение стека :

int c[50000][50000]; 

, так как размер этого будет 50000 * 50000 * 4, которая составляет примерно 9,3 Гб.

Итак, чтобы соответствовать всем этим данным, нам нужно выделить его в кучу. Хотя можно сделать malloc для cи поддерживать двумерный доступ к матрице, нам нужно было бы создать функцию и передать указатель на c.

Итак, вот модифицированная версия, которая принимает данные сколь угодно больших размеров:

#include <stdio.h> 
#include <stdlib.h> 
#include <errno.h> 
#include <string.h> 

#define sysfault(_fmt...) \ 
    do { \ 
     fprintf(stderr,_fmt); \ 
     exit(1); \ 
    } while (0) 

#define C(y,x)  c[((y) * (len2 + 1)) + (x)] 

long 
min(long a, long b, long c) 
{ 
    if (a > b && a > c) 
     return a; 
    if (b > a && b > c) 
     return b; 
    return c; 
} 

char * 
input(const char *prompt,long *lenp,const char *file) 
{ 
    FILE *fp; 
    char *lhs; 
    int chr; 
    long siz; 
    long len; 

    if (file != NULL) 
     fp = fopen(file,"r"); 
    else { 
     fp = stdin; 
     printf("Enter %s string: ",prompt); 
     fflush(stdout); 
    } 

    lhs = NULL; 
    siz = 0; 
    len = 0; 

    while (1) { 
     chr = fgetc(fp); 
     if (chr == EOF) 
      break; 

     if ((chr == '\n') && (file == NULL)) 
      break; 

     // grow the character array 
     if ((len + 1) >= siz) { 
      siz += 100; 
      lhs = realloc(lhs,siz); 
      if (lhs == NULL) 
       sysfault("input: realloc failure -- %s\n",strerror(errno)); 
     } 

     lhs[len] = chr; 
     len += 1; 
    } 

    if (file != NULL) 
     fclose(fp); 

    if (lhs == NULL) 
     sysfault("input: premature EOF\n"); 

    // add the EOS 
    lhs[len] = 0; 

    // return the length to the caller 
    *lenp = len; 

    return lhs; 
} 

int 
main(int argc,char **argv) 
{ 
    long i; 
    long j; 
    char *input1; 
    long len1; 
    char *input2; 
    long len2; 
    long *c; 

    --argc; 
    ++argv; 

    switch (argc) { 
    case 2: 
     input1 = input("first",&len1,argv[0]); 
     input2 = input("second",&len2,argv[1]); 
     break; 
    default: 
     input1 = input("first",&len1,NULL); 
     input2 = input("second",&len2,NULL); 
     break; 
    } 

    // make matrix 
    c = malloc(sizeof(*c) * (len1 + 1) * (len2 + 1)); 
    if (c == NULL) 
     sysfault("main: malloc failure -- %s\n",strerror(errno)); 

    // set up input 2 length 
    for (i = 0; i < len2 + 1; i++) { 
     C(0,i) = i; 
    } 

    // set up input 1 length 
    for (i = 0; i < len1 + 1; i++) { 
     C(i,0) = i; 
    } 

    // fill in the rest of the matrix 
    for (i = 1; i < len1; i++) { 
     for (j = 1; j < len2; j++) { 
      // if the 1st letters are equal make the diagonal equal to the last 
      if (input1[i] == input2[j]) 
       C(i,j) = C(i - 1,j - 1); 
      else 
       C(i,j) = 1 + min(C(i - 1,j - 1), C(i - 1,j), C(i,j - 1)); 
     } 
    } 

    // print the matrix 
    printf("\n"); 
    for (j = 0; j < len2; j++) { 
     for (i = 0; i < len1; i++) { 
      printf("| %ld", C(i,j)); 
     } 
     printf("\n"); 
    } 

    return 1; 
} 
Смежные вопросы