繁体   English   中英

Printf不打印-返回NULL

[英]Printf not printing - returns NULL

这里的初学者。 因此,我正在尝试编写一些包含句子并返回最长单词的代码。 当我调试程序时,一切看起来都正确,包括char数组。 但是,当我来打印输出时,我总是得到一个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;
}

在函数LongestWord中替换

printf("%s", *ptr);

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

*ptr表示单个字符,但是您要打印一个字符串(请参见%s规范),因此必须改用ptr 也可以添加一个换行符(\\ n)。

同时删除

return 0; 

在那里,因为它是一个空函数。

返回最长的单词

要将函数中最长的单词返回为char的指针,可以将函数签名更改为

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仍然是数组的地址。

应用于您的记忆集,它将如下所示:

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))

变量maximum_end_position已分配,但从未在某处使用。 因此可以将其删除。

下一行

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

如果第一个单词也最长,则会省略该单词的第一个字母。 似乎maximum_start_position是该空间的位置,但是在第一个单词(largest_start_position == 0)的情况下,您将从索引1开始复制。需要处理这种特殊情况。

您在main中有一个未初始化的本地数组。 所以代替

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;
}

虽然Stephan为您提供了一个很好的答案,以解决您在实现LongestWord函数时遇到的问题,但您可能会为寻找最长的单词而过度复杂。

为了有用,请考虑从句子中获取最长单词时需要了解的内容。 您想知道(1)最长的单词是什么; (2)它包含几个字符? 您总是可以在函数返回时再次调用strlen ,但是为什么呢? 您将已经在函数中处理了该信息,因此您最好也可以在调用方中使该信息可用。

您可以通过多种方式编写函数,以返回最长单词的长度,或指向最长单词本身的指针,等等。如果要返回指向最长单词的指针,则可以传递一个数组足够大的大小作为要填充到函数中的函数的参数,或者可以在函数内动态分配存储,以使存储在函数返回时幸免( 分配的存储持续时间与自动存储持续时间之比)。 您还可以声明一个数组为static数组并以此方式保留存储,但这将使您只能在任何一个表达式中使用该函数。 如果返回指向最长单词的指针,以使长度也可以在调用方中返回,则可以将指针作为参数传递,并在函数中更新该地址处的值,以使长度在调用函数中可用。

只要您只是在寻找最长的单词,未删节词典中的最长单词(非医学)就是29个字符(总共存储30个字符),医学术语中最长的单词是45个字符(总共46个字符)。 因此,简单地传递一个数组以填充最长的单词作为参数可能更有意义,因为您已经知道所需的最大长度是多少(64个字符的数组就足够了,或者将其加倍以免跳过缓冲区大小,请致电)。

只需使用一个简单的循环和一对指针,而不是使用多个数组,您只需沿着句子缓冲区步行,并用括号括起来每个单词的开头和结尾以挑选最长的单词。 (与使用strtok等相反,这样做的好处是使原始句子保持不变,允许将其作为const char *传递,从而允许编译器进一步优化代码)

一个longest_word函数可以直接将句子和单词填充为参数,以返回最长字符串的长度,这很容易在一个循环中完成。 松散地称为“ 状态循环” ,您可以在其中使用一个简单的标志来跟踪您的读取状态,即您是否in句子in某个单词中,或者是在句子in的单词之前,之间还是之后的空格中。 一个简单的输入/输出状态标志。

然后,您只需使用指针p定位每个单词的开头,然后使用端点指针ep向下推动句子以定位每个单词的结尾,并在使用时检查最大长度的单词。 您可以使用ctype.h提供的isspace()宏来定位每个单词之间的空格。

循环本身无非是在跟踪每个指针的同时连续循环,然后在发现每个单词的末尾时通过简单的指针差ep - p检查哪个单词最长。 如果单词长于先前的max ,则将其复制到最长的单词数组,并使用新的max-length更新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)

这并不是要代替Stephan的答案来帮助解决您实施中的紧迫问题,而是为您提供一个替代方法来思考解决问题的示例。 通常,保留任何编码任务越简单,出错的可能性就越小。 查看一下,让我知道您是否对该方法还有其他疑问。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM