Printf не печатает - возвращает NULL - PullRequest
0 голосов
/ 16 июня 2019

новичок здесь. Поэтому я пытаюсь написать код, который принимает предложение и возвращает самое длинное слово. Когда я отлаживаю программу, все выглядит правильно, как я и ожидал, включая массив символов. Однако, когда я прихожу распечатать вывод, я неизменно получаю NULL ...

Я вставил весь код, потому что я думаю, что один из циклов должен каким-то образом влиять на указатель строки массива?

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

void LongestWord(char sen1[500]) {
/*
steps:
1. char pointer.  Each Byte holds array position of each space or return            value  Note space = 32 & return = 10.

2.  Once got above asses biggest word.  Biggest word stored in short int (starting position)
3.  Once got biggest word start - move to sen using strncpy
*/

char sen[500];
char *ptr = sen;
int i = 0;
int space_position[500];
int j = 0;
int k = 0;
int word_size_prior_to_each_position[500];
int l = 0;
int largest = 0;
int largest_end_position = 0;
int largest_start_position =0;

memset(&sen[0], 0, 500);
memset(&space_position[0], 0, 2000);
memset(&word_size_prior_to_each_position[0], 0, 2000);


while (i < 500) { //mark out where the spaces or final return is
if ((sen1[i] == 0b00100000) ||
     (sen1[i] == 0b00001010))
        {
space_position[j] = i;
j = j+1;
}
i = i+1;
}

while (k < 500) {
 if (k == 0) {
    word_size_prior_to_each_position[k] = (space_position[k]);
 }

                    //calculate word size at each position
if ((k > 0) && (space_position[k] != 0x00)) {
    word_size_prior_to_each_position[k] = (space_position[k] -   space_position[k-1]) -1;
    }
k = k+1;
}

while (l < 500) {       //find largest start position
if (word_size_prior_to_each_position[l] > largest) {
    largest = word_size_prior_to_each_position[l];
    largest_end_position = space_position[l];
    largest_start_position = space_position[l-1];

}
l = l+1;
}

strncpy(ptr, sen1+largest_start_position+1, largest);

printf("%s", *ptr);

return 0;
}

int main(void) {
char stringcapture[500];
fgets(stringcapture, 499, stdin);
LongestWord(stringcapture);       //this grabs input and posts into the     longestword function
return 0;
}

Ответы [ 2 ]

2 голосов
/ 16 июня 2019

В функции LongestWord замените

printf("%s", *ptr);

на

printf("%s\n", ptr);

*ptr обозначает один символ, но вы хотите напечатать строку (см. Спецификацию% s), поэтомуВы должны использовать ptr вместо.Имеет смысл также добавить разрыв строки (\ n).

Также удалите

return 0; 

, потому что это пустая функция.

Возвращение самого длинного слова

Для возвратасамое длинное слово из функции в качестве указателя на символ, вы можете изменить сигнатуру функции на

char *LongestWord(char sen1[500])

Поскольку ваш указатель ptr указывает на локальный массив в LongestWord, это приведет к зависанию ссылки, как только функциявозвращает.

Поэтому вам нужно сделать что-то вроде:

return strdup(ptr);

Затем в основном вы можете изменить свой код на:

char *longest_word = LongestWord(stringcapture);
printf("%s\n", longest_word);
free(longest_word);

Еще несколько подсказок

У вас есть объявление

int space_position[500];

Там вы звоните:

memset(&space_position[0], 0, 2000);

Здесь вы предполагаете, что int равен 4 байта.Это предположение приводит к непереносимому коду.

Вы должны использовать:

memset(&space_position[0], 0, sizeof(space_position));

Вы даже можете написать:

memset(space_position, 0, sizeof(space_position));

, так как space_position в любом случае является адресом массива.

Применительно к вашим memsets, это будет выглядеть так:

memset(sen, 0, sizeof(sen));
memset(space_position, 0, sizeof(space_position));
memset(word_size_prior_to_each_position, 0, sizeof(word_size_prior_to_each_position));

Вместо использования двоичных чисел для пробела и возврата, вы можете альтернативно использовать, вероятно, более читаемую запись '' и'\ n', чтобы вы могли, например, написать:

if ((sen1[i] == ' ') ||
    (sen1[i] == '\n'))

вместо

if ((sen1[i] == 0b00100000) ||
    (sen1[i] == 0b00001010))

Переменная large_end_position назначается, но нигде не используется.Так что его можно удалить.

Следующая строка

strncpy(ptr, sen1 + largest_start_position + 1, largest);

пропустит первую букву слова, если первое слово будет также самым длинным.Кажется, large_start_position - это позиция пробела, но в случае первого слова (most_start_position == 0) вы начинаете копировать из индекса 1. Этот особый случай необходимо обработать.

У вас есть локальный массивв основном то, что не инициализировано.Поэтому вместо

char stringcapture[500];

вы должны написать

char stringcapture[500];
memset(stringcapture, 0, sizeof(stringcapture));

или вы можете использовать:

char stringcapture[500] = {0};

Наконец, в этой строке:

largest_start_position = space_position[l - 1];

Вы получаете доступ к массиву за пределами границ, если l == 0 (space_position [-1]).Поэтому вы должны написать:

if (l > 0) {
    largest_start_position = space_position[l - 1];
}
else {
    largest_start_position = 0;
}
0 голосов
/ 17 июня 2019

Хотя Стефан предоставил вам хороший ответ на проблемы, с которыми вы столкнулись при реализации функции LongestWord, вы, возможно, слишком усложняете то, что делаете, чтобы найти самое длинное слово.

Чтобы быть полезным, подумайте о том, что вам нужно знать, получая самое длинное слово из предложения. Вы хотите знать (1) какое слово самое длинное; и (2) сколько символов оно содержит? Вы всегда можете вызвать strlen снова, когда функция вернется, но почему? Вы уже обработали эту информацию в функции, так что вы могли бы также сделать эту информацию доступной обратно в вызывающей стороне.

Вы можете написать свою функцию несколькими способами, чтобы либо вернуть длину самого длинного слова, либо указатель на самое длинное слово, и т. Д. Если вы хотите вернуть указатель на самое длинное слово, вы можете либо передать массив достаточного размера в качестве параметра функции для заполнения внутри функции, или вы можете динамически распределять хранилище внутри функции так, чтобы хранилище сохранилось после возврата функции ( выделено длительности хранения стихи автоматическое срок хранения). Вы также можете объявить массив static и таким образом сохранить хранилище, но это ограничит вас одним использованием функции в любом одном выражении. Если вы возвращаете указатель на самое длинное слово, чтобы также сделать длину доступной обратно в вызывающей стороне, вы можете передать указатель в качестве параметра и обновить значение по этому адресу в вашей функции, сделав длину доступной обратно в вызывающей функции.

До тех пор, пока вы просто ищете самое длинное слово, самое длинное слово в словаре без ограничений (немедицинское) составляет 29 символов (с общим объемом хранения 30 символов), или для медицинских терминов самое длинное слово - 45- персонаж (всего 46 символов) Поэтому может иметь смысл просто передать массив для заполнения самым длинным словом в качестве параметра, поскольку вы уже знаете, какой будет максимальная длина (достаточно массива из 64 символов - или вдвое больше, чтобы не экономить на размер буфера, ваш звонок).

Вместо того, чтобы использовать несколько массивов, простой цикл и пара указателей - все, что вам нужно, чтобы пройтись по буферу предложений, заключив в скобки начало и конец каждого слова, чтобы выбрать самое длинное. (и преимущество, в отличие от использования strtok и т. д., заключается в том, что исходное предложение остается неизменным, что позволяет ему быть переданным как const char *, позволяя компилятору дополнительно оптимизировать код)

Функция longest_word, которая передает предложение и слово для заполнения в качестве параметров, возвращающих длину самой длинной строки, довольно просто сделать в одном цикле. Слабое название State Loop , где вы используете простой флаг для отслеживания вашего состояния чтения, т. Е. Являетесь ли вы in словом в предложении или находитесь ли вы в пробеле до, между или после слов в предложении. Простой государственный флаг In / Out.

Затем вы просто используете указатель p, чтобы найти начало каждого слова, и указатель конца ep, чтобы продвинуться вниз по предложению, чтобы найти конец каждого слова, проверяя слово с максимальной длиной как вы идете. Вы можете использовать макрос isspace(), предоставленный в ctype.h, чтобы найти пробелы между каждым словом.

Сам цикл постоянно выполняет только цикл, пока вы отслеживаете каждый указатель, а затем проверяете, какое слово самое длинное, с помощью простой разницы указателей ep - p, когда найден конец каждого слова. Если слово длиннее предыдущего max, скопируйте его в самый длинный массив слов и обновите max новой максимальной длиной.

Короткая реализация может быть похожа на:

size_t longest_word (const char *sentence, char *word)
{
    const char *p = sentence, *ep = p;  /* pointer & end-pointer */
    size_t in = 0, max = 0;             /* in-word flag & max len */

    if (!sentence || !*sentence)        /* if NULL or empty, set word empty */
        return (*word = 0);

    for (;;) {                          /* loop continually */
        if (isspace (*ep) || !*ep) {    /* check whitespace & end of string */
            if (in) {                   /* if in-word */
                size_t len = ep - p;    /* get length */
                if (len > max) {        /* if greater than max */
                    memcpy (word, p, len);  /* copy to word */
                    word[len] = 0;      /* nul-terminate word */
                    max = len;          /* update max */
                }
                p = ep;                 /* update pointer to end-pointer */
                in = 0;                 /* zero in-word flag */
            }
            if (!*ep)                   /* if end of word, bail */
                break;
        }
        else {          /* non-space character */
            if (!in) {                  /* if not in-word */
                p = ep;                 /* update pointer to end-pointer */
                in = 1;                 /* set in-word flag */
            }
        }
        ep++;           /* advance end-pointer */
    }

    return max;         /* return max length */
}

Полный пример, в котором предложение читается как ввод пользователя, может быть похож на:

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

#define MAXWRD   64     /* longest word size */
#define MAXC   2048     /* max characters in sentence */

size_t longest_word (const char *sentence, char *word)
{
    const char *p = sentence, *ep = p;  /* pointer & end-pointer */
    size_t in = 0, max = 0;             /* in-word flag & max len */

    if (!sentence || !*sentence)        /* if NULL or empty, set word empty */
        return (*word = 0);

    for (;;) {                          /* loop continually */
        if (isspace (*ep) || !*ep) {    /* check whitespace & end of string */
            if (in) {                   /* if in-word */
                size_t len = ep - p;    /* get length */
                if (len > max) {        /* if greater than max */
                    memcpy (word, p, len);  /* copy to word */
                    word[len] = 0;      /* nul-terminate word */
                    max = len;          /* update max */
                }
                p = ep;                 /* update pointer to end-pointer */
                in = 0;                 /* zero in-word flag */
            }
            if (!*ep)                   /* if end of word, bail */
                break;
        }
        else {          /* non-space character */
            if (!in) {                  /* if not in-word */
                p = ep;                 /* update pointer to end-pointer */
                in = 1;                 /* set in-word flag */
            }
        }
        ep++;           /* advance end-pointer */
    }

    return max;         /* return max length */
}

int main (void) {

    char buf[MAXC], word[MAXWRD];
    size_t len;

    if (!fgets (buf, MAXC, stdin)) {
        fputs ("error: user canceled input.\n", stderr);
        return 1;
    }

    len = longest_word (buf, word);

    printf ("longest: %s (%zu-chars)\n", word, len);

    return 0;
}

Пример использования / Вывод

Введенная строка имеет 2-символьные пробелы в начале, а также 2-символьные пробелы:

$ ./bin/longest_word
  1234 123 12 123456 1234 123456789 12345678 1 1234
longest: 123456789 (9-chars)

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...