Палка с 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;
}
символ «\ п» по-прежнему остается в буфере, поэтому ур 2-й fgets не в состоянии захватить 2-й линии ввода. – Mox
Вы пытались использовать char input1 [100] вместо этого? – brijs
использование sizeof (input1) неверно, он не даст u 100, вместо этого он просто даст ua размер 1. – Mox